繁体   English   中英

在 Python 中计算加权成对距离矩阵

[英]Calculate weighted pairwise distance matrix in Python

我试图找到在 Python 中执行以下成对距离计算的最快方法。 我想使用距离按相似性对list_of_objects进行排名。

list_of_objects中的每一项都以四个度量 a、b、c、d 为特征,这些度量是在非常不同的尺度上进行的,例如:

object_1 = [0.2, 4.5, 198, 0.003]
object_2 = [0.3, 2.0, 999, 0.001]
object_3 = [0.1, 9.2, 321, 0.023]
list_of_objects = [object_1, object_2, object_3]

目的是获得list_of_objects对象的成对距离矩阵。 但是,我希望能够通过权重向量在我的距离计算中指定每个度量的“相对重要性”,每个度量一个权重,例如:

weights = [1, 1, 1, 1]

表示所有测量值的权重相等。 在这种情况下,我希望每次测量对物体之间的距离的贡献相等,而不管测量比例如何。 或者:

weights = [1, 1, 1, 10]

表示我希望测量 d 对物体之间的距离的贡献比其他测量多 10 倍。

我当前的算法如下所示:

  1. 为每次测量计算成对距离矩阵
  2. 标准化每个距离矩阵,使最大值为 1
  3. 将每个距离矩阵乘以来自weights的适当权weights
  4. 对距离矩阵求和以生成单个成对矩阵
  5. 使用来自 4 的矩阵提供来自list_of_objects的对象对的排名列表

这很好用,并为我提供了对象之间城市街区距离的加权版本。

我有两个问题:

  1. 在不改变算法的情况下,在 SciPy、NumPy 或 SciKit-Learn 中执行初始距离矩阵计算的最快实现是什么。

  2. 是否有现有的多维距离方法可以为我完成所有这些工作?

对于 Q 2,我已经查看过,但找不到任何以我想要的方式执行“相对重要性”的内置步骤。

欢迎其他建议。 很高兴澄清我是否遗漏了细节。

scipy.spatial.distance是您想要查看的模块。 它有很多不同的规范,可以很容易地应用。

我建议使用加权 M​​onkowski Metrik

加权 Minkowski Metrik

您可以使用此包中的pdist方法进行成对距离计算。

例如

import numpy as np
from scipy.spatial.distance import pdist, wminkowski, squareform

object_1 = [0.2, 4.5, 198, 0.003]
object_2 = [0.3, 2.0, 999, 0.001]
object_3 = [0.1, 9.2, 321, 0.023]
list_of_objects = [object_1, object_2, object_3]

# make a 3x4 array from the list of objects
X = np.array(list_of_objects)

#calculate pairwise distances, using weighted Minkowski norm
distances = pdist(X,wminkowski,2, [1,1,1,10])

#make a square matrix from result
distances_as_2d_matrix = squareform(distances)

print distances
print distances_as_2d_matrix

这将打印

[ 801.00390786  123.0899671   678.0382942 ]
[[   0.          801.00390786  123.0899671 ]
 [ 801.00390786    0.          678.0382942 ]
 [ 123.0899671   678.0382942     0.        ]]

将成对距离除以最大值的归一化步骤似乎是非标准的,并且可能很难找到一个现成的函数来满足您的要求。 虽然自己做很容易。 一个起点是将你的list_of_objects变成一个数组:

>>> obj_arr = np.array(list_of_objects)
>>> obj_arr.shape
(3L, 4L)

然后,您可以使用广播获得成对距离。 这有点低效,因为它没有利用度量的对称性,而是对每个距离计算两次:

>>> dists = np.abs(obj_arr - obj_arr[:, None])
>>> dists.shape
(3L, 3L, 4L)

标准化很容易做到:

>>> dists /= dists.max(axis=(0, 1))

您的最终称重可以通过多种方式完成,您可能希望以最快的方式进行基准测试:

>>> dists.dot([1, 1, 1, 1])
array([[ 0.        ,  1.93813131,  2.21542674],
       [ 1.93813131,  0.        ,  3.84644195],
       [ 2.21542674,  3.84644195,  0.        ]])
>>> np.einsum('ijk,k->ij', dists, [1, 1, 1, 1])
array([[ 0.        ,  1.93813131,  2.21542674],
       [ 1.93813131,  0.        ,  3.84644195],
       [ 2.21542674,  3.84644195,  0.        ]])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM