我正在尝试使用numpy
在python中实现这个公式如上图所示,X是numpy矩阵,每个xi是n维向量,C也是numpy矩阵,每个Ci也是n维的向量,dist(Ci,xi)是欧氏距离这两个载体。 我在python中实现了一个代码:
value = 0
for i in range(X.shape[0]):
min_value = math.inf
#this for loop iterate k times
for j in range(C.shape[0]):
distance = (np.dot(X[i] - C[j],
X[i] - C[j])) ** .5
min_value = min(min_value, distance)
value += min_value
fitnessValue = value
但是我的代码性能还不够好我正在寻找更快,有没有更快的方法来计算python中的公式,任何想法都会感激不尽。
答案 0 :(得分:5)
通常,在python中应尽可能避免循环运行很多次。
这里有一个scipy函数distance_matrix = scipy.spatial.distance.cdist(C, X)
,它计算C和X之间的成对距离矩阵。也就是说,如果你调用numpy.minimum
,你就有distance_matrix [i,j] = dist(C_i,X_j)。
然后,对于每个j,你想要计算所有i的dist(C_i,X_j)的最小值。你不需要循环来计算这个!如果传递轴参数,函数numpy.sum
会为您完成。
最后,通过调用import scipy.spatial.distance
import numpy as np
def your_function(C, X):
distance_matrix = scipy.spatial.distance.cdist(C, X)
minimum = np.min(distance_matrix, axis=0)
return np.sum(minimum)
函数来完成所有这些最小值的总和。
这使代码更具可读性和更快:
{{1}}
返回与您的函数相同的结果:) 希望这有帮助!
答案 1 :(得分:1)
>>> a
array([[ 0., 0.],
[ 1., 1.],
[ 2., 2.],
[ 3., 3.],
[ 4., 4.]])
>>> b = a.reshape(np.prod(a.shape[:-1]),1,a.shape[-1])
>>> b
array([[[ 0., 0.]],
[[ 1., 1.]],
[[ 2., 2.]],
[[ 3., 3.]],
[[ 4., 4.]]])
>>> diff = a - b; dist_arr = np.sqrt(np.einsum('ijk,ijk->ij', diff, diff)).squeeze()
>>> dist_arr
array([[ 0. , 1.41421, 2.82843, 4.24264, 5.65685],
[ 1.41421, 0. , 1.41421, 2.82843, 4.24264],
[ 2.82843, 1.41421, 0. , 1.41421, 2.82843],
[ 4.24264, 2.82843, 1.41421, 0. , 1.41421],
[ 5.65685, 4.24264, 2.82843, 1.41421, 0. ]])
数组'a'是一个简单的2d(形状=(5,2),'b'只是'a'重新形成以便于(5,1,2)cdist样式数组的差异计算。术语是详细说明,因为它们是从其他代码中提取的.'diff'变量是差异数组,dist_arr显示的是'euclidean'距离。如果你需要euclideansq(平方距离)进行'最接近'的测定,只需删除np即可。 sqrt term并最终挤压,只删除形状中的1个术语。
cdist对于更大的数组(大约1000个起源和目的地)更快,但是einsum是一个不错的选择,并且在本网站上的其他人都有很好的文档记录。