计算另一个向量的每个列向量的欧几里得距离。
这样说对吗?
distances=np.sqrt(np.sum(np.square(new_v-val.reshape(10,1)),axis=0))
new_v是一个矩阵。 val.reshape(10,1)是一个列向量。 还有其他/更好的方法来完成它。
你所说的是正确的。在numpy.linalg
中有一种更简单的方法:
from numpy.linalg import norm
norm(new_v.T-val, axis=1, ord=2)
val
,然后沿着axis=0
使用norm函数,你会看到改进:norm(new_v-val[:,None], axis=0, ord=2)
。 - Divakar你可以利用高效的 np.einsum
-
subs = new_v - val[:,None]
out = np.sqrt(np.einsum('ij,ij->j',subs,subs))
或者,使用 (a-b)^2 = a^2 + b^2 - 2ab
公式 -
out = np.sqrt(np.einsum('ij,ij->j',new_v, new_v) + val.dot(val) - 2*val.dot(new_v))
new_v
的第二个轴是一个大轴,我们也可以使用numexpr
模块在最后计算sqrt
部分。
运行时测试
方法 -import numexpr as ne
def einsum_based(new_v, val):
subs = new_v - val[:,None]
return np.sqrt(np.einsum('ij,ij->j',subs,subs))
def dot_based(new_v, val):
return np.sqrt(np.einsum('ij,ij->j',new_v, new_v) + \
val.dot(val) - 2*val.dot(new_v))
def einsum_numexpr_based(new_v, val):
subs = new_v - val[:,None]
sq_dists = np.einsum('ij,ij->j',subs,subs)
return ne.evaluate('sqrt(sq_dists)')
def dot_numexpr_based(new_v, val):
sq_dists = np.einsum('ij,ij->j',new_v, new_v) + val.dot(val) - 2*val.dot(new_v)
return ne.evaluate('sqrt(sq_dists)')
时间 -
In [85]: # Inputs
...: new_v = np.random.randint(0,9,(10,100000))
...: val = np.random.randint(0,9,(10))
In [86]: %timeit np.sqrt(np.sum(np.square(new_v-val.reshape(10,1)),axis=0))
...: %timeit einsum_based(new_v, val)
...: %timeit dot_based(new_v, val)
...: %timeit einsum_numexpr_based(new_v, val)
...: %timeit dot_numexpr_based(new_v, val)
...:
100 loops, best of 3: 2.91 ms per loop
100 loops, best of 3: 2.1 ms per loop
100 loops, best of 3: 2.12 ms per loop
100 loops, best of 3: 2.26 ms per loop
100 loops, best of 3: 2.43 ms per loop
In [87]: from numpy.linalg import norm
# @wim's solution
In [88]: %timeit norm(new_v.T-val, axis=1, ord=2)
100 loops, best of 3: 5.88 ms per loop
norm
一无所知,那么我想其他解决方案也是如此。 - Divakarnew_v = np.random.rand(10, 1000)
和 val = np.random.rand(10)
。实际上,使用两行的第一种方法更快。我最初尝试了单行的方法。 - wim
new_v
的形状是什么? - Divakar(10, n)
对于任意的 n。 - wimn
值会激发我们对一些时间的关注 :) - Divakar