推荐算法Chapter2.2 矩阵分解模型


1.矩阵分解

1.模型结构

1.1 模型核心原理

矩阵分解的核心思想是:每一个用户和每一个物品,都可以映射到一个低维的隐空间(Latent Space)中。

什么是隐向量

隐向量将用户和物品投影到了同一个低维空间,这使得它们具有了可比性

用户隐向量 ($p_u$):
  • 定义: 代表了用户 $u$ 在 $k$ 个潜在兴趣维度上的偏好权重。
  • 通俗解释: 假设 $k=2$,维度 1 代表“动作戏”,维度 2 代表“文艺范”。如果 $p_u = [0.9, 0.1]$,说明该用户极度热衷动作片,对文艺片无感。
    物品隐向量 ($q_i$):
  • 定义: 代表了物品 $i$ 在 $k$ 个潜在特征维度上的表现强度。
  • 通俗解释: 同样在上述空间中,如果电影《终结者》的 $q_i = [0.95, 0.05]$,说明它动作成分极高,几乎没有文艺成分。
为什么叫“隐”?

因为这些维度(如“动作戏”、“文艺范”)是模型自动学习出来的,在训练前我们并不知道第 1 维度代表什么。它们是数学上的投影,不一定能用人类语言完美描述,但它们捕捉到了数据中的内在结构。

假设我们有 $m$ 个用户和 $n$ 个物品,交互矩阵为 $R \in \mathbb{R}^{m \times n}$。
由于用户不可能消费所有物品,$R$ 是极度稀疏的。我们将其分解为两个稠密的低维矩阵:

  • 用户矩阵 $P \in \mathbb{R}^{m \times k}$:每一行 $p_u$ 是用户 $u$ 的隐向量。
  • 物品矩阵 $Q \in \mathbb{R}^{n \times k}$:每一行 $q_i$ 是物品 $i$ 的隐向量。

预测公式:

其中 $k$ 是隐向量的维度(通常比 $m, n$ 小得多),代表了潜在的特征(如:电影的导演、风格、演员等,虽然这些特征是模型自动学习出的,并不一定具有直观语义)。

训练流程:如何学习 $P$ 和 $Q$

矩阵分解的训练本质上是一个优化问题,目标是让预测评分 $\hat{r}_{ui}$ 尽可能接近真实评分 $r_{ui}$。

第一步:初始化

随机初始化 $P$ 和 $Q$ 矩阵中的元素(通常服从均值为 0、方差较小的正态分布)。

第二步:定义损失函数

使用带有 L2 正则化的平方损失函数:

第三步:选择优化算法进行迭代

常用的优化方法有两种:

1. 随机梯度下降 (SGD)
  • 流程: 遍历每一个已知的评分 $r_{ui}$,计算误差 $e_{ui} = r_{ui} - \hat{r}_{ui}$,然后根据梯度更新参数:
  • 优点:实现简单,速度快,适合处理超大规模数据。
2. 交替最小二乘法 (ALS)
  • 流程:由于 $P$ 和 $Q$ 同时变化时目标函数不是凸的,但如果固定 $Q$ 更新 $P$,或者固定 $P$ 更新 $Q$,问题就变成了线性最小二乘问题。
    • 固定 $Q$,利用最小二乘法更新 $P$。
    • 固定 $P$,利用最小二乘法更新 $Q$。
  • 优点:适合并行化计算(Spark 默认实现),处理隐式反馈效果好。

1.2 损失函数表达式

在矩阵分解(Matrix Factorization)中,最常用的带 L2 正则化的平方损失函数为:

参数含义:

  • $r_{ui}$:用户 $u$ 对物品 $i$ 的真实评分(Label)。
  • $q_i^T p_u$:模型预估评分(Prediction)。
  • $\lambda$:正则化系数(Hyperparameter),控制惩罚力度。
  • $| \cdot |^2$:L2 范数(每个元素的平方和)。

2. 正则化项的作用

  1. 抑制过拟合 (Overfitting)
    • 推荐数据极度稀疏,模型极易学习到噪声。
    • L2 正则化通过惩罚大的参数值,降低模型复杂度,使模型不至于为了拟合个别样本而让向量波动剧烈。
  2. 提升数值稳定性
    • 在梯度下降过程中,防止权重更新过大导致梯度爆炸。
    • 使目标函数变成严格凸函数(Strictly Convex),更容易收敛到稳定的局部最优解。
  3. 解决多重共线性
    • 当特征之间存在高度相关性时,正则化能有效约束参数空间。

3. L1 与 L2 正则化的对比

