我正在尝试找到在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倍。
我当前的算法如下所示:
weights
list_of_objects
这很好用,并给我一个对象之间城市街区距离的加权版本。
我有两个问题:
在不改变算法的情况下,SciPy,NumPy或SciKit-Learn中执行初始距离矩阵计算的最快实现是什么。
是否存在现有的多维距离方法,可以为我完成所有这些操作?
对于Q 2,我看过,但找不到任何内置步骤,以我想要的方式做出“相对重要性”。
其他建议表示欢迎。很高兴澄清我是否错过了细节。
答案 0 :(得分:9)
scipy.spatial.distance
是您想要查看的模块。它有很多不同的规范,可以很容易地应用。
我建议使用加权的Monkowski Metrik
您可以使用此程序包中的pdist
方法进行成对距离计算。
E.g。
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 4x3 matrix from 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. ]]
答案 1 :(得分:3)
归一化步骤,您将成对距离除以最大值,似乎是非标准的,并且可能很难找到一个现成的函数,它将完全按照您的要求执行。虽然自己动手很容易。一个起点是将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. ]])