计算numpy中2个点列表的距离

leo*_*ank 7 python numpy

我有 2 个点列表作为 numpy.ndarray,每一行都是一个点的坐标,例如:

a = np.array([[1,0,0],[0,1,0],[0,0,1]])
b = np.array([[1,1,0],[0,1,1],[1,0,1]])
Run Code Online (Sandbox Code Playgroud)

这里我想计算2个列表中所有点对之间的欧氏距离,对于a中的每个点p_a,我想计算它与b中每个点p_b之间的距离。所以结果是

d = np.array([[1,sqrt(3),1],[1,1,sqrt(3)],[sqrt(3),1,1]])
Run Code Online (Sandbox Code Playgroud)

如何使用numpy中的矩阵乘法来计算距离矩阵?

jak*_*vdp 11

使用直接 numpy 广播,您可以执行以下操作:

dist = np.sqrt(((a[:, None] - b[:, :, None]) ** 2).sum(0))
Run Code Online (Sandbox Code Playgroud)

或者,scipy有一个例程可以更有效地计算这个问题(特别是对于大型矩阵)

from scipy.spatial.distance import cdist
dist = cdist(a, b)
Run Code Online (Sandbox Code Playgroud)

我会避免依赖于分解矩阵乘积(形式为 A^2 + B^2 - 2AB)的解决方案,因为它们可能由于浮点舍入误差而在数值上不稳定。


Div*_*kar 5

为了计算每对元素 x 和 y 的欧氏距离平方,我们需要找到:

(Xik-Yjk)**2 = Xik**2 + Yjk**2 - 2*Xik*Yjk
Run Code Online (Sandbox Code Playgroud)

然后沿k求和得到对应点的距离dist(Xi,Yj)。

使用关联性,它可以简化为:

dist(Xi,Yj) = sum_k(Xik**2) + sum_k(Yjk**2) - 2*sum_k(Xik*Yjk)
Run Code Online (Sandbox Code Playgroud)

在最后一部分引入矩阵乘法,我们将得到所有距离,如下所示 -

dist = sum_rows(X^2), sum_rows(Y^2), -2*matrix_multiplication(X, Y.T)
Run Code Online (Sandbox Code Playgroud)

因此,用 NumPy 术语来说,我们最终会得到以ab作为输入的情况的欧几里德距离,如下所示 -

np.sqrt((a**2).sum(1)[:,None] + (b**2).sum(1) - 2*a.dot(b.T))
Run Code Online (Sandbox Code Playgroud)

利用np.einsum,我们可以将前两个求和约简替换为 -

np.einsum('ij,ij->i',a,a)[:,None] + np.einsum('ij,ij->i',b,b) 
Run Code Online (Sandbox Code Playgroud)

eucl_dist 更多信息可以在包上找到wiki page(免责声明:我是它的作者)。