特性 L1 正则化 (Lasso) L2 正则化 (Ridge)
惩罚项 $\lambda \sum w_i $ $\lambda \sum w_i^2$
效果 倾向于产生稀疏解(部分权重为0) 倾向于产生稠密小值解
用途 特征选择(自动剔除无效特征) 防止过拟合,保证模型稳定性
贝叶斯先验 拉普拉斯分布 (Laplace) 高斯分布 (Gaussian)
为什么是这样

从贝叶斯统计学的视角来看,正则化项本质上是我们在观测数据之前,对模型参数 $\theta$ 所抱有的先验假设 (Prior Assumption)

1. 概率论背景:最大后验概率 (MAP)

模型学习的目标是最大化后验概率 $P(\theta|D)$。根据对数变换:

2. L2 正则化 <=> 高斯先验 (Gaussian Prior)

  • 假设:每个参数 $w_i$ 独立同分布地服从 $N(0, \sigma^2)$。
  • 推导: 高斯概率密度 取负对数得到
  • 物理意义:高斯分布的曲线在 0 附近是平滑的。它告诉模型:参数值不应该太大,但它们可以均匀地分布在 0 附近,这导致了参数的整体缩小 (Weight Decay)

3. L1 正则化 <=> 拉普拉斯先验 (Laplacian Prior)

  • 假设:每个参数 $w_i$ 独立同分布地服从 $Laplace(0, b)$。
  • 推导: 拉普拉斯概率密度 取负对数得到
  • 物理意义:拉普拉斯分布在 $w=0$ 处有一个非常尖的峰(导数不连续)。这意味着模型有极高的概率预设参数就是 0,从而促使模型产生稀疏性 (Sparsity)

4. 拓展:如何选择 $\lambda$?

  • 交叉验证 (Cross-Validation):在验证集上观察不同 $\lambda$ 下的 RMSE/MAE。
  • 经验法则
    • $\lambda$ 太小 $\rightarrow$ 模型依然过拟合(训练集效果好,测试集差)。
    • $\lambda$ 太大 $\rightarrow$ 模型欠拟合(训练集和测试集效果都差)。

5. 工业实践演进

  • Dropout:深度学习时代最常用的正则化手段,通过随机关闭神经元实现。
  • Early Stopping:在验证集性能不再提升时提前停止训练。
  • Embedding Normalization:在双塔模型中,对输出的向量进行 $L_2$ 归一化,使其映射到单位球面上,这可以看作是一种隐式的硬正则化。

2.FunkSVD 与传统 SVD

1. 传统 SVD 的“数学困境”

在数学定义中,奇异值分解(Singular Value Decomposition)将矩阵 $M$ 分解为 $U\Sigma V^T$。

  • 硬性要求:矩阵 $M$ 必须是稠密(Dense)的。
  • 推荐系统的现实:用户-物品矩阵 $R$ 极其稀疏(99% 为空)。
  • 后果:为了使用传统 SVD,你必须对缺失值进行填充(Imputation),如填充 0 或均值。这会导致矩阵体积爆炸,且引入的伪造数据会严重干扰预测精度。

2. FunkSVD 的“工程智慧”

由 Simon Funk 提出,它跳出了“分解”的数学框架,转而使用“拟合”的机器学习框架。

  • 核心逻辑:不再追求完美的数学分解,而是定义一个损失函数,只看已有的评分。
  • 预测公式:$\hat{r}_{ui} = p_u \cdot q_i^T$
  • 损失函数:
    注意:求和只针对 $\text{Observed}$(已观测到的数据),这完美解决了稀疏性问题。
训练过程

FunkSVD 的训练是一个基于 SGD(随机梯度下降) 的迭代过程,主要分为以下四个步骤:

第一步:参数初始化 (Initialization)

  • 随机初始化矩阵 $P$ 和 $Q$。
  • 通常使用均值为 0、方差较小的正态分布(如 $N(0, 0.1)$)。初始值不宜过大,否则内积结果容易爆炸,导致模型不收敛。

第二步:定义损失函数 (Loss Function)

  • 目标:让预测评分尽可能接近真实评分,同时防止过拟合。
  • 公式

    核心注意点:求和符号 $\sum$ 只针对已有的(非空)评分数据进行计算。

第三步:执行随机梯度下降 (Optimization via SGD)

  • 流程:遍历训练集中的每一个三元组 $(u, i, r_{ui})$。
  • 计算误差:$e_{ui} = r_{ui} - \hat{r}_{ui}$。
  • 梯度更新:根据损失函数对参数求偏导,得到更新公式: 其中 $\eta$ 是学习率(Learning Rate)。

