余弦相似度

3

我正在阅读一个公式:

enter image description here

这个公式是用于计算余弦相似度的。我认为这看起来很有趣,于是我创建了一个numpy数组,该数组以用户ID作为行,物品ID作为列。例如,让M 是这个矩阵:

M = [[2,3,4,1,0],[0,0,0,0,5],[5,4,3,0,0],[1,1,1,1,1]] 

这里矩阵中的条目是人们给项目 i 的评分,基于行 u 和列 i。我想在项目(行)之间计算此矩阵的余弦相似度。我相信这应该会产生一个 5 x 5 的矩阵。我尝试过了。

df = pd.DataFrame(M)
item_mean_subtracted = df.sub(df.mean(axis=0), axis=1)
similarity_matrix = item_mean_subtracted.fillna(0).corr(method="pearson").values

然而,这似乎不太对。
1个回答

4
这是一种可能的调整余弦相似度实现方式:
import numpy as np
from scipy.spatial.distance import pdist, squareform

M = np.asarray([[2, 3, 4, 1, 0], 
                [0, 0, 0, 0, 5], 
                [5, 4, 3, 0, 0], 
                [1, 1, 1, 1, 1]])

M_u = M.mean(axis=1)
item_mean_subtracted = M - M_u[:, None]
similarity_matrix = 1 - squareform(pdist(item_mean_subtracted.T, 'cosine'))

备注:

  • 我利用NumPy的广播机制来减去平均值。
  • 如果M是一个稀疏矩阵,你可以这样做:M.toarray()
  • 文档中得知:
  • Y = pdist(X, 'cosine')
    计算向量u和v之间的余弦距离,
    1- u⋅v / (||u||2||v||2)
    这里 ||∗||2是它的参数*的2范数,u⋅v是向量u和v的点积。

  • 使用T方法进行数组转置。

演示:

In [277]: M_u
Out[277]: array([ 2. ,  1. ,  2.4,  1. ])

In [278]: item_mean_subtracted
Out[278]: 
array([[ 0. ,  1. ,  2. , -1. , -2. ],
       [-1. , -1. , -1. , -1. ,  4. ],
       [ 2.6,  1.6,  0.6, -2.4, -2.4],
       [ 0. ,  0. ,  0. ,  0. ,  0. ]])

In [279]: np.set_printoptions(precision=2)

In [280]: similarity_matrix
Out[280]: 
array([[ 1.  ,  0.87,  0.4 , -0.68, -0.72],
       [ 0.87,  1.  ,  0.8 , -0.65, -0.91],
       [ 0.4 ,  0.8 ,  1.  , -0.38, -0.8 ],
       [-0.68, -0.65, -0.38,  1.  ,  0.27],
       [-0.72, -0.91, -0.8 ,  0.27,  1.  ]])

我相信调整后的余弦相似度值应该在-1和1之间,对吗? - Mike El Jackson
是的,绝对没错。我误读了公式。请再次查看我的编辑答案,我认为现在已经正确实现了调整余弦相似度。 - Tonechas
是的,它确实如此。请注意相似度矩阵的形状为(I,I),其中I是项目数量。 - Tonechas
好的,如果我们正在查看第2项,则它会找到所有对于item2有非零条目的用户,并计算$\bar{R}_u$的平均值。 - Mike El Jackson
让我们在聊天中继续这个讨论 - Mike El Jackson
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接