召回

ZaynPei Lv6

基于物品的协同过滤 (Item-Based Collaborative Filtering, ItemCF)

ItemCF的原理:如果用户喜欢物品 1,而且物品 1 与物品 2 相似,那么用户很可能也喜欢物品 2。

这个原理非常直观。在现实生活中,如果你喜欢一部科幻电影(比如《星际穿越》),那么推荐系统很可能会向你推荐另一部评价很高、风格类似的科幻电影(比如《盗梦空间》),因为它假设这两部电影是”相似”的。ItemCF 就是将这种思想系统化和自动化。

它的核心优势在于,物品之间的相似性在大多数情况下是相对稳定的,比用户兴趣的稳定性要高。因此,可以预先离线计算好物品之间的相似度,从而在线上实现快速推荐。

当然,ItemCF 也有局限性。它无法发掘用户的潜在兴趣,推荐结果往往比较局限,新颖性不足。对于新物品还存在 冷启动 (Cold Start) 问题,因为它没有被评分,无法计算相似度。

计算两个物品之间相似度的公式

余弦相似度:

在隐式反馈场景,即只要用户喜欢过(比如点击过)like(u,i)=1的时候, 公式进一步退化为最后一项。

  • i1, i2:代表我们想要计算相似度的两个物品(例如,电影A和电影B)。
  • W1:喜欢物品 i1 的所有用户的集合。
  • W2:喜欢物品 i2 的所有用户的集合。
  • V = W1 ∩ W2:同时喜欢物品 i1i2 的所有用户的集合。这个交集是计算相似度的关键。
  • like(u, i):代表用户 u 对物品 i 的喜好程度。
    • 在隐式反馈场景中:如果用户 u 点击/播放/购买了物品 i,则 like(u, i) = 1,否则为 0。
    • 在显式反馈场景中:like(u, i) 可以是用户 u 对物品 i 的具体评分,比如 1 到 5 星。

分子 (Numerator)

含义:这部分计算的是两个物品被共同用户喜欢的程度的累积。

步骤说明: 1. 找到所有同时喜欢过 i1i2 的用户(即集合 V 中的每一个用户 v)。 2. 对于每一个这样的用户 v,取出他对 i1 的喜好分 like(v, i1) 和他对 i2 的喜好分 like(v, i2)。 3. 将这两个分数相乘。 4. 将所有共同用户的计算结果(乘积)全部加起来。

直观理解:如果共同喜欢这两个物品的用户,都给出了很高的评分,那么这个分子的值就会很大,说明这两个物品在”核心粉丝群”中的评价模式很一致。

分母 (Denominator)

含义:这部分是两个物品各自”热度”的体现,起到归一化 (Normalization) 的作用,旨在消除物品流行度带来的影响。

步骤说明: - 分母由两部分相乘构成: - 第一部分: - 找到所有喜欢物品 i1 的用户(集合 W1)。 - 计算每个用户对 i1 喜好程度的平方,并把它们全部加起来。 - 最后对这个总和开平方根。这在数学上被称为向量的 L2 范数 (L2-norm)。 - 第二部分: - 对物品 i2 进行完全相同的计算。

直观理解:一个物品越热门,喜欢它的用户(W1W2)就越多,它在分母上的值就越大。这就像一个惩罚项,可以降低超级热门物品与任何其他物品的相似度。

预估用户对候选物品的兴趣

计算出物品之间的相似度后,我们就可以为特定用户 u 预测他对某个候选物品 j 的兴趣度(或评分)了。

基本思路:

  1. 找到该用户 u 过去喜欢过的所有物品集合 S(u)。
  2. 对于候选物品 j,计算它和各个 S(u) 集合中物品的相似度。
  3. 用户 u 对物品 j 的兴趣度 P(u, j),可以通过加权平均的方式计算得出。

公式:

P(u, j) = ∑i ∈ S(u), i ≠ jlikeui ⋅ sim(i, j)

  • sim(i, j) 是物品 i 和物品 j 的相似度。
  • likeui 是用户 u 对物品 i 的喜好程度。
  • S(u) 是用户 u 过去有过行为的物品集合。

步骤说明:

  1. 遍历用户历史行为:我们查看用户 u 过去喜欢的每一个物品 i 。
  2. 查找相似度:找到物品 i 与目标物品 j 之间的相似度 。
  3. 加权求和:将这个相似度作为权重,乘以用户对物品 i 的喜好程度。
  4. 累加:将所有这些加权后的分数累加起来,就得到了用户 u 对物品 j 的最终兴趣预测分。分数越高,代表用户可能越喜欢它。

利用索引在线上快速做召回

在大型推荐系统中,物品数量可能达到百万甚至千万级别。如果每次推荐请求都实时计算所有物品的相似度和预测得分,计算量会非常巨大,无法满足线上服务的低延迟要求。

问题: 线上服务要求在几十毫秒内返回推荐结果,实时计算是不可行的。

解决方案:建立倒排索引 (Inverted Index)。