第四步:收敛与存储

  • 重复迭代(Epochs),直到损失函数不再下降或达到预设次数。
  • 训练完成后,丢弃原始稀疏矩阵,只保留稠密的 $P$ 和 $Q$ 矩阵。

3.知识点讲解:随机梯度下降(SGD)优化矩阵分解

矩阵分解(MF)的训练目标是找到最优的用户隐向量 $p_u$ 和物品隐向量 $q_i$。由于目标函数通常不是简单的凸函数,我们采用随机梯度下降(SGD)这一迭代算法来寻找局部最优解。


1. 损失函数定义 (Loss Function)

为了保证模型既能拟合训练数据,又具备泛化能力,我们定义单个样本 $(u, i)$ 的损失函数如下:

其中:

  • $r_{ui}$ 是真实评分,$\hat{r}_{ui} = p_u \cdot q_i^T$ 是模型预测评分。
  • $\lambda (|p_u|^2 + |q_i|^2)$ 是 L2 正则化项,防止隐向量数值过大导致过拟合。

2. 参数更新公式推导 (Derivation)

我们需要通过求导找到损失函数下降最快的方向(负梯度方向)。

第一步:求偏导数

利用链式法则,分别对变量 $p_u$ 和 $q_i$ 求偏导:

  1. 对 $p_u$ 求偏导:

  2. 对 $q_i$ 求偏导:

第二步:参数更新

根据梯度下降公式 $\theta \leftarrow \theta - \eta \frac{\partial L}{\partial \theta}$(其中 $\eta$ 为学习率),我们将常数项 $2$ 合并到学习率中,得到最终更新公式:

  1. 用户向量更新:
  2. 物品向量更新:

3. 算法执行流程

  1. 初始化:随机初始化矩阵 $P$ 和 $Q$。
  2. 洗牌 (Shuffle):打乱训练集中三元组 $(u, i, r_{ui})$ 的顺序,防止模型产生周期性震荡。
  3. 迭代更新:遍历每个样本,计算误差并根据上述公式立即更新对应的 $p_u$ 和 $q_i$。
  4. 收敛检查:检查全量损失是否稳定或验证集指标是否下降。

4. 完整笔记与面试避坑

核心问题 关键答案
为什么叫“随机”? 因为它不像批量梯度下降 (BGD) 那样计算所有样本的梯度,而是每看到一个样本就更新一次参数。
学习率 $\eta$ 的作用? 步长。太大容易越过最优解(不收敛),太小收敛速度极慢。
正则化 $\lambda$ 的意义? 相当于给隐向量戴上“枷锁”,强制它们不要为了拟合单一噪声而变得过大。
SGD vs ALS? SGD 在非凸问题上更灵活;ALS 在分布式场景(并行计算)下效率更高。

5. 拓展:工业界常见的优化变体

  • Momentum (动量法):引入前一次更新的方向,帮助模型冲出“鞍点”或局部极小值。
  • Adam (自适应矩估计):为每个参数动态调整学习率,是目前最常用的优化器。
  • Bias-SVD:在更新公式中增加对 $b_u, b_i$(偏置项)的导数更新。

4.矩阵分解中的冷启动 (Cold Start)

冷启动问题是推荐系统的“顽疾”。这道面试题考察你是否理解矩阵分解(MF)的数学局限性,以及你是否有处理实际工程复杂性的经验。

1. 问题的根源 (Root Cause)

在矩阵分解中,预测评分公式为:$\hat{r}_{ui} = p_u \cdot q_i^T$。

  • 用户冷启动:新用户 $u_{new}$ 没有历史交互。在 SGD 训练过程中,没有样本去更新对应的 $p_{u_new}$,该向量保持初始化时的随机值,无法体现偏好。
  • 物品冷启动:新物品 $i_{new}$ 没有被消费过。没有样本去更新 $q_{i_new}$,模型无法得知该物品的“性格”。

2. 解决方案分类

解决冷启动的核心思想是“寻找外部辅助信息”来代替缺失的交互数据。

A. 用户冷启动方案 (User Cold Start)

  1. 非个性化兜底:推荐热门榜单(Popularity-based)、最新上架。
  2. 兴趣采集 (Onboarding):注册时让用户勾选标签(如“科技”、“健身”)。
  3. 人口属性画像:利用年龄、性别、职业,通过 Lookup 表 映射到一个初始隐向量。
  4. 多臂赌博机 (Bandit):通过 $Epsilon-Greedy$ 或 $UCB$ 算法,给予新用户多样化的探索机会。
