链接:https://pan.quark.cn/s/35fc37047e5e

8-6 矩阵分解与低秩近似在推荐系统中的应用
------把"人 × 物"的大表格,压缩进几个有含义的隐藏维度
直觉先行:把用户--物品评分表看成一张巨大的"照片"。低秩近似就像用少量主色 来复原这张照片------虽然省下了大量像素,但仍抓住了最重要的结构。推荐系统中的矩阵分解,就是把用户和物品都嵌入到一个低维空间里:相似用户靠近,相似物品靠近,匹配就有高分。
1. 从"评分表"到"低秩"的故事
-
数据模型 :有 m m m 个用户、 n n n 个物品,构造评分矩阵 R ∈ R m × n R\in\mathbb{R}^{m\times n} R∈Rm×n。绝大多数条目是未知 (未互动),只观测到集合 Ω ⊆ { ( u , i ) } \Omega\subseteq\{(u,i)\} Ω⊆{(u,i)}。
-
低秩假设:用户兴趣与物品属性都可用少量隐向量解释。于是,
R ≈ P Q ⊤ , P ∈ R m × k , Q ∈ R n × k , k ≪ min ( m , n ) , R \approx P Q^\top,\quad P\in\mathbb{R}^{m\times k},\ Q\in\mathbb{R}^{n\times k},\ k\ll \min(m,n), R≈PQ⊤,P∈Rm×k, Q∈Rn×k, k≪min(m,n),
其中 p u p_u pu 是用户 u u u 的 k k k 维向量, q i q_i qi 是物品 i i i 的 k k k 维向量,预测 r ^ u i = p u ⊤ q i \hat r_{ui}=p_u^\top q_i r^ui=pu⊤qi。
生活类比:给每个用户和电影贴"口味标签"(动作、爱情、冷门、经典...),标签向量点积越大,就越可能喜欢。
2. SVD 与最佳低秩近似(全观测理想形态)
若 R R R 没有缺失 ,SVD 给出最优秩 k k k 近似(Eckart--Young 定理):
R = U Σ V ⊤ , R k = U k Σ k V k ⊤ = arg min r a n k ( X ) ≤ k ∥ R − X ∥ F . R = U\Sigma V^\top,\quad R_k = U_k \Sigma_k V_k^\top = \arg\min_{\mathrm{rank}(X)\le k}\|R-X\|_F. R=UΣV⊤,Rk=UkΣkVk⊤=argrank(X)≤kmin∥R−X∥F.
现实推荐是缺失极多 ,无法直接做 SVD,于是我们转向只在已观测处拟合的矩阵分解训练目标。
3. 显式反馈矩阵分解(带偏置)
3.1 目标函数
min P , Q , b ∑ ( u , i ) ∈ Ω ( r u i − μ − b u − b i − p u ⊤ q i ) 2 + λ ( ∑ u ( ∥ p u ∥ 2 + b u 2 ) + ∑ i ( ∥ q i ∥ 2 + b i 2 ) ) , \min_{P,Q,b}\;\sum_{(u,i)\in\Omega}\big(r_{ui}-\mu-b_u-b_i-p_u^\top q_i\big)^2 +\lambda\!\left(\sum_u(\|p_u\|^2+b_u^2)+\sum_i(\|q_i\|^2+b_i^2)\right), P,Q,bmin(u,i)∈Ω∑(rui−μ−bu−bi−pu⊤qi)2+λ(u∑(∥pu∥2+bu2)+i∑(∥qi∥2+bi2)),
其中 μ \mu μ 是全局均值, b u , b i b_u,b_i bu,bi 是用户/物品偏置(有人打分普遍更高或某电影普遍更受欢迎)。
3.2 两类常用优化
-
SGD(逐条样本)
设误差 e u i = r u i − r ^ u i e_{ui}=r_{ui}-\hat r_{ui} eui=rui−r^ui,学习率 η \eta η:
p u ← p u + η ( e u i q i − λ p u ) , q i ← q i + η ( e u i p u − λ q i ) , b u ← b u + η ( e u i − λ b u ) , b i ← b i + η ( e u i − λ b i ) . \begin{aligned} p_u &\leftarrow p_u + \eta\,(e_{ui} q_i-\lambda p_u),\quad q_i \leftarrow q_i + \eta\,(e_{ui} p_u-\lambda q_i),\\ b_u &\leftarrow b_u + \eta\,(e_{ui}-\lambda b_u),\quad b_i \leftarrow b_i + \eta\,(e_{ui}-\lambda b_i). \end{aligned} pubu←pu+η(euiqi−λpu),qi←qi+η(euipu−λqi),←bu+η(eui−λbu),bi←bi+η(eui−λbi).
-
ALS(交替最小二乘)
交替固定 Q Q Q 解 P P P,再固定 P P P 解 Q Q Q;每一步都是带 ∣ N ( u ) ∣ |\mathcal{N}(u)| ∣N(u)∣ 或 ∣ N ( i ) ∣ |\mathcal{N}(i)| ∣N(i)∣ 个样本的小型岭回归,并行友好、适合离线大规模训练。
#mermaid-svg-yXSFDJxFDiQChdTx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yXSFDJxFDiQChdTx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yXSFDJxFDiQChdTx .error-icon{fill:#552222;}#mermaid-svg-yXSFDJxFDiQChdTx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yXSFDJxFDiQChdTx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yXSFDJxFDiQChdTx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yXSFDJxFDiQChdTx .marker.cross{stroke:#333333;}#mermaid-svg-yXSFDJxFDiQChdTx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yXSFDJxFDiQChdTx p{margin:0;}#mermaid-svg-yXSFDJxFDiQChdTx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yXSFDJxFDiQChdTx .cluster-label text{fill:#333;}#mermaid-svg-yXSFDJxFDiQChdTx .cluster-label span{color:#333;}#mermaid-svg-yXSFDJxFDiQChdTx .cluster-label span p{background-color:transparent;}#mermaid-svg-yXSFDJxFDiQChdTx .label text,#mermaid-svg-yXSFDJxFDiQChdTx span{fill:#333;color:#333;}#mermaid-svg-yXSFDJxFDiQChdTx .node rect,#mermaid-svg-yXSFDJxFDiQChdTx .node circle,#mermaid-svg-yXSFDJxFDiQChdTx .node ellipse,#mermaid-svg-yXSFDJxFDiQChdTx .node polygon,#mermaid-svg-yXSFDJxFDiQChdTx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yXSFDJxFDiQChdTx .rough-node .label text,#mermaid-svg-yXSFDJxFDiQChdTx .node .label text,#mermaid-svg-yXSFDJxFDiQChdTx .image-shape .label,#mermaid-svg-yXSFDJxFDiQChdTx .icon-shape .label{text-anchor:middle;}#mermaid-svg-yXSFDJxFDiQChdTx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yXSFDJxFDiQChdTx .rough-node .label,#mermaid-svg-yXSFDJxFDiQChdTx .node .label,#mermaid-svg-yXSFDJxFDiQChdTx .image-shape .label,#mermaid-svg-yXSFDJxFDiQChdTx .icon-shape .label{text-align:center;}#mermaid-svg-yXSFDJxFDiQChdTx .node.clickable{cursor:pointer;}#mermaid-svg-yXSFDJxFDiQChdTx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yXSFDJxFDiQChdTx .arrowheadPath{fill:#333333;}#mermaid-svg-yXSFDJxFDiQChdTx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yXSFDJxFDiQChdTx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yXSFDJxFDiQChdTx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yXSFDJxFDiQChdTx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yXSFDJxFDiQChdTx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yXSFDJxFDiQChdTx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yXSFDJxFDiQChdTx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yXSFDJxFDiQChdTx .cluster text{fill:#333;}#mermaid-svg-yXSFDJxFDiQChdTx .cluster span{color:#333;}#mermaid-svg-yXSFDJxFDiQChdTx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yXSFDJxFDiQChdTx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yXSFDJxFDiQChdTx rect.text{fill:none;stroke-width:0;}#mermaid-svg-yXSFDJxFDiQChdTx .icon-shape,#mermaid-svg-yXSFDJxFDiQChdTx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yXSFDJxFDiQChdTx .icon-shape p,#mermaid-svg-yXSFDJxFDiQChdTx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yXSFDJxFDiQChdTx .icon-shape .label rect,#mermaid-svg-yXSFDJxFDiQChdTx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yXSFDJxFDiQChdTx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yXSFDJxFDiQChdTx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yXSFDJxFDiQChdTx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SGD
ALS
未收敛
已收敛
观测数据
选择优化方式
逐样本更新 参数
交替解 岭回归
收敛评估
得到用户与物品向量
图示:显式反馈矩阵分解的两种常用求解路径。
4. 隐式反馈:点击、浏览、购买的建模
评分常缺失,但点击/浏览/停留时长 等隐式信号丰富。常用加权回归建模(权重代表置信度):
-
定义偏好 p u i ∈ { 0 , 1 } p_{ui}\in\{0,1\} pui∈{0,1}:有过互动记为 1,无互动为 0。
-
置信度 c u i = 1 + α r u i c_{ui}=1+\alpha r_{ui} cui=1+αrui(或按次数/时长构造)。
-
目标:
\\min_{P,Q};\\sum_{u,i} c_{ui},(p_{ui}-p_u\^\\top q_i)\^2 * \\lambda\\left(\\sum_u\|p_u\|^2+\\sum_i\|q_i\|^2\\right).
权重让模型更重视"确实喜欢"的样本,同时不把所有未互动都当"强烈不喜欢"。
5. 排序优先:BPR 的成对学习
做 Top-K 推荐时,优化 RMSE 不如直接优化排序。**BPR(Bayesian Personalized Ranking)**用成对样本 ( u , i , j ) (u,i,j) (u,i,j)(用户看过 i i i 没看过 j j j)最大化:
max ∑ ( u , i , j ) log σ ( p u ⊤ q i − p u ⊤ q j ) − λ ( ∥ p u ∥ 2 + ∥ q i ∥ 2 + ∥ q j ∥ 2 ) . \max\ \sum_{(u,i,j)} \log \sigma\big( p_u^\top q_i - p_u^\top q_j \big) - \lambda(\|p_u\|^2+\|q_i\|^2+\|q_j\|^2). max (u,i,j)∑logσ(pu⊤qi−pu⊤qj)−λ(∥pu∥2+∥qi∥2+∥qj∥2).
SGD 更新把"正样本得分"拉高、"负样本得分"拉低,更贴近召回/排序任务。
6. 约束与可解释:NMF、正则与先验
- NMF(非负矩阵分解) :要求 P , Q ≥ 0 P,Q\ge 0 P,Q≥0,分解变成"加法部件",可解释性更强(例如"类型强度")。
- 正则化 : ℓ 2 \ell_2 ℓ2 常用, ℓ 1 \ell_1 ℓ1 稀疏化可让维度更"干净";也可用Dropout/DropEdge 思想做样本或维度的随机屏蔽。
- 侧信息融合 :把用户/物品属性(年龄、品类、文本 embedding)拼到向量里,或通过Factorization Machines 、多任务约束共享。
7. 从"低秩"到"嵌入":与深度模型的衔接
- 矩阵分解的 p u , q i p_u,q_i pu,qi 本质是嵌入向量。
- Neural MF:用 MLP 替代简单点积,学习更复杂的匹配函数;
- 二阶段推荐:第一阶段(召回)用 MF/图召回快速筛子,第二阶段(排序)用深模型(DIN、Transformer)细排;
- 图建模:用户--物品二分图上跑 GNN,隐式实现"聚合邻居"的低秩近似。
8. 训练与上线:一条实用流水线
#mermaid-svg-UrC3qcnJh7uDycNS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UrC3qcnJh7uDycNS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UrC3qcnJh7uDycNS .error-icon{fill:#552222;}#mermaid-svg-UrC3qcnJh7uDycNS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UrC3qcnJh7uDycNS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UrC3qcnJh7uDycNS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UrC3qcnJh7uDycNS .marker.cross{stroke:#333333;}#mermaid-svg-UrC3qcnJh7uDycNS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UrC3qcnJh7uDycNS p{margin:0;}#mermaid-svg-UrC3qcnJh7uDycNS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UrC3qcnJh7uDycNS .cluster-label text{fill:#333;}#mermaid-svg-UrC3qcnJh7uDycNS .cluster-label span{color:#333;}#mermaid-svg-UrC3qcnJh7uDycNS .cluster-label span p{background-color:transparent;}#mermaid-svg-UrC3qcnJh7uDycNS .label text,#mermaid-svg-UrC3qcnJh7uDycNS span{fill:#333;color:#333;}#mermaid-svg-UrC3qcnJh7uDycNS .node rect,#mermaid-svg-UrC3qcnJh7uDycNS .node circle,#mermaid-svg-UrC3qcnJh7uDycNS .node ellipse,#mermaid-svg-UrC3qcnJh7uDycNS .node polygon,#mermaid-svg-UrC3qcnJh7uDycNS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UrC3qcnJh7uDycNS .rough-node .label text,#mermaid-svg-UrC3qcnJh7uDycNS .node .label text,#mermaid-svg-UrC3qcnJh7uDycNS .image-shape .label,#mermaid-svg-UrC3qcnJh7uDycNS .icon-shape .label{text-anchor:middle;}#mermaid-svg-UrC3qcnJh7uDycNS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UrC3qcnJh7uDycNS .rough-node .label,#mermaid-svg-UrC3qcnJh7uDycNS .node .label,#mermaid-svg-UrC3qcnJh7uDycNS .image-shape .label,#mermaid-svg-UrC3qcnJh7uDycNS .icon-shape .label{text-align:center;}#mermaid-svg-UrC3qcnJh7uDycNS .node.clickable{cursor:pointer;}#mermaid-svg-UrC3qcnJh7uDycNS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UrC3qcnJh7uDycNS .arrowheadPath{fill:#333333;}#mermaid-svg-UrC3qcnJh7uDycNS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UrC3qcnJh7uDycNS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UrC3qcnJh7uDycNS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UrC3qcnJh7uDycNS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UrC3qcnJh7uDycNS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UrC3qcnJh7uDycNS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UrC3qcnJh7uDycNS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UrC3qcnJh7uDycNS .cluster text{fill:#333;}#mermaid-svg-UrC3qcnJh7uDycNS .cluster span{color:#333;}#mermaid-svg-UrC3qcnJh7uDycNS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UrC3qcnJh7uDycNS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UrC3qcnJh7uDycNS rect.text{fill:none;stroke-width:0;}#mermaid-svg-UrC3qcnJh7uDycNS .icon-shape,#mermaid-svg-UrC3qcnJh7uDycNS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UrC3qcnJh7uDycNS .icon-shape p,#mermaid-svg-UrC3qcnJh7uDycNS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UrC3qcnJh7uDycNS .icon-shape .label rect,#mermaid-svg-UrC3qcnJh7uDycNS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UrC3qcnJh7uDycNS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UrC3qcnJh7uDycNS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UrC3qcnJh7uDycNS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} A/B
行为日志
清洗 去重 采样
构造矩阵或样本
选择目标 RMSE 或 BPR
训练 MF 模型
离线评估 RMSE NDCG MAP
在线服务 向量检索
定期增量更新
图示:从日志到上线的主流程;"向量检索"可用 ANN(如 HNSW/IVF)加速在线 Top-K。
9. 一个手搓的小例子
假设 3 个用户 × 4 个电影(未评分记为"?"):
R = 5 4 ? 1 4 ? 2 1 ? 2 4 ? , k = 2. R= \begin{bmatrix} 5 & 4 & ? & 1\\ 4 & ? & 2 & 1\\ ? & 2 & 4 & ? \end{bmatrix},\quad k=2. R= 54?4?2?2411? ,k=2.
- 初始化 P , Q P,Q P,Q 随机;只对已观测条目做 SGD。
- 若采用偏置项,先减去全局均值再学 b u , b i b_u,b_i bu,bi。
- 训练若干轮后,得到 p u , q i p_u,q_i pu,qi。预测"?"处: r ^ u i = p u ⊤ q i + μ + b u + b i \hat r_{ui}=p_u^\top q_i + \mu + b_u + b_i r^ui=pu⊤qi+μ+bu+bi。
- Top-K 推荐:对用户 u u u 按 r ^ u i \hat r_{ui} r^ui 排序,取未看过的前 K K K。
观察:两个用户的向量夹角小,口味相似;两个电影的向量相近,可能属于同一风格。
10. 代码骨架(SGD 版,显式反馈)
python
import numpy as np
def train_mf_sgd(triples, m, n, k=64, lr=0.01, reg=1e-3, iters=10):
# triples: list of (u, i, r), u in [0,m), i in [0,n)
rng = np.random.default_rng(0)
P = 0.1 * rng.standard_normal((m, k))
Q = 0.1 * rng.standard_normal((n, k))
bu = np.zeros(m)
bi = np.zeros(n)
mu = np.mean([r for _,_,r in triples])
for _ in range(iters):
rng.shuffle(triples)
for u, i, r in triples:
pred = mu + bu[u] + bi[i] + P[u] @ Q[i]
e = r - pred
bu[u] += lr * (e - reg * bu[u])
bi[i] += lr * (e - reg * bi[i])
Pu = P[u].copy()
P[u] += lr * (e * Q[i] - reg * P[u])
Q[i] += lr * (e * Pu - reg * Q[i])
return P, Q, bu, bi, mu
实战提示:用小批量会更稳;隐式反馈或 BPR 需要改造样本生成与损失;工业场景常用 ALS 或分布式实现。
11. 评估指标与注意事项
- 回归型:RMSE/MAE(适合评分预测)。
- 排序型:HitRate@K、Precision@K、Recall@K、MAP、NDCG(更贴近首页推荐)。
- 采样偏置 :日志数据是被系统和用户选择过 的(MNAR),离线评估要谨慎;可引入反事实评估(IPS/DR)。
- 冷启动:新用户/新物品向量难学,结合内容特征(文本、图像、标签)或使用预训练嵌入初始化。
- 规模化 :稀疏存储、批量负采样、参数分片、ANN 检索;在线需延时与新鲜度权衡。
12. 常见变体与拓展
- 时间漂移:加入时间偏置或时间衰减,适配趋势变化。
- 上下文感知 :在 p u , q i p_u,q_i pu,qi 基础上引入上下文向量(位置、设备、节日),做 Context-Aware MF。
- 多目标:把"点击""加购""购买"多任务联合训练,共享底层嵌入。
- 与大模型结合 :物品标题/图片经大模型编码成向量,作为 q i q_i qi 的先验或初始化;召回后用 LLM/多模态模型二次重排。
13. 小结
- 低秩近似是"压缩结构"的数学语言;矩阵分解把用户与物品映射到同一向量空间,点积就是匹配分。
- 显式反馈 用带偏置的平方损失,隐式反馈 用置信度加权,BPR强调排序;ALS 与 SGD 是两条好用的优化路线。
- 在工业里,矩阵分解常作为召回主力:快、稳、可解释;与深度排序、图模型、LLM 重排配合,形成高性能推荐系统。
14. 练习
- 推导 ALS 中用户向量 p u p_u pu 的闭式更新:当固定 Q , b Q,b Q,b 时, ( A + λ I ) p u = b (A+\lambda I)p_u = b (A+λI)pu=b 的具体形式。
- 在隐式反馈目标中,证明当 c u i c_{ui} cui 足够大时,模型会强制 p u ⊤ q i p_u^\top q_i pu⊤qi 逼近 1。
- 实现 BPR-SGD,比较与回归损失在 NDCG@10 上的差异。
- 用带文本嵌入的 q i q_i qi 初始化与随机初始化对比,观察冷启动物品的提升。
- 设计一次 A/B:MF 召回 + ANN 检索 vs 仅用热门规则,记录 CTR、CVR、留存的变化。
附:两张小图
#mermaid-svg-0TGX7OP4d8Q7o8Ey{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .error-icon{fill:#552222;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .marker.cross{stroke:#333333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey p{margin:0;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .cluster-label text{fill:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .cluster-label span{color:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .cluster-label span p{background-color:transparent;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .label text,#mermaid-svg-0TGX7OP4d8Q7o8Ey span{fill:#333;color:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .node rect,#mermaid-svg-0TGX7OP4d8Q7o8Ey .node circle,#mermaid-svg-0TGX7OP4d8Q7o8Ey .node ellipse,#mermaid-svg-0TGX7OP4d8Q7o8Ey .node polygon,#mermaid-svg-0TGX7OP4d8Q7o8Ey .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .rough-node .label text,#mermaid-svg-0TGX7OP4d8Q7o8Ey .node .label text,#mermaid-svg-0TGX7OP4d8Q7o8Ey .image-shape .label,#mermaid-svg-0TGX7OP4d8Q7o8Ey .icon-shape .label{text-anchor:middle;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .rough-node .label,#mermaid-svg-0TGX7OP4d8Q7o8Ey .node .label,#mermaid-svg-0TGX7OP4d8Q7o8Ey .image-shape .label,#mermaid-svg-0TGX7OP4d8Q7o8Ey .icon-shape .label{text-align:center;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .node.clickable{cursor:pointer;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .arrowheadPath{fill:#333333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0TGX7OP4d8Q7o8Ey .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0TGX7OP4d8Q7o8Ey .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0TGX7OP4d8Q7o8Ey .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .cluster text{fill:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .cluster span{color:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0TGX7OP4d8Q7o8Ey rect.text{fill:none;stroke-width:0;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .icon-shape,#mermaid-svg-0TGX7OP4d8Q7o8Ey .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .icon-shape p,#mermaid-svg-0TGX7OP4d8Q7o8Ey .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .icon-shape .label rect,#mermaid-svg-0TGX7OP4d8Q7o8Ey .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0TGX7OP4d8Q7o8Ey .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0TGX7OP4d8Q7o8Ey .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0TGX7OP4d8Q7o8Ey :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 点积
点积
用户向量
打分
物品向量
排序 推荐列表
说明:用户与物品在同一向量空间点积,得到分数后排序。
#mermaid-svg-0XFqCkr5teXFESOO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0XFqCkr5teXFESOO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0XFqCkr5teXFESOO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0XFqCkr5teXFESOO .error-icon{fill:#552222;}#mermaid-svg-0XFqCkr5teXFESOO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0XFqCkr5teXFESOO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0XFqCkr5teXFESOO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0XFqCkr5teXFESOO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0XFqCkr5teXFESOO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0XFqCkr5teXFESOO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0XFqCkr5teXFESOO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0XFqCkr5teXFESOO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0XFqCkr5teXFESOO .marker.cross{stroke:#333333;}#mermaid-svg-0XFqCkr5teXFESOO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0XFqCkr5teXFESOO p{margin:0;}#mermaid-svg-0XFqCkr5teXFESOO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0XFqCkr5teXFESOO .cluster-label text{fill:#333;}#mermaid-svg-0XFqCkr5teXFESOO .cluster-label span{color:#333;}#mermaid-svg-0XFqCkr5teXFESOO .cluster-label span p{background-color:transparent;}#mermaid-svg-0XFqCkr5teXFESOO .label text,#mermaid-svg-0XFqCkr5teXFESOO span{fill:#333;color:#333;}#mermaid-svg-0XFqCkr5teXFESOO .node rect,#mermaid-svg-0XFqCkr5teXFESOO .node circle,#mermaid-svg-0XFqCkr5teXFESOO .node ellipse,#mermaid-svg-0XFqCkr5teXFESOO .node polygon,#mermaid-svg-0XFqCkr5teXFESOO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0XFqCkr5teXFESOO .rough-node .label text,#mermaid-svg-0XFqCkr5teXFESOO .node .label text,#mermaid-svg-0XFqCkr5teXFESOO .image-shape .label,#mermaid-svg-0XFqCkr5teXFESOO .icon-shape .label{text-anchor:middle;}#mermaid-svg-0XFqCkr5teXFESOO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0XFqCkr5teXFESOO .rough-node .label,#mermaid-svg-0XFqCkr5teXFESOO .node .label,#mermaid-svg-0XFqCkr5teXFESOO .image-shape .label,#mermaid-svg-0XFqCkr5teXFESOO .icon-shape .label{text-align:center;}#mermaid-svg-0XFqCkr5teXFESOO .node.clickable{cursor:pointer;}#mermaid-svg-0XFqCkr5teXFESOO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0XFqCkr5teXFESOO .arrowheadPath{fill:#333333;}#mermaid-svg-0XFqCkr5teXFESOO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0XFqCkr5teXFESOO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0XFqCkr5teXFESOO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0XFqCkr5teXFESOO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0XFqCkr5teXFESOO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0XFqCkr5teXFESOO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0XFqCkr5teXFESOO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0XFqCkr5teXFESOO .cluster text{fill:#333;}#mermaid-svg-0XFqCkr5teXFESOO .cluster span{color:#333;}#mermaid-svg-0XFqCkr5teXFESOO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0XFqCkr5teXFESOO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0XFqCkr5teXFESOO rect.text{fill:none;stroke-width:0;}#mermaid-svg-0XFqCkr5teXFESOO .icon-shape,#mermaid-svg-0XFqCkr5teXFESOO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0XFqCkr5teXFESOO .icon-shape p,#mermaid-svg-0XFqCkr5teXFESOO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0XFqCkr5teXFESOO .icon-shape .label rect,#mermaid-svg-0XFqCkr5teXFESOO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0XFqCkr5teXFESOO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0XFqCkr5teXFESOO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0XFqCkr5teXFESOO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 评分目标
平方损失
BPR 排序
SGD 或 ALS
SGD 成对更新
生成嵌入与服务
说明:不同目标与优化路径,均以生成嵌入并服务为终点。