具体做法:

  1. 离线计算:在离线环境下,花费数小时甚至数天的时间,计算出所有物品两两之间的相似度。这是一个计算密集型任务。
  2. 存储相似物品:对于每一个物品 i,我们筛选出与它最相似的 K 个物品,并将这个关系 {i : [(j1, sim1), (j2, sim2), ...]} 存储起来。这个结构就是一个倒排索引:键(Key)是物品 i,值(Value)是一个列表,包含了与 i 最相似的物品及其相似度分数。
  3. 线上召回 (Retrieval):当一个用户 u 发出推荐请求时,系统执行以下快速操作:
      1. 获取该用户最近有过行为的物品列表(例如,最近点击的 10 个商品)。
      1. 对于列表中的每一个物品 i,通过倒排索引,瞬间查到与 i 最相似的物品集合。
      1. 将所有这些相似物品集合汇总、去重、排序,然后生成最终的推荐列表。

优势:

通过预计算和索引,线上的推荐过程从复杂的”计算”任务转变为高效的”查找”任务,极大地降低了响应时间,满足了实时推荐的需求。

基于模型的协同过滤 (Model-Based Collaborative Filtering, ModelCF)

基于模型的协同过滤算法,通过构建用户和物品的潜在特征矩阵,旨在从稀疏的评分数据中学习到能够描述用户和物品特性的隐因子 (Latent Factors)来预测用户对物品的兴趣。

矩阵分解 (Matrix Factorization, MF)

矩阵分解是基于模型的协同过滤算法中的一种,它将用户-物品评分矩阵分解为两个低维矩阵的乘积,从而揭示用户和物品的潜在特征

矩阵分解假设用户对物品的评分行为是由一些潜在的、无法直接观测到的共同因素决定的。例如,在电影推荐中,这些隐因子可能代表着电影的”喜剧成分”、“动作片成分”、“艺术性”,以及用户对这些成分的偏好程度。

它的目标是将原始的 用户-物品评分矩阵 R (大小为 m×n,m是用户数,n是物品数) 分解为两个低维度的 隐因子矩阵:用户因子矩阵 P (大小为 m×k)和物品因子矩阵 Q (大小为 n×k), 其中k是隐因子的数量,是一个远小于 m 和 n 的超参数 (k≪m,n)。

通过这两个矩阵,我们可以用它们的乘积来近似重构原始的评分矩阵:R ≈ P × QT

  • P 矩阵:每一行 pu 代表一个用户的 用户隐向量,描述了该用户在 k 个隐因子上的偏好程度。

  • Q 矩阵:每一行 qi 代表一个物品的 物品隐向量,描述了该物品在 k 个隐因子上的分布情况。

预测评分:用户 u 对物品 i 的预测评分 ui 就是他们对应隐向量的 点积 (Dot Product):

如何进行分解?—— 模型学习

由于原始评分矩阵 R 是高度稀疏的,我们无法直接进行像 奇异值分解 (Singular Value Decomposition, SVD) 这样的标准矩阵分解。因此,我们采用机器学习的方法来学习 P 和 Q 矩阵。

  1. 定义目标函数 (Objective Function): 我们的目标是让预测评分 ui 尽可能地接近已知的真实评分 rui。因此,我们定义一个基于均方根误差 (RMSE) 的损失函数,并为了防止过拟合 (Overfitting),加入 正则化项 (Regularization Term)。
  • minP, QL = ∑(u, i) ∈ K(rui − pu ⋅ qi)2 + λ(||pu||2 + ||qi||2)

  • K:所有已知的用户-物品评分对的集合。

  • (rui − pu ⋅ qi)2:平方误差项,衡量预测与真实的差距。我们只对已知的评分进行计算。

  • λ(||pu||2 + ||qi||2):L2 正则化项,用于惩罚隐向量中元素值过大的情况,增强模型的泛化能力。λ 是正则化系数。

  1. 优化求解: 常用的优化算法有两种:
  • 交替最小二乘法 (Alternating Least Squares, ALS)
    • 这是一个两阶段的迭代过程。首先,固定 Q 矩阵,此时目标函数是关于 P 的二次函数,可以直接求解得到最优的 P。然后,固定更新后的 P 矩阵,用同样的方法求解最优的 Q

    • 交替进行这两个步骤,直到收敛。ALS 的优点是易于并行化实现,尤其适用于处理大规模的隐式反馈数据。

  • 随机梯度下降 (Stochastic Gradient Descent, SGD)
    • 随机选择一个已知的评分 (u,i),计算损失函数puqi偏导数,并沿着梯度的反方向小步更新这两个向量。

    • 更新规则:

      其中,eui = rui − ui预测误差,η 是学习率

    • 通过大量迭代,不断地对 P 和 Q 进行微调,直到损失函数收敛。这种方法实现简单,计算速度快。

矩阵分解的优缺点

优点:

  • 处理稀疏数据能力强:通过低维的隐因子表示,极大地缓解了数据稀疏问题。
  • 泛化能力好:能够发现数据中潜在的关联模式,预测精度通常高于近邻方法。
  • 可扩展性强:模型训练好后,预测新评分的计算成本很低。

缺点:

  • 缺乏可解释性:学习到的隐因子通常没有明确的物理意义,难以向用户解释推荐的原因。
  • 冷启动问题依然存在:对于新用户或新物品,由于没有历史数据,无法为其生成隐向量。