簡體   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