numpy中的矢量化矩阵曼哈顿距离
Posted
技术标签:
【中文标题】numpy中的矢量化矩阵曼哈顿距离【英文标题】:Vectorized matrix manhattan distance in numpy 【发布时间】:2018-05-24 00:11:56 【问题描述】:我正在尝试实现一个有效的矢量化numpy
来制作曼哈顿距离矩阵。我熟悉用于使用点积创建高效欧几里得距离矩阵的构造,如下所示:
A = [[1, 2]
[2, 1]]
B = [[1, 1],
[2, 2],
[1, 3],
[1, 4]]
def euclidean_distmtx(X, X):
f = -2 * np.dot(X, Y.T)
xsq = np.power(X, 2).sum(axis=1).reshape((-1, 1))
ysq = np.power(Y, 2).sum(axis=1)
return np.sqrt(xsq + f + ysq)
我想实现类似的东西,但改用曼哈顿距离。到目前为止,我已经接近但未能重新排列绝对差异。据我了解,曼哈顿距离是
我试图通过考虑绝对函数是否根本不适用给我这个等价来解决这个问题
这给了我以下矢量化
def manhattan_distmtx(X, Y):
f = np.dot(X.sum(axis=1).reshape(-1, 1), Y.sum(axis=1).reshape(-1, 1).T)
return f / Y.sum(axis=1) - Y.sum(axis=1)
我认为我是正确的轨道,但我无法在不移除围绕每个向量元素之间差异的绝对函数的情况下移动值。我确信绝对值有一个聪明的技巧,可能是使用平方值的np.sqrt
或其他东西,但我似乎无法意识到这一点。
【问题讨论】:
曼哈顿距离与点积无关,所以任何带有.dot
的东西都不会有太大帮助。
您也可以尝试 e_dist 并将 sqrt 部分省略到底部。这种 einsum 方法可以在各种情况下用作 scipy cdist 和 pdist 等的替代品。***.com/questions/42660459/…
【参考方案1】:
我认为我们不能在这里利用基于 BLAS 的矩阵乘法,因为这里不涉及元素乘法。但是,我们几乎没有其他选择。
方法#1
我们可以使用以曼哈顿距离为特征的Scipy's cdist
,其可选的度量参数设置为'cityblock'
-
from scipy.spatial.distance import cdist
out = cdist(A, B, metric='cityblock')
方法 #2 - A
我们也可以利用broadcasting
,但需要更多内存 -
np.abs(A[:,None] - B).sum(-1)
方法 #2 - B
对于具有两个列的输入数组的切片和求和可以重写以使用更少的内存 -
np.abs(A[:,0,None] - B[:,0]) + np.abs(A[:,1,None] - B[:,1])
方法 #2 - C
移植 broadcasting
版本以利用更快的 absolute
计算和 numexpr
module -
import numexpr as ne
A3D = A[:,None]
out = ne.evaluate('sum(abs(A3D-B),2)')
【讨论】:
非常全面!我相信方法 2B 需要遍历所有列。根据timeit
,scipy
是最快的。方法 C 看起来很丑 ;) 编辑:错字以上是关于numpy中的矢量化矩阵曼哈顿距离的主要内容,如果未能解决你的问题,请参考以下文章
CF 366E - Dima and Magic Guitar 最远曼哈顿距离