这个问题与this问题相似。在
我有一个2d布尔数组“beyond”和一个2d浮点数组“angles”。 我想要的是沿着行求和相应索引所属的角度,并使用numpy(即避免python循环)。我不需要存储结果行,这些行的长度不同,如链接问题中所述,需要一个列表。在
所以我尝试的是np.总和(angles[beyond],axis=1),但是angles[beyond]返回一个1d结果,我不能按我的要求减少它。我也试过了np.总和(角度*属于,轴=1)这样就行了。但是我想知道是否可以通过只访问属于真的索引来改进时间安排。归属是正确的大约30%的时间和角度是一个较长的公式的简化涉及角度。在
更新
我喜欢用einsum的解,但是在我的实际计算中,速度是很小的。我用角度来简化问题,实际上这是一个使用角度的公式。我怀疑这个公式是针对所有的角度(不管属于什么)计算的,然后传递给einsum,它将执行计算。在
这就是我所做的:
THRESθ和max_line_length是浮点数。 属于,角度和线条长度都有形状(1653,58) 以及np.count_非零(属于)/属于。大小->;0.376473287856979
l2 = (lambda angle=angle, belong=belong, THRES_THETA=THRES_THETA, lines_lengths_vstacked=lines_lengths_vstacked, max_line_length=max_line_length:
np.sum(belong*(0.3 * (1-(angle/THRES_THETA)) + 0.7 * (lines_lengths_vstacked/max_line_length)), axis=1)) #base method
t2 = timeit.Timer(l2)
print(t2.repeat(3, 100))
l1 = (lambda angle=angle, belong=belong, THRES_THETA=THRES_THETA, lines_lengths_vstacked=lines_lengths_vstacked, max_line_length=max_line_length:
np.einsum('ij,ij->i', belong, 0.3 * (1-(angle/THRES_THETA)) + 0.7 * (lines_lengths_vstacked/max_line_length)))
t1 = timeit.Timer(l1)
print(t1.repeat(3, 100))
l3 = (lambda angle=angle, belong=belong:
np.sum(angle*belong ,axis=1)) #base method
t3 = timeit.Timer(l3)
print(t3.repeat(3, 100))
l4 = (lambda angle=angle, belong=belong:
np.einsum('ij,ij->i', belong, angle))
t4 = timeit.Timer(l4)
print(t4.repeat(3, 100))
结果是:
^{pr2}$如果我们看最后两行,对应于einsum的行比使用基方法快30%。但是如果我们看前两行,einsum方法的加速速度更小,大约快了0.1%。在
我不确定这个时机是否可以改进。在
您可以使用masked arrays来实现这一点,但在我运行的测试中,它比
(angles * belong).sum(1)
快。在掩码数组方法如下所示:
这里,我们正在创建一个
angles
的掩码数组,其中值~belong
(“不属于”)是掩码的(排除)。我们使用而不是,因为我们要排除belong
中的False
中的值。然后沿着第.sum(1)
行取和。sum
将返回另一个掩码数组,因此您可以使用该掩码数组的.data
属性获取值。在我添加了
copy=False
kwarg,这样代码就不会因为创建数组而变慢,但是它仍然比(angles * belong).sum(1)
方法慢,所以您应该坚持这样做。在您可以使用^{} -
您也可以使用^{} ,如下-
^{pr2}$样本运行-
运行时测试-
我会选择
np.einsum
的那一个!在我发现了一种比einsum方法快3倍的方法,而且我不认为它能更快,所以我用另一种方法回答我自己的问题。在
我所希望的是计算出一个公式,这个公式涉及到,属于的位置是真的。这应该会加快大约3倍,因为归属是真实的大约30%的时间。在
我尝试用第一个公式来计算数组的位置,但这不属于第一个问题np.总和. 解决方案是使用np.add.reduceat。在
reduceat可以在特定切片的列表中减少ufunc(在本例中为add)。所以我只需要创建一个切片列表,这样我就可以减少由角度[归属]产生的一维数组。在
我将展示我的代码和时间安排,这应该是独立的。在
首先,我用reduceat解决方案定义一个函数:
然后比较了基本方法和einsum方法:
^{pr2}$时间安排:
因此,还原解决方案的速度大约是其他两种方法的3倍,并给出了相同的结果。 请注意,这些结果是针对比之前稍大的示例,其中: 属于,角度和线条长度有形状:(3400170) 以及np.count_非零(属于)/属于。大小->;0.16765051903114186
更新 因为一个角落的案子np.还原(就像在numpy版本'1.11.0rc1')中它不能正确地处理重复的索引,see,我不得不添加hack to vote_op()函数来处理beyond中的整行都是False的情况。这会导致重复索引和错误的投票结果。我目前的解决方案是修补错误的值,这是可行的,但这是另一步。请参见新投票操作():
相关问题 更多 >
编程相关推荐