我得到一个由浮点值组成的二维 numpy 数组 X,需要计算所有行对之间的欧氏距离,然后计算距离最小的前 k 行索引并返回它们(其中 k > 0 ).我正在用一个小阵列进行测试,这是我目前所拥有的……
import numpy as np
from sklearn.metrics.pairwise import euclidean_distances
X_testing = np.asarray([[1,2,3.5],[4,1,2],[0,0,2],[3.4,1,5.6]])
test = euclidean_distances(X_testing, X_testing)
print(test)
结果打印输出是:
[[ 0. 3.5 2.6925824 3.34215499]
[ 3.5 0. 4.12310563 3.64965752]
[ 2.6925824 4.12310563 0. 5.05173238]
[ 3.34215499 3.64965752 5.05173238 0. ]]
接下来,我需要高效地计算出所有行对之间的前k个最小距离,并以列表的形式依次返回对应的k个(row1, row2, distance_value)元组。
所以在上面的测试用例中,如果 k = 2,那么我需要返回以下内容:
[(0, 2, 2.6925824), (0, 3, 3.34215499)]
是否有内置方法(scipy、sklearn、numpy 等)或任何其他方法来帮助高效计算?虽然上面的测试用例很小,但实际上二维数组非常大,所以内存和时间是一个问题。谢谢
请您参考如下方法:
使用 scipy.spatial
而不是 sklearn
(我还没有安装)我可以获得相同的距离矩阵:
In [623]: from scipy import spatial
In [624]: pdist=spatial.distance.pdist(X_testing)
In [625]: pdist
Out[625]:
array([ 3.5 , 2.6925824 , 3.34215499, 4.12310563, 3.64965752,
5.05173238])
In [626]: D=spatial.distance.squareform(pdist)
In [627]: D
Out[627]:
array([[ 0. , 3.5 , 2.6925824 , 3.34215499],
[ 3.5 , 0. , 4.12310563, 3.64965752],
[ 2.6925824 , 4.12310563, 0. , 5.05173238],
[ 3.34215499, 3.64965752, 5.05173238, 0. ]])
pdist
是压缩形式,其在正方形中的索引可以用
In [629]: np.triu_indices(4,1)
Out[629]:
(array([0, 0, 0, 1, 1, 2], dtype=int32),
array([1, 2, 3, 2, 3, 3], dtype=int32))
2个最小的距离是第一个2个值
In [630]: idx=np.argsort(pdist)
In [631]: idx
Out[631]: array([1, 2, 0, 4, 3, 5], dtype=int32)
所以我们想要 [1,2]
来自 pdist
和 triu
的相应元素:
In [633]: pdist[idx[:2]]
Out[633]: array([ 2.6925824 , 3.34215499])
In [634]: np.transpose(np.triu_indices(4,1))[idx[:2],:]
Out[634]:
array([[0, 2],
[0, 3]], dtype=int32)
并将这些值收集为元组列表:
In [636]: I,J = np.triu_indices(4,1)
In [637]: kbig = idx[:2]
In [638]: [(i,j,d) for i,j,d in zip(I[kbig], J[kbig], pdist[kbig])]
Out[638]: [(0, 2, 2.6925824035672519), (0, 3, 3.3421549934136805)]