使用numpy实现基于欧氏距离的公式

时间:2016-12-08 15:39:06

标签: python numpy matrix

我正在尝试使用numpy

在python中实现这个公式

enter image description here

如上图所示,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中的公式,任何想法都会感激不尽。

2 个答案:

答案 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)

einsum也可以被称为发挥。这是一个小集合的成对距离计算的简单小例子。如果你没有安装scipy和/或希望单独使用numpy,这很有用。

>>> 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是一个不错的选择,并且在本网站上的其他人都有很好的文档记录。