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

Python 用numpy实现基于欧氏距离的公式,python,numpy,matrix,Python,Numpy,Matrix,我正在尝试使用numpy在python中实现这个公式 如图所示,X是NUMPY矩阵,每个席席是N维向量,C也是一个NUMP矩阵,每个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]):

我正在尝试使用numpy在python中实现这个公式

如图所示,X是NUMPY矩阵,每个席席是N维向量,C也是一个NUMP矩阵,每个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中的公式?如果有任何想法,我都会心存感激。

一般来说,在python中,如果可能的话,应该避免循环大量运行

这里存在一个scipy函数,
scipy.space.distance.cdist(C,X)
,它计算C和X之间的成对距离矩阵。也就是说,如果调用
distance\u matrix=scipy.space.distance.cdist(C,X)
,则距离矩阵[i,j]=dist(C\u i,X\j)

然后,对于每个j,您需要计算所有i上的距离(C_i,X_j)的最小值。你也不需要一个循环来计算这个!如果传递轴参数,函数
numpy.minimum
将为您执行此操作

最后,通过调用
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)
返回与函数相同的结果:)
希望这有帮助

通常,在python中,如果可能的话,应该避免循环大量运行

这里存在一个scipy函数,
scipy.space.distance.cdist(C,X)
,它计算C和X之间的成对距离矩阵。也就是说,如果调用
distance\u matrix=scipy.space.distance.cdist(C,X)
,则距离矩阵[i,j]=dist(C\u i,X\j)

然后,对于每个j,您需要计算所有i上的距离(C_i,X_j)的最小值。你也不需要一个循环来计算这个!如果传递轴参数,函数
numpy.minimum
将为您执行此操作

最后,通过调用
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)
返回与函数相同的结果:)
希望这有帮助

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是“欧几里德”距离。是否需要欧几里德Q(平方距离)对于“最近的”测定,只需删除np.sqrt项,最后挤压,只需删除形状中的和1项


cdist对于更大的阵列更快(起点和目的地的数量约为1000个)但einsum是一个很好的替代方案,本网站上的其他人对此有很好的记录。

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是“欧几里德”距离。是否需要欧几里德Q(平方距离)对于“最近的”测定,只需删除np.sqrt项,最后挤压,只需删除形状中的和1项


cdist对于更大的阵列(以1000个起点和终点的顺序)来说速度更快,但einsum是一个很好的替代方案,该站点上的其他人对此进行了充分的记录。

根据X和C的大小,您可以通过先构建a来获得更好的性能。构建树是
O(n log n)
。在KDTree中找到最近的点是
O(logn)
。Scipy是您的朋友:根据X和C的大小,您可以通过首先构建a来获得更好的性能。构建树是
O(nlogn)
。在KDTree中找到最近的点是
O(logn)
。Scipy是您的朋友: