Scipy稀疏矩阵与稀疏向量的欧氏距离

时间:2014-02-10 10:33:46

标签: python scipy sparse-matrix knn euclidean-distance

我正在研究用于大学任务的KNN算法,目前我正在努力寻找存储为Scipy lil_matrix的每个训练向量之间的欧几里德距离(由于其中值的稀疏性)矢量),以及存储为1 xn lil_matrix的测试向量,原因与上述相同。

要计算出欧几里德距离,然后执行以下代码:

for positiveIndex, positivesComparison in enumerate(positives):
    result.append((spatial.distance.euclidean(positivesComparison.todense(),sentenceVector.todense() ), positiveIndex, 1))

其中sentenceVector是1行的lil_matrix,而positives是大小为n x m的lil_matrix。

我想尝试找出更快的东西,而不是逐行遍历正面矩阵并每次评估欧氏距离,并且可以运行正面矩阵和sentenceVector矢量之间的欧氏距离,并返回1 xm矩阵与欧氏距离。 我想这样做的原因是当前系统的计算速度相对较慢,因为它基本上是一个NM时间复杂度,因为我需要计算多个句子测试。 这是可能的,如果是的话,我该怎么做?

注意,任务是使用KNN算法的不同K值来评估性能,而不是KNN的实际实现(尽管我们不允许使用KNN库来完成任务)

1 个答案:

答案 0 :(得分:4)

您可以非常轻松地计算批次欧几里德距离:

In [10]: a = np.random.random(size=(4,5))

In [11]: b = np.random.random(size=(1,5))

In [12]: from scipy.spatial.distance import euclidean

In [13]: [euclidean(aa, b) for aa in a]
Out[13]: [1.1430615949614429, 0.568517046878056, 1.3302284168375587, 1.0581730230363529]

In [14]: np.sqrt(np.sum((a - b)**2, axis=1))
Out[14]: array([ 1.1431,  0.5685,  1.3302,  1.0582])

但是我们想要使用稀疏矩阵,这会让事情变得更加困难:

In [22]: import scipy.sparse as ss

In [23]: sa = ss.lil_matrix(a)

In [24]: sb = ss.lil_matrix(b)

In [25]: np.sqrt(np.sum((sa - sb)**2, axis=1))  # <-- ValueError: inconsistent shapes

可以这样做,但您需要使用some tricks

更重要的是,你应该看看你的矢量究竟有多大(以及多么稀疏)。你可能会更快离开所有密集的东西,它肯定会让你头疼。

最后,我会避免使用LIL格式矩阵,因为它们是最慢的格式之一。对于您的情况,请查看CSR格式。

编辑:我忘记了最简单的解决方案:使用scikit-learn

In [36]: from sklearn.metrics import pairwise_distances

In [37]: pairwise_distances(a, b)
Out[37]:
array([[ 1.1431],
       [ 0.5685],
       [ 1.3302],
       [ 1.0582]])

In [38]: pairwise_distances(sa, sb)
Out[38]:
array([[ 1.1431],
       [ 0.5685],
       [ 1.3302],
       [ 1.0582]])