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. 正则化项的作用
- 抑制过拟合 (Overfitting):
- 推荐数据极度稀疏,模型极易学习到噪声。
- L2 正则化通过惩罚大的参数值,降低模型复杂度,使模型不至于为了拟合个别样本而让向量波动剧烈。
- 提升数值稳定性:
- 在梯度下降过程中,防止权重更新过大导致梯度爆炸。
- 使目标函数变成严格凸函数(Strictly Convex),更容易收敛到稳定的局部最优解。
- 解决多重共线性:
- 当特征之间存在高度相关性时,正则化能有效约束参数空间。
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$ 求偏导:
对 $p_u$ 求偏导:
对 $q_i$ 求偏导:
第二步:参数更新
根据梯度下降公式 $\theta \leftarrow \theta - \eta \frac{\partial L}{\partial \theta}$(其中 $\eta$ 为学习率),我们将常数项 $2$ 合并到学习率中,得到最终更新公式:
- 用户向量更新:
- 物品向量更新:
3. 算法执行流程
- 初始化:随机初始化矩阵 $P$ 和 $Q$。
- 洗牌 (Shuffle):打乱训练集中三元组 $(u, i, r_{ui})$ 的顺序,防止模型产生周期性震荡。
- 迭代更新:遍历每个样本,计算误差并根据上述公式立即更新对应的 $p_u$ 和 $q_i$。
- 收敛检查:检查全量损失是否稳定或验证集指标是否下降。
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)
- 非个性化兜底:推荐热门榜单(Popularity-based)、最新上架。
- 兴趣采集 (Onboarding):注册时让用户勾选标签(如“科技”、“健身”)。
- 人口属性画像:利用年龄、性别、职业,通过 Lookup 表 映射到一个初始隐向量。
- 多臂赌博机 (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}$
- 核心逻辑:
- 分母 $n_i$ 控制探索:如果物品被展示次数越少,得分越高。
- 分子 $\ln n$ 控制演进:随着总次数增加,对不确定性的容忍度缓慢提升。
- 优点:自适应探索。它会优先探索那些不确定性高的物品。
- 缺点:处理非平稳(即兴趣随时间变化)的数据时,效果不如针对性改进的算法。
B. 物品冷启动方案 (Item Cold Start)
- 内容特征映射 (CB):利用物品的标题、类目、图片特征。使用 CNN/BERT 提取特征,再通过线性层映射到与 MF 相同的隐空间。
- 以老带新:计算新物品与老物品的内容相似度。如果新手机 A 和老手机 B 属性极像,就将 A 推给喜欢过 B 的人。
- 关联图谱:利用知识图谱(KG),根据新物品的品牌、产地关联到已有向量。
怎么“以老带新”
“以老带新”本质上是一种基于属性的特征迁移。当新物品没有交互数据时,我们强行给它找一个或多个“老大哥”,继承它们的流量。
1. 基于内容相似度的迁移 (Content-based Transfer)
这是最常见的方法。如果新物品 A 与老物品 B 在内容上高度相似,系统会认为喜欢 B 的用户大概率也会喜欢 A。
- 操作流程:
- 提取特征:使用 NLP(BERT/Word2Vec)处理标题,使用 CV(ResNet/Swin Transformer)处理封面图。
- 计算相似度:计算新物品 $i_{new}$ 与所有老物品 ${i_{old}}$ 的余弦相似度。
- 偏好继承:$\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)
对于某些品类,物品具有强烈的结构化属性(如品牌、类目、系列)。
- 操作流程:
- 计算类目中心向量:将同一类目(如:iPhone 15 系列)下所有老物品的隐向量 $q_{old}$ 取平均,得到一个类目 Embedding。
- 向量继承:新物品(iPhone 16)上架时,直接初始化为其所属类目的中心向量。
- 效果:这保证了新物品在模型还没训练时,就已经站在了“品牌/类目”的平均水平线上,而不是随机乱跑。
3. 知识图谱与实体关联 (KG-based)
利用外部知识库建立联系。
- 场景:一部新电影上映。
- 以老带新逻辑:新电影 $A$ 的导演是张艺谋,主演是沈腾。系统会自动寻找张艺谋和沈腾的其他老作品,将这些老作品的受众作为新电影 $A$ 的初始流量池。
4. 工业界大杀器:Look-alike 建模
Look-alike 原本用于广告扩量,但在冷启动中非常有效。
- 逻辑:
- 给新物品找一小群“种子用户”(比如通过内容匹配找到的硬核粉丝)。
- 利用 Look-alike 模型,在全站范围内寻找与这些种子用户行为特征最像的人。
- 将新物品推给这些“相似用户”。
5. 面试总结金句
“矩阵分解的冷启动本质上是参数未训练的问题。解决它的关键在于‘特征对齐’:即如何利用侧信息(Side Info)在缺乏交互的情况下,为新 ID 预估一个合理的初始 Embedding。在现代架构中,我们通常通过双塔模型或混合召回路径来平滑度过这个阶段。”
$$