我想计算两组点inputs
和testing
之间的欧氏距离平方。 inputs
通常是一个大小为〜(200,N)的实数组,而testing
通常为〜(1e8,N),N大约为10.距离应在N的每个维度中缩放,所以我会将表达式scale[j]*(inputs[i,j] - testing[ii,j])**2
(其中scale
是缩放矢量)聚合N次。我试图尽可能快地做到这一点,特别是因为N可能很大。我的第一个测试是
def old_version (inputs, testing, x0):
nn, d1 = testing.shape
n, d1 = inputs.shape
b = np.zeros((n, nn))
for d in xrange(d1):
b += x0[d] * (((np.tile(inputs[:, d], (nn, 1)) -
np.tile (testing[:, d], (n, 1)).T))**2).T
return b
没什么太花哨的。然后我尝试使用scipy.spatial.distance.cdist
,虽然我仍然需要遍历它以获得正确的缩放
def new_version (inputs, testing, x0):
# import scipy.spatial.distance as dist
nn, d1 = testing.shape
n, d1 = inputs.shape
b = np.zeros ((n, nn))
for d in xrange(d1):
b += x0[d] * dist.cdist(inputs[:, d][:, None],
testing[:, d][:, None], 'sqeuclidean')
return b
new_version
似乎更好地扩展(N> 1000),但我不确定我在这里走的速度是否越来越快。任何进一步的想法非常感谢!
答案 0 :(得分:3)
这段代码给了我一个10倍的实现,尝试一下:
x = np.random.randn(200, 10)
y = np.random.randn(1e5, 10)
scale = np.abs(np.random.randn(1, 10))
scale_sqrt = np.sqrt(scale)
dist_map = dist.cdist(x*scale_sqrt, y*scale_sqrt, 'sqeuclidean')
这些是测试结果:
在[135]中:%timeit suggested_version(输入,测试,x0)
1个循环,最好为每个循环3:341 ms
在[136]中:%timeit op_version(输入,测试,x00)(注意:x00是x0的重塑)
1个循环,最佳3:3.37秒/循环
只要确保比你选择更大的N
,你就不会记忆力低下。它确实可以减慢速度。