首先,我想对问题标题不清楚表示道歉:原因是我无法确定工作中的数学过程。
简而言之,情况如下:
以下是我的工作方式,
import numpy as np
def distLstSq(f1,f2):
"Return the least square distance between f1 and f2 per unit element"
return np.sum(np.square(np.subtract(f1,f2)))/len(f1)
f1 = np.arange(100)
f2 = np.random.random_integers(1,100,5)
nBuf = len(f2)
dist = np.empty(len(f1)-nBuf)
for i in range(len(f1)-nBuf):
temp = f1[i:i+nBuf]
dist[i] = distLstSq(temp,f2)
然而,由于大向量f1(从4MB的文件生成),我想知道是否没有更优雅的pythonic解决方案,使用更少的CPU资源,在更短的时间内。可能是一种减法卷积"其中f2在元素方向上滑过f1,每一步都有减法运算。
非常感谢您的投入!
Bertrand
答案 0 :(得分:2)
首先,我想指出dist
中的字词数不是len(f1)-nBuf
而是len(f1)-nBuf+1
。这就是短矢量与较长矢量完全重叠的方式。
忽略len(f1)
的除法,它只是按常量缩放,你为f2的每个切片计算以下内容:
所以我认为你可以通过一些预先计算来减少操作次数。我们还可以使用np.convolve
来查找交叉术语。
f1_squared = f1**2
f2_squared_sum = np.sum(f2**2)
nBuf = len(f2)
cross_terms = -2*np.convolve(f1, f2[::-1], "valid")
# reverse f2 to get what we want.
# "valid" returns where vectors completely overlap
squared_distance = [f2_squared_sum + np.sum(f1_squared[i:i+nBuf]) + cross_terms[i]
for i in xrange(len(cross_terms))]
mean_squared_distance = np.array(squared_distance)/nBuf
您的版本:
nBuf = len(f2)
dist = np.empty(len(f1)-nBuf+1)
for i in xrange(len(f1)-nBuf+1):
temp = f1[i:i+nBuf]
dist[i] = distLstSq(temp,f2)
基于timeit.timeit
,我的版本速度提高了30-50%。
通过优化np.sum(f1_squared[i:i+nBuf])
可以进一步提高性能,因为这涉及重复操作。应该有一些分而治之的方法来做总和。
另外我认为scipy.signal.fftconvolve可能比np.convolve
更快,但这取决于较短矢量的长度(see here)