numpy/scipy 中的平方差总和 (SSD)
Posted
技术标签:
【中文标题】numpy/scipy 中的平方差总和 (SSD)【英文标题】:Sum of Square Differences (SSD) in numpy/scipy 【发布时间】:2011-01-18 01:58:44 【问题描述】:我正在尝试使用 Python 和 Numpy/Scipy 来实现图像处理算法。分析器告诉我很多时间都花在以下函数上(经常调用),它告诉我两张图像之间的平方差之和
def ssd(A,B):
s = 0
for i in range(3):
s += sum(pow(A[:,:,i] - B[:,:,i],2))
return s
如何加快速度?谢谢。
【问题讨论】:
【参考方案1】:只是
s = numpy.sum((A[:,:,0:3]-B[:,:,0:3])**2)
(如果形状始终为 (,,3),我预计可能只是 sum((A-B)**2)
)
也可以使用求和法:((A-B)**2).sum()
对吗?
【讨论】:
砰。我过得很慢。我的跑步时间减半。 值得注意的是,为此您必须使用numpy.sum
,而不是内置的sum
,它将在第一个维度上找到总和并返回一个新的一维数组.
((A-B)**2).sum(-1) 如果只想在最后一个轴上添加,则需要指定轴参数。只需使用 sum() 添加数组的所有条目(首先解开)【参考方案2】:
顺便提一下,也可以使用np.dot
:
def ssd(A,B):
dif = A.ravel() - B.ravel()
return np.dot( dif, dif )
这可能比使用np.sum
和**2
的替代方法更快并且可能更准确,但如果您想沿指定轴计算ssd,则不起作用。在这种情况下,可能会有一个神奇的下标公式使用np.einsum
。
【讨论】:
【参考方案3】:我很困惑你为什么选择i in range(3)
。那应该是整个阵列,还是只是一部分?
总的来说,您可以用 numpy 中定义的操作替换其中的大部分内容:
def ssd(A,B):
squares = (A[:,:,:3] - B[:,:,:3]) ** 2
return numpy.sum(squares)
这样你可以做一个操作而不是三个,使用numpy.sum
可能比内置的sum
更好地优化加法。
【讨论】:
+1scipy.stats.stats.ss
(平方和)就是这样做的。【参考方案4】:
不知道 power 2 的 pow() 函数会不会很快。试试:
def ssd(A,B):
s = 0
for i in range(3):
s += sum((A[:,:,i] - B[:,:,i])*A[:,:,i] - B[:,:,i])
return s
【讨论】:
A-B 乘法中缺少括号。【参考方案5】:Ritsaert Hornstra 的回答得到了 2 个否定分数(诚然,我没有看到它的原始形式......)
这是真的。
对于大量迭代,使用 '**' 运算符或 pow(x,y) 方法所花费的时间通常是手动将这些对相乘的两倍。如果有必要使用 math.fabs() 方法,如果它抛出 NaN(有时尤其是在使用 int16s 等时会这样做),它仍然只需要给定两个函数的大约一半时间。
对于我知道的原始问题并不重要,但绝对值得知道。
【讨论】:
【参考方案6】:你可以试试这个:
dist_sq = np.sum((A[:, np.newaxis, :] - B[np.newaxis, :, :]) ** 2, axis=-1)
可以在此处找到更多详细信息(“k-Nearest Neighbors”示例): https://jakevdp.github.io/PythonDataScienceHandbook/02.08-sorting.html
【讨论】:
【参考方案7】:在 Ruby 语言中,您可以通过这种方式实现此目的
def diff_btw_sum_of_squars_and_squar_of_sum(from=1,to=100) # use default values from 1..100.
((1..100).inject(:+)**2) -(1..100).map |num| num ** 2.inject(:+)
end
diff_btw_sum_of_squars_and_squar_of_sum #call for above method
【讨论】:
以上是关于numpy/scipy 中的平方差总和 (SSD)的主要内容,如果未能解决你的问题,请参考以下文章
如何检查 NumPy 和 SciPy 中的 BLAS/LAPACK 链接?
Matlab 中的 FFT 和 numpy / scipy 给出不同的结果