让我们首先尝试理解公式,矩阵的存储使得每一行是一个用户,每一列是一个项目。用户由 u 索引,列由 i 索引。
每个用户对事物的好坏有不同的判断规则。一个用户的 1 可能是另一个用户的 3。这就是为什么我们从每个 R_{u,i} 中减去每个 R_u 的平均值。这在您的代码中计算为 item_mean_subtracted。请注意,我们将每个元素减去其 行均值 以标准化用户的偏见。之后,我们通过将每一列除以其范数对每一列(项目)进行归一化,然后计算每一列之间的余弦相似度。
pdist(item_mean_subtracted.T, 'cosine') 计算项目之间的余弦距离,已知
余弦相似度=1-余弦距离
这就是代码有效的原因。
现在,如果我直接根据定义直接计算呢?我已经注释了每个步骤中执行的内容,尝试复制并粘贴代码,您可以通过打印更多中间步骤来与您的计算进行比较。
import numpy as np
from scipy.spatial.distance import pdist, squareform
from numpy.linalg import norm
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'))
print(similarity_matrix)
#Computing the cosine similarity directly
n = len(M[0]) # find out number of columns(items)
normalized = item_mean_subtracted/norm(item_mean_subtracted, axis = 0).reshape(1,n) #divide each column by its norm, normalize it
normalized = normalized.T #transpose it
similarity_matrix2 = np.asarray([[np.inner(normalized[i],normalized[j] ) for i in range(n)] for j in range(n)]) # compute the similarity matrix by taking inner product of any two items
print(similarity_matrix2)
两个代码给出相同的结果:
[[ 1. 0.86743396 0.39694169 -0.67525773 -0.72426278]
[ 0.86743396 1. 0.80099604 -0.64553225 -0.90790362]
[ 0.39694169 0.80099604 1. -0.37833504 -0.80337196]
[-0.67525773 -0.64553225 -0.37833504 1. 0.26594024]
[-0.72426278 -0.90790362 -0.80337196 0.26594024 1. ]]