You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

推荐系统协同过滤中Python余弦相似度函数的范数计算原理问询

理解Numpy实现余弦相似度中的范数计算原理

先把你提到的这段实现代码贴出来:

import numpy as np

def similarity(ratings, kind='user', epsilon=1e-9):
    if kind == 'user' :
        sim = ratings.dot(ratings.T)
    elif (kind=='item'):
        sim = ratings.T.dot(ratings) + epsilon
    norms = np.array([np.sqrt(np.diagonal(sim))])
    return (sim / norms / norms.T )

接下来我一步步给你拆解范数计算背后的数学逻辑,其实核心就是紧扣余弦相似度的定义:

1. 先回忆余弦相似度的核心公式

两个向量 $\boldsymbol{u}$ 和 $\boldsymbol{v}$ 的余弦相似度,本质是它们的点积除以两个向量的L2范数(欧几里得范数)的乘积,公式是:
$$
\text{cosine similarity}(\boldsymbol{u}, \boldsymbol{v}) = \frac{\boldsymbol{u} \cdot \boldsymbol{v}}{||\boldsymbol{u}|| \times ||\boldsymbol{v}||}
$$
其中 $||\boldsymbol{u}|| = \sqrt{u_1^2 + u_2^2 + ... + u_n^2}$,也就是向量自身点积的平方根:$||\boldsymbol{u}|| = \sqrt{\boldsymbol{u} \cdot \boldsymbol{u}}$。

2. 先搞懂sim矩阵的意义

  • 当kind='user'时,ratings是用户-物品评分矩阵(假设形状是$U \times I$,U是用户数,I是物品数),ratings.dot(ratings.T)会生成一个$U \times U$的矩阵,其中第$(i,j)$个元素就是用户i的评分向量和用户j的评分向量的点积 $\boldsymbol{u}_i \cdot \boldsymbol{u}_j$。
  • 当kind='item'时,ratings.T.dot(ratings)生成$I \times I$的矩阵,第$(m,n)$个元素是物品m的评分向量和物品n的评分向量的点积 $\boldsymbol{v}_m \cdot \boldsymbol{v}_n$。

3. 范数norms的计算逻辑

np.diagonal(sim)会提取sim矩阵的对角线元素:

  • 对用户模式来说,对角线元素是$\boldsymbol{u}_i \cdot \boldsymbol{u}_i$,也就是用户i评分向量自身的点积,这正好等于$||\boldsymbol{u}_i||^2$(L2范数的平方)。
  • 对物品模式同理,对角线元素是$\boldsymbol{v}_m \cdot \boldsymbol{v}_m = ||\boldsymbol{v}_m||^2$。

然后np.sqrt(...)把这些平方值开根号,就得到了每个用户(或物品)向量的L2范数。最后用np.array([...])把结果转成行向量(形状是$1 \times U$或$1 \times I$),方便后续的广播运算。

4. 最后一步的广播除法是关键

sim / norms / norms.T利用了Numpy的广播机制,完美对应余弦相似度的计算:

  • 第一步sim / norms:把$U \times U$的sim矩阵的每一行,都除以行向量norms中对应的元素(也就是每个用户i的范数$||\boldsymbol{u}_i||$),此时矩阵的$(i,j)$元素变成$\frac{\boldsymbol{u}_i \cdot \boldsymbol{u}_j}{||\boldsymbol{u}_i||}$。
  • 第二步再除以norms.T(转成列向量,形状$U \times 1$):把每一列再除以对应的用户j的范数$||\boldsymbol{u}_j||$,最终$(i,j)$元素就变成$\frac{\boldsymbol{u}_i \cdot \boldsymbol{u}_j}{||\boldsymbol{u}_i|| \times ||\boldsymbol{u}_j||}$,完全符合余弦相似度的公式!

另外提一句,物品模式里加了epsilon是为了避免某个物品没有任何评分时,范数为0导致除零错误,这个小细节是为了提升代码的鲁棒性。


内容的提问来源于stack exchange,提问作者Nithin Varghese

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:41:08