$Epsilon-Greedy$与$UCB$算法
1. 核心背景:EE 困境
  • Exploitation (利用):展示用户最喜欢的,保证短期收益。
  • Exploration (探索):展示新物品或冷门物品,挖掘长期潜力,避免系统陷入“越推越窄”的死循环。
2. Epsilon-Greedy 策略
  • 算法原理
    • 设定探索率 $\epsilon$(如 5%)。
    • 每次决策时,有 $\epsilon$ 的概率随机选一个,有 $1-\epsilon$ 的概率选历史最优。
  • 优点:计算极其简单,不需存储复杂状态。
  • 缺点:探索没有针对性,且 $\epsilon$ 固定,后期可能造成收益损失。
3. UCB 策略 (置信区间上界)
  • 算法原理: 给每个物品算一个分数:$Score = \text{Mean_Reward} + \text{Uncertainty_Bonus}$
  • 核心逻辑
    1. 分母 $n_i$ 控制探索:如果物品被展示次数越少,得分越高。
    2. 分子 $\ln n$ 控制演进:随着总次数增加,对不确定性的容忍度缓慢提升。
  • 优点自适应探索。它会优先探索那些不确定性高的物品。
  • 缺点:处理非平稳(即兴趣随时间变化)的数据时,效果不如针对性改进的算法。

B. 物品冷启动方案 (Item Cold Start)

  1. 内容特征映射 (CB):利用物品的标题、类目、图片特征。使用 CNN/BERT 提取特征,再通过线性层映射到与 MF 相同的隐空间。
  2. 以老带新:计算新物品与老物品的内容相似度。如果新手机 A 和老手机 B 属性极像,就将 A 推给喜欢过 B 的人。
  3. 关联图谱:利用知识图谱(KG),根据新物品的品牌、产地关联到已有向量。
怎么“以老带新”

“以老带新”本质上是一种基于属性的特征迁移。当新物品没有交互数据时,我们强行给它找一个或多个“老大哥”,继承它们的流量。

1. 基于内容相似度的迁移 (Content-based Transfer)

这是最常见的方法。如果新物品 A 与老物品 B 在内容上高度相似,系统会认为喜欢 B 的用户大概率也会喜欢 A。

  • 操作流程
    1. 提取特征:使用 NLP(BERT/Word2Vec)处理标题,使用 CV(ResNet/Swin Transformer)处理封面图。
    2. 计算相似度:计算新物品 $i_{new}$ 与所有老物品 ${i_{old}}$ 的余弦相似度。
    3. 偏好继承:$\text{Score}(u, i_{new}) = \sum_{j \in \text{Similar Old Items}} \text{sim}(i_{new}, j) \cdot \text{Interest}(u, j)$。
2. 基于属性聚合的“代表向量” (Representative Vector)

对于某些品类,物品具有强烈的结构化属性(如品牌、类目、系列)。

  • 操作流程
    1. 计算类目中心向量:将同一类目(如:iPhone 15 系列)下所有老物品的隐向量 $q_{old}$ 取平均,得到一个类目 Embedding。
    2. 向量继承:新物品(iPhone 16)上架时,直接初始化为其所属类目的中心向量。
    3. 效果:这保证了新物品在模型还没训练时,就已经站在了“品牌/类目”的平均水平线上,而不是随机乱跑。
3. 知识图谱与实体关联 (KG-based)

利用外部知识库建立联系。

  • 场景:一部新电影上映。
  • 以老带新逻辑:新电影 $A$ 的导演是张艺谋,主演是沈腾。系统会自动寻找张艺谋和沈腾的其他老作品,将这些老作品的受众作为新电影 $A$ 的初始流量池。
4. 工业界大杀器:Look-alike 建模

Look-alike 原本用于广告扩量,但在冷启动中非常有效。

  • 逻辑
    1. 给新物品找一小群“种子用户”(比如通过内容匹配找到的硬核粉丝)。
    2. 利用 Look-alike 模型,在全站范围内寻找与这些种子用户行为特征最像的人。
    3. 将新物品推给这些“相似用户”。

5. 面试总结金句

“矩阵分解的冷启动本质上是参数未训练的问题。解决它的关键在于‘特征对齐’:即如何利用侧信息(Side Info)在缺乏交互的情况下,为新 ID 预估一个合理的初始 Embedding。在现代架构中,我们通常通过双塔模型或混合召回路径来平滑度过这个阶段。”
$$


Author: YANG
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source YANG !
  TOC