首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在给定稀疏矩阵数据的情况下,在Python中计算余弦相似度的最快方法是什么?

在给定稀疏矩阵数据的情况下,在Python中计算余弦相似度的最快方法是什么?
EN

Stack Overflow用户
提问于 2013-07-13 13:18:08
回答 8查看 136.6K关注 0票数 75

给定一个稀疏矩阵列表,计算矩阵中每一列(或行)之间的余弦相似度的最佳方法是什么?我不想重复n- iterate 2次。

假设输入矩阵是:

代码语言:javascript
复制
A= 
[0 1 0 0 1
 0 0 1 1 1
 1 1 0 1 0]

稀疏表示为:

代码语言:javascript
复制
A = 
0, 1
0, 4
1, 2
1, 3
1, 4
2, 0
2, 1
2, 3

在Python中,使用矩阵输入格式很简单:

代码语言:javascript
复制
import numpy as np
from sklearn.metrics import pairwise_distances
from scipy.spatial.distance import cosine

A = np.array(
[[0, 1, 0, 0, 1],
[0, 0, 1, 1, 1],
[1, 1, 0, 1, 0]])

dist_out = 1-pairwise_distances(A, metric="cosine")
dist_out

提供:

代码语言:javascript
复制
array([[ 1.        ,  0.40824829,  0.40824829],
       [ 0.40824829,  1.        ,  0.33333333],
       [ 0.40824829,  0.33333333,  1.        ]])

这对于全矩阵输入来说很好,但是我真的想从稀疏表示开始(由于我的矩阵的大小和稀疏性)。关于如何最好地实现这一点,您有什么想法吗?提前谢谢。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2016-08-23 22:45:16

您可以直接使用sklearn计算稀疏矩阵的行上的成对余弦相似度。从0.17版本开始,它还支持稀疏输出:

代码语言:javascript
复制
from sklearn.metrics.pairwise import cosine_similarity
from scipy import sparse

A =  np.array([[0, 1, 0, 0, 1], [0, 0, 1, 1, 1],[1, 1, 0, 1, 0]])
A_sparse = sparse.csr_matrix(A)

similarities = cosine_similarity(A_sparse)
print('pairwise dense output:\n {}\n'.format(similarities))

#also can output sparse matrices
similarities_sparse = cosine_similarity(A_sparse,dense_output=False)
print('pairwise sparse output:\n {}\n'.format(similarities_sparse))

结果:

代码语言:javascript
复制
pairwise dense output:
[[ 1.          0.40824829  0.40824829]
[ 0.40824829  1.          0.33333333]
[ 0.40824829  0.33333333  1.        ]]

pairwise sparse output:
(0, 1)  0.408248290464
(0, 2)  0.408248290464
(0, 0)  1.0
(1, 0)  0.408248290464
(1, 2)  0.333333333333
(1, 1)  1.0
(2, 1)  0.333333333333
(2, 0)  0.408248290464
(2, 2)  1.0

如果你想要列余弦相似性,只需事先转置你的输入矩阵:

代码语言:javascript
复制
A_sparse.transpose()
票数 80
EN

Stack Overflow用户

发布于 2013-12-20 01:26:54

下面的方法大约比scipy.spatial.distance.pdist快30倍。它在大型矩阵上的运行速度非常快(假设您有足够的RAM)

有关如何优化稀疏性的讨论,请参阅下面的内容。

代码语言:javascript
复制
# base similarity matrix (all dot products)
# replace this with A.dot(A.T).toarray() for sparse representation
similarity = numpy.dot(A, A.T)


# squared magnitude of preference vectors (number of occurrences)
square_mag = numpy.diag(similarity)

# inverse squared magnitude
inv_square_mag = 1 / square_mag

# if it doesn't occur, set it's inverse magnitude to zero (instead of inf)
inv_square_mag[numpy.isinf(inv_square_mag)] = 0

# inverse of the magnitude
inv_mag = numpy.sqrt(inv_square_mag)

# cosine similarity (elementwise multiply by inverse magnitudes)
cosine = similarity * inv_mag
cosine = cosine.T * inv_mag

如果你的问题是典型的大规模二元偏好问题,那么你在一个维度上的条目要比另一个维度多得多。此外,短维度是您要计算其条目之间的相似性的维度。让我们将这个维度称为“item”维度。

如果是这样的话,在行中列出您的“项目”,并使用scipy.sparse创建A。然后按照指示替换第一行。

如果你的问题是非典型的,你需要更多的修改。这些应该是用它们的scipy.sparse等价物非常直接地替换基本的numpy操作。

票数 47
EN

Stack Overflow用户

发布于 2017-09-30 17:31:19

我已经尝试了上面的一些方法。然而,@zbinsd的实验有其局限性。实验中使用的矩阵稀疏度极低,而实际稀疏度通常在90%以上。在我的条件下,稀疏的形状是(7000,25000),稀疏度是97%。方法4非常慢,我不能容忍得到结果。我使用方法6,它在10秒内完成。令人惊讶的是,我尝试了下面的方法,它只用了0.247秒就完成了。

代码语言:javascript
复制
import sklearn.preprocessing as pp

def cosine_similarities(mat):
    col_normed_mat = pp.normalize(mat.tocsc(), axis=0)
    return col_normed_mat.T * col_normed_mat

这种高效的方法是通过enter link description here链接的

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17627219

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档