导语: 推荐系统已经渗透到我们生活的方方面面——淘宝的商品、抖音的视频、知乎的回答、Spotify 的歌单、小红书的内容。本文从最传统的推荐方法一路讲到最前沿的研究方向,用尽量通俗的语言完整梳理推荐系统的技术演进脉络。
一、为什么推荐系统如此重要
在信息爆炸的时代,核心问题不再是”信息不够多”,而是”注意力不够用”。假设你在淘宝上有 1000 万种商品,在抖音上有数亿条视频,你一天能看完多少?所以平台需要帮你筛选——这就是推荐系统的任务。
推荐系统的本质就是在海量物品和有限用户注意力之间架桥。
从商业角度看,推荐系统直接驱动了平台的核心增长飞轮:更好的推荐 → 更高的用户参与度 → 更多的数据 → 更好的推荐。
二、第一阶段:规则与统计时代(1990s 以前)
1. 基于内容的推荐(Content-Based Filtering)
一句话解释: 你看过什么,我就给你推荐跟它相似的东西。
具体怎么做? 分三步:
- 给物品打标签。 比如一部电影,它的标签可以是:科幻、动作、科幻大师诺兰执导、主演克里斯蒂安·贝尔。
- 建用户画像。 如果你连续看了《星际穿越》《盗梦空间》《信条》,系统就判断你喜欢”科幻”和”诺兰”。
- 做匹配。 系统从你还没看过的电影里,找出标签里也有”科幻”的推荐给你。
经典算法:
TF-IDF(词频-逆文档频率): 用来给文本特征打分,判断某个词对某部电影的”重要程度”。计算分两步:
第一步,TF(词频) 衡量一个词在这部电影中出现得有多频繁:
$$TF(t, d) = \frac{\text{词 } t \text{ 在文档 } d \text{ 中出现的次数}}{\text{文档 } d \text{ 的总词数}}$$
比如《星际穿越》全文 5000 字,”时间”出现了 80 次,那么 $TF(\text{时间}, \text{星际穿越}) = 80/5000 = 0.016$。第二步,IDF(逆文档频率) 衡量这个词在所有电影中有多”稀有”——越稀有的词,区分度越高:
$$IDF(t) = \log\frac{N}{df(t)}$$
其中 $N$ 是电影总数,$df(t)$ 是包含词 $t$ 的电影数。比如有 10000 部电影,”科幻”出现了 5000 部,$df(\text{科幻}) = 5000$,$IDF = \log(10000/5000) = \log 2 \approx 0.69$;而”诺兰”只出现在 10 部电影里,$IDF = \log(10000/10) = \log 1000 \approx 6.91$。显然”诺兰”的区分度远高于”科幻”。最后 TF-IDF = TF × IDF。某个词在某部电影中既常见(TF 高),又在整体中稀有(IDF 高),那它就构成了这部电影的”核心标签”。
KNN(最近邻): 计算两部电影的特征向量之间的相似度,越相似推荐概率越高。最常用的相似度度量是余弦相似度:
$$\text{Cosine}(A, B) = \frac{A \cdot B}{|A| \times |B|} = \frac{\sum _{i=1}^{n} A _i B _i}{\sqrt{\sum _{i=1}^{n} A _i^2} \times \sqrt{\sum _{i=1}^{n} B _i^2}}$$
具体怎么算?假设用三个标签维度来描述电影:[科幻,动作,诺兰]。电影 X 的特征向量是 A = [0.9, 0.3, 0.8],电影 Y 的特征向量是 B = [0.8, 0.2, 0.9]。- 分子(点积):$A \cdot B = 0.9 \times 0.8 + 0.3 \times 0.2 + 0.8 \times 0.9 = 0.72 + 0.06 + 0.72 = 1.50$
- 分母(模长乘积):$|A| = \sqrt{0.9^2 + 0.3^2 + 0.8^2} = \sqrt{0.81 + 0.09 + 0.64} = \sqrt{1.54} \approx 1.24$,同理 $|B| = \sqrt{0.8^2 + 0.2^2 + 0.9^2} = \sqrt{0.64 + 0.04 + 0.81} = \sqrt{1.49} \approx 1.22$
- 余弦相似度:$\text{Cosine} = \frac{1.50}{1.24 \times 1.22} = \frac{1.50}{1.51} \approx 0.99$
接近 1,说明两部电影非常相似。如果余弦相似度等于 0,说明完全正交(毫无相似之处);等于 -1,说明完全相反(一般不会出现)。
局限性: 你只能看到你”可能已经喜欢”的东西。比如你可能从来没看过动画电影,但推荐系统永远不会给你推荐——因为你没有看动画电影的历史,它不知道你喜欢这个。
2. 关联规则(Association Rules)
一句话解释: 找出那些经常被一起买(或一起看)的物品组合。
经典场景: 啤酒与尿布的传说。据说超市发现,买啤酒的顾客也有较大概率买尿布,于是把它们摆在一起,销量都涨了。
核心算法:
- Apriori: 这是最经典的关联规则算法。它的工作方式是”逐层搜索”——先找出所有经常被单独购买的物品(比如”面包”被买了 1000 次),然后找经常一起出现的物品对(比如”面包+牛奶”一起出现了 300 次),再找三个物品的组合,以此类推。其核心思想是先验性质:如果某个物品集不频繁,那么它的所有超集也一定不频繁(Apriori 性质),由此可以大幅剪枝搜索空间。
- FP-Growth: Apriori 的改进版,通过构建 FP-Tree(频繁模式树)来压缩数据,只需扫描两次数据库即可挖掘所有频繁项集,速度更快。
核心输出格式: {啤酒} → {尿布}(置信度 60%,支持度 10%)
这个输出背后有三个指标,分别衡量这条规则的”价值”。让我们用数字把每个指标算清楚。
假设一个超市一周共有 1000 笔交易,其中 100 笔同时买了啤酒和尿布,200 笔买了啤酒,150 笔买了尿布。
支持度(Support) 衡量这条规则覆盖了多少交易:
$$\text{Support}(\text{啤酒} \Rightarrow \text{尿布}) = \frac{|{\text{同时包含啤酒和尿布的交易}}|}{|\text{总交易数}|} = \frac{100}{1000} = 0.10 = 10%$$
意思是:在所有交易中,有 10% 的交易同时买了啤酒和尿布。
置信度(Confidence) 衡量买了啤酒的人中有多少人买了尿布:
$$\text{Confidence}(\text{啤酒} \Rightarrow \text{尿布}) = \frac{\text{Support}(\text{啤酒} \cup \text{尿布})}{\text{Support}(\text{啤酒})} = \frac{0.10}{0.20} = 0.50 = 50%$$
也就是说,买了啤酒的人中,有 50% 的人同时买了尿布。
提升度(Lift) 衡量”买啤酒”对”买尿布”的促进作用:
$$\text{Lift}(\text{啤酒} \Rightarrow \text{尿布}) = \frac{\text{Confidence}}{\text{Support}(\text{尿布})} = \frac{0.50}{0.15} \approx 3.33$$
Lift = 3.33 > 1,说明买啤酒的人确实更有可能买尿布,而且概率是不买啤酒人群的 3.33 倍。如果 Lift = 1,说明”买啤酒”和”买尿布”完全无关;如果 Lift < 1,说明它们甚至互相排斥(买了啤酒反而不太可能买尿布)。
局限性: 它只能发现”谁和谁常一起出现”,但不能解释”为什么”。而且它不考虑每个人的个人偏好——对所有人都用同一套规则。
三、第二阶段:协同过滤时代(1990s–2010s)
1. User-Based 协同过滤
一句话解释: “和你品味相似的人也喜欢这个,所以你可能也喜欢。”
具体怎么做? 分两步:
- 找相似用户。 假设你有 5 部电影评分:A(5分)、B(4分)、C(3分)、D(1分)、E(2分)。系统找到和你评分模式最像的另外 10 个人。
- 取他们喜欢、但你不喜欢的。 假设这 10 个人中有 8 个人都给了电影 F 高分,但你还没看过 F,那系统就会把 F 推荐给你。
核心思路: 品味相似的用户,大概率也会喜欢相似的东西。
用户相似度怎么算? 最常用的度量是余弦相似度(减去平均值后的版本)。假设用户 A 和用户 B 都对 3 部电影评过分,评分如下表:
| 电影 | 用户 A | 用户 B |
|---|---|---|
| 《星际穿越》 | 5 | 4 |
| 《盗梦空间》 | 4 | 3 |
| 《泰坦尼克号》 | 1 | 2 |
先算平均评分:$\bar{r} _A = (5+4+1)/3 = 3.33$,$\bar{r} _B = (4+3+2)/3 = 3.00$。用减去均值后的评分来计算相似度:
$$\text{sim}(A, B) = \frac{\sum _{i \in I _{AB}} (r _{Ai} - \bar{r} _A)(r _{Bi} - \bar{r} _B)}{\sqrt{\sum _{i \in I _{AB}} (r _{Ai} - \bar{r} _A)^2} \times \sqrt{\sum _{i \in I _{AB}} (r _{Bi} - \bar{r} _B)^2}}$$
具体计算:
- 分子:$(5-3.33)(4-3.00) + (4-3.33)(3-3.00) + (1-3.33)(2-3.00) = 1.67 \times 1.00 + 0.67 \times 0.00 + (-2.33) \times (-1.00) = 1.67 + 0 + 2.33 = 4.00$
- 分母:$\sqrt{1.67^2 + 0.67^2 + 2.33^2} \times \sqrt{1.00^2 + 0.00^2 + 1.00^2} = \sqrt{2.79 + 0.45 + 5.43} \times \sqrt{1 + 0 + 1} = \sqrt{8.67} \times \sqrt{2} \approx 2.94 \times 1.41 = 4.15$
- 相似度:$\text{sim}(A, B) = 4.00 / 4.15 \approx 0.96$
接近 1,说明用户 A 和用户 B 的品味高度一致。
评分预测: 找到与用户 u 最相似的 k 个邻居后,预测用户 u 对物品 i 的评分:
$$\hat{r} _{ui} = \bar{r} _u + \frac{\sum _{v \in N _u(k)} \text{sim}(u, v) \times (r _{vi} - \bar{r} _v)}{\sum _{v \in N _u(k)} |\text{sim}(u, v)|}$$
具体怎么算?假设用户 C 还没看《盗梦空间》,我们想用用户 A 和用户 B 帮他预测。已知:$\bar{r} _C = 3.0$,用户 A 对《盗梦空间》评分 4,相似度 0.96;用户 B 对《盗梦空间》评分 3,相似度 0.90。
- 分子:$0.96 \times (4 - 3.33) + 0.90 \times (3 - 3.00) = 0.96 \times 0.67 + 0.90 \times 0.00 = 0.64 + 0 = 0.64$
- 分母:$0.96 + 0.90 = 1.86$
- 预测评分:$\hat{r} _{C, \text{盗梦空间}} = 3.00 + 0.64 / 1.86 = 3.00 + 0.34 = 3.34$
用户 C 预计会给《盗梦空间》打 3.34 分。
局限性: 当用户量达到千万级时,计算”你和所有人的相似度”计算量巨大。而且很多用户可能只看过很少的物品,很难找到足够相似的人。
2. Item-Based 协同过滤
一句话解释: “喜欢这个物品的人,也喜欢那个。”
具体怎么做?
- 计算物品相似度。 所有给电影 A 评分的人,和所有给电影 B 评分的人,看看他们的评分模式是否相似。如果给 A 高分的人也给 B 高分,那 A 和 B 就相似。
- 给用户推荐相似物品。 如果你给电影 A 打了 5 分,系统找出和 A 最相似的 10 部电影(但你还没看过的),推荐给你。
为什么 ItemCF 比 UserCF 更流行?
- 物品相似度相对稳定。 今天和 A 相似的电影,明天大概率还是相似的;但”和你品味相似的人”可能每天都在变。
- 可以离线计算。 物品相似度矩阵可以提前算好,线上推荐时只需要查表。
- 适合电商。 电商的物品数量比用户少得多,计算物品相似度更划算。
物品相似度怎么算? 用最简洁的 Jaccard 风格公式:
$$\text{sim}(A, B) = \frac{|N(A) \cap N(B)|}{\sqrt{|N(A)| \times |N(B)|}}$$
其中 $N(A)$ 是购买过物品 A 的用户集合。举个例子:
- 买了电影 A 的用户:${\text{张三, 李四, 王五, 赵六, 钱七}}$,共 5 人
- 买了电影 B 的用户:${\text{张三, 李四, 王五, 孙八, 周九}}$,共 5 人
- 交集:${\text{张三, 李四, 王五}}$,共 3 人
- 相似度:$\text{sim}(A, B) = 3 / \sqrt{5 \times 5} = 3 / 5 = 0.60$
评分预测: 假设用户 u 给电影 A 打了 5 分,与 A 最相似的两部电影是 B(相似度 0.60,u 打了 4 分)和 C(相似度 0.40,u 打了 3 分)。预测 u 对电影 D 的评分(D 与 B 的相似度 0.70,与 C 的相似度 0.50):
$$\hat{r} _{ui} = \frac{\sum _{j \in S(i, k) \cap R _u} w _{ij} \times r _{uj}}{\sum _{j \in S(i, k) \cap R _u} |w _{ij}|} = \frac{0.70 \times 4 + 0.50 \times 3}{0.70 + 0.50} = \frac{2.8 + 1.5}{1.2} = \frac{4.3}{1.2} \approx 3.58$$
用户 u 预计会给电影 D 打 3.58 分。
局限性: 对新物品完全没用——刚上架的电影没有人给它评过分,它就永远不会被推荐。
3. 矩阵分解(Matrix Factorization, MF)
一句话解释: 把”用户-物品评分表”压缩成两个小表格,每个用户和每个物品各有一组”隐向量”,它们的点积就能近似原始评分。
详细解释:
想象一个用户-物品评分矩阵,行是用户,列是物品,格子里是评分。但这个矩阵极其稀疏——大多数格子是空的(你没看过的东西怎么评分?)。
矩阵分解的核心想法是:虽然矩阵很稀疏,但用户的兴趣和物品的属性其实由少数几个”隐因子”决定。
比如电影可能有这些隐因子:科幻程度、浪漫程度、喜剧程度、动作程度。每个用户对这四个因子的偏好不同,每部电影在这四个因子上的得分也不同。
数学上: 假设你有 N 个用户和 M 个物品,我们试图找到两个矩阵:
- 用户矩阵 U(N 行 × k 列),每行是一个用户的隐向量
- 物品矩阵 V(M 行 × k 列),每行是一个物品的隐向量
使得 $U \times V^T \approx$ 原始评分矩阵 $R$
其中 k 是隐向量的维度(通常 50~256),远小于 N 和 M。
优化目标:
$$\min _{U, V} \sum _{(u, i) \in \Omega} (r _{ui} - \hat{r} _{ui})^2 + \lambda (|U| _F^2 + |V| _F^2)$$
其中 $\Omega$ 是已知的评分集合,$\hat{r} _{ui} = u _u^T v _i$(用户隐向量与物品隐向量的点积),$\lambda$ 是正则化系数,$|\cdot| _F$ 是 Frobenius 范数。
SGD 更新规则:
$$e _{ui} = r _{ui} - u _u^T v _i$$
$$u _u \leftarrow u _u + \gamma (e _{ui} \cdot v _i - \lambda \cdot u _u)$$
$$v _i \leftarrow v _i + \gamma (e _{ui} \cdot u _u - \lambda \cdot v _i)$$
其中 $\gamma$ 是学习率,$e _{ui}$ 是预测误差。每次只更新一个已知的 $(u,i)$ 对。
经典算法:
- SVD(奇异值分解): 最经典的矩阵分解方法,但要求矩阵完整(不能有缺失值),而实际评分矩阵大量缺失。
- SVD++: SVD 的改进版,把用户的隐式反馈(比如点击、浏览)也考虑进来。
- ALS(交替最小二乘法): Netflix Prize 比赛的核心算法。思路是:先固定用户矩阵 U,用最小二乘法解出最优的物品矩阵 V;然后固定 V,解出最优的 U。交替进行,直到收敛。
- MF(Matrix Factorization): 用随机梯度下降(SGD)直接优化 U 和 V,使预测评分和实际评分的差距最小。
优势:
- 隐向量可以捕捉比显性标签更复杂的用户-物品关系
- 缓解了数据稀疏性问题——即使某个用户只评了 3 个分,也能通过隐向量找到其他相似用户的信息
四、第三阶段:特征工程 + 机器学习时代(2010–2014)
1. 特征工程驱动
互联网大厂(尤其是 Google、Facebook)开始构建大规模的特征体系。
什么是特征工程? 简单说就是把用户、物品、场景的各种信息整理成机器能理解的数字格式。
- 用户侧特征: 年龄、性别、注册时长、今天活跃了几次、平均每天花多少时间、昨晚几点睡……
- 物品侧特征: 类别、价格、上架时间、历史点击率、平均评分……
- 交叉特征: 这是最关键的——用户和物品的组合特征。比如”一个 25 岁的女性用户看到一件女装广告”这个交叉特征,比单独的”25 岁”或”女装”都有信息量。
问题: 人工设计交叉特征非常累,而且很难穷举所有可能的组合。
2. 逻辑回归(LR)
为什么推荐 LR? 因为它简单、可解释、线上推理极快。
LR 的输出是:用户点击某条广告的概率 = σ(w₁x₁ + w₂x₂ + … + wₙxₙ),其中 σ 是 sigmoid 函数(把任意实数压缩到 0~1 之间),x 是特征,w 是权重。
数学公式:
$$P(y=1 \mid x) = \sigma(w^T x + b) = \frac{1}{1 + e^{-(w^T x + b)}}$$
损失函数(交叉熵):
$$\mathcal{L} = -\frac{1}{N} \sum _{i=1}^{N} [y _i \log(\hat{y} _i) + (1-y _i) \log(1-\hat{y} _i)]$$
其中 $\hat{y} _i = \sigma(w^T x _i + b)$,$y _i \in {0, 1}$ 是真实标签。
关键问题: 如果特征都是人工设计的,LR 的性能上限就在那里了。所以关键是”如何自动发现好的特征交叉”。
3. FM——自动发现特征交叉
一句话解释: 给每个特征学一个”隐向量”,通过隐向量的点积来自动发现特征之间的二阶交叉关系。
举个例子:
假设你要预测用户是否会点击一条广告。有两个特征:
- 特征 1:用户性别(男/女)
- 特征 2:广告类别(女装/男装/食品)
传统 LR 需要人工构造交叉特征”性别×广告类别”(比如”男×男装”、”女×女装”)。如果有一百个特征,交叉特征就有 C(100,2) = 4950 个,而且大部分数据是稀疏的(你不可能看到所有组合)。
FM 的巧妙之处在于:它给每个特征学一个 k 维隐向量 v₁, v₂, …, vₙ。两个特征的交叉就通过它们的隐向量点积 vᵢ·vⱼ 来近似。
核心公式:
FM 的预测公式为:
$$\hat{y}(x) = w _0 + \sum _{i=1}^{n} w _i x _i + \sum _{i=1}^{n} \sum _{j=i+1}^{n} \langle v _i, v _j \rangle x _i x _j$$
其中 $w _0$ 是全局偏置,$w _i$ 是第 $i$ 个特征的权重,$v _i$ 是第 $i$ 个特征的 k 维隐向量,$\langle v _i, v _j \rangle$ 是隐向量的点积。
交叉项的数学推导——利用平方和展开的技巧,二阶交叉项可以改写为:
$$\sum _{i=1}^{n} \sum _{j=i+1}^{n} \langle v _i, v _j \rangle x _i x _j = \frac{1}{2} \sum _{f=1}^{k} \left( \left( \sum _{i=1}^{n} v _{i,f} x _i \right)^2 - \sum _{i=1}^{n} v _{i,f}^2 x _i^2 \right)$$
这意味着即使特征非常稀疏,FM 也能高效地学习交叉项,计算复杂度是 O(kn),而不是 O(n²)。
FM 的实际影响: 2010 年提出后,FM 在 CTR 预估(预测用户是否会点击广告/商品)领域成为重要工具。
4. FFM——给每个特征每个”域”一个隐向量
一句话解释: FM 给每个特征一个隐向量,但 FFM 发现:同一个特征在不同的”上下文”(Field)中可能代表不同的含义,所以给每个特征在每个 Field 里单独学一个隐向量。
举个例子:
假设有两个特征:
- 特征 A:性别(男)
- 特征 B:广告类别(男装)
在 FM 中,性别”男”只有一个隐向量 $v_A$ 。但在 FFM 中,性别”男”对广告类别”男装”的隐向量,和性别”男”对广告类别”女装”的隐向量是不同的—— $v_A(男装) ≠ v_A(女装)$ 。
因为性别”男”和广告”男装”之间的相关性,和性别”男”与广告”女装”之间的相关性显然不同。FFM 捕捉到了这种”上下文依赖性”。
2016 年 WSDM 最佳论文。 在 2014–2018 年间,FFM 是工业界 CTR 预估的标配算法。
FFM 的公式改进:
FM 中的交叉项是 $\sum _{i=1}^n \sum _{j=i+1}^n \langle v _i, v _j \rangle x _i x _j$,其中隐向量 $v _i$ 与特征无关。
FFM 则将隐向量按”域(Field)”拆分:$\langle v _{i, F _j}, v _{j, F _i} \rangle$,其中 $v _{i, F _j}$ 表示特征 $i$ 在特征 $j$ 所属域中的隐向量。于是:
$$\hat{y}(x) = w _0 + \sum _{i=1}^n w _i x _i + \sum _{i=1}^n \sum _{j=i+1}^n \langle v _{i, F _j}, v _{j, F _i} \rangle x _i x _j$$
代价是隐向量个数从 $n \times k$ 增加到 $n \times k \times |\text{Fields}|$,但精度显著提升。
5. GBDT + LR
一句话解释: 用树模型(XGBoost/LightGBM)自动做特征交叉,用 LR 做最终的分类。
具体流程:
- 先用 XGBoost 训练一个树模型
- 把训练数据输入到树的叶子节点,得到每个样本在树中的叶子编号(比如样本 A 落在第 3 片叶子)
- 把叶子编号作为新的特征输入到 LR
为什么这样做有效?
- 树模型能自动发现特征之间的非线性交叉关系
- LR 最后做一个线性分类,简单高效
- 在 Kaggle 比赛中非常流行
具体转化过程:
假设用 $T$ 棵树做 GBDT,每棵树有 $L$ 个叶子节点。对于一个样本 $x$:
- 输入每棵树,得到它落入的叶子节点索引:$t(x) = (t _1(x), t _2(x), \ldots, t _T(x))$
- 将叶子索引做 one-hot 编码,得到新的特征向量 $x’ = \text{onehot}(t(x))$,维度为 $T \times L$
- 将 $x’$ 输入 LR:$\hat{y} = \sigma(w _{LR}^T x’ + b _{LR})$
五、第四阶段:深度学习时代(2014–2019)
1. Google Wide & Deep(2016)
一句话解释: 用两个网络并行工作——Wide 部分负责”记忆”你之前见过的模式,Deep 部分负责”泛化”到没见过的组合。
具体架构:
Wide 部分(记忆能力):
- 用稀疏的交叉特征(人工设计的),如”25岁女性×北京×女装×晚间”
- 输出:$s _{\text{wide}} = w _{\text{wide}}^T x _{\text{wide}} + b _{\text{wide}}$
- 优点:对见过的组合记得很准
- 缺点:没见过的新组合就无能为力了(稀疏特征中没出现的组合输出为零)
Deep 部分(泛化能力):
- Embedding 层:把稀疏特征(用户 ID、商品 ID 等)映射到稠密向量:$e _i = \text{Embed}(f _i)$
- DNN:多层全连接网络,逐层变换:$h^{(l+1)} = \sigma(W^{(l)} h^{(l)} + b^{(l)})$
- 优点:没见过的新组合也能通过 Embedding 的连续空间做泛化
- 缺点:对某些特定组合不够精准
最终融合:
$$\hat{y} = \sigma(s _{\text{wide}} + s _{\text{deep}}) = \sigma(w _{\text{wide}}^T x _{\text{wide}} + b _{\text{wide}} + w _{\text{deep}}^T h _{\text{deep}} + b _{\text{deep}})$$
即把两部分的 logits 相加(而不是拼接再做一次 LR),等价于一个逻辑回归。
效果: Google Play 上线后 CTR 提升 2.7%。
2. DeepFM(2017)
一句话解释: 去掉 Wide & Deep 中需要人工设计 Wide 部分特征的麻烦,用 FM 自动提取低阶交叉,用 DNN 自动提取高阶交叉,两者共享同一个 Embedding 层。
为什么比 Wide & Deep 更好?
- Wide & Deep 的 Wide 部分需要大量人工特征工程
- DeepFM 用 FM 层自动做二阶交叉,DNN 自动做高阶交叉
- 两层共享 Embedding,更高效
- 不需要人工设计 Wide 部分
DeepFM 的预测公式:
DeepFM 由两个子网络组成,共享同一组 Embedding 层:
- FM 部分(捕获二阶特征交叉):
$$s _{\text{FM}} = w _0 + \sum _{i=1}^n w _i x _i + \frac{1}{2} \sum _{f=1}^k \left( \left( \sum _{i=1}^n v _{i,f} x _i \right)^2 - \sum _{i=1}^n v _{i,f}^2 x _i^2 \right)$$ - DNN 部分(捕获高阶特征交叉):
$$h^{(0)} = [e _1, e _2, \ldots, e _n], \quad h^{(l+1)} = \sigma(W^{(l)} h^{(l)} + b^{(l)})$$
$$s _{\text{DNN}} = w _{\text{out}}^T h^{(L)} + b _{\text{out}}$$ - 最终预测:
$$\hat{y} = \sigma(s _{\text{FM}} + s _{\text{DNN}})$$
FM 和 DNN 的输出直接相加,共享同一组 Embedding $v _i = e _i$,无需任何人工特征交叉。
3. DIN / DIEN(阿里巴巴,2018–2019)
一句话解释: 用户对不同商品的兴趣不同。推荐女装时,他看过的”美白牙膏”和”口红”兴趣权重不同,应该动态调整。
DIN(Deep Interest Network)的核心创新——注意力机制:
假设用户历史行为是:[口红, 眼影, 美白牙膏, 洗面奶, 面霜]
现在要预测他会不会买”口红”。DIN 的思路是:
- “口红”和”口红”高度相关 → 权重很高
- “口红”和”眼影”相关 → 权重较高
- “口红”和”美白牙膏”不太相关 → 权重很低
- “口红”和”洗面奶”有一定相关 → 权重中等
具体实现:
- 把候选商品(口红)的 embedding 作为”查询”(query)
- 把用户历史行为的每个商品 embedding 作为”键和值”(key, value)
- 用注意力机制计算每个历史行为对当前预测的权重
- 加权求和得到用户兴趣表示
DIN 的注意力权重计算:
设候选商品 embedding 为 $e _c$,用户历史行为序列为 $h = [e _{h _1}, e _{h _2}, \ldots, e _{h _m}]$:
- 用多层感知机(MLP)计算每个历史行为与候选商品的相关性:$a _j = \text{Attention}(e _{h _j}, e _c) = \text{softmax}(v^T \tanh(W _1 e _{h _j} + W _2 e _c + b))$
- 其中 $W _1, W _2, v$ 是可学习参数,$\tanh$ 和点积捕捉历史行为与候选商品之间的非线性相关性
- 加权求和得到用户兴趣表示:$u = \sum _{j=1}^m a _j \cdot e _{h _j}$
- 最后将 $u$ 与候选商品 $e _c$ 拼接,通过全连接层预测点击率:$\hat{y} = \text{FC}([u; e _c])$
DIEN 更进一步——兴趣演化:
DIN 只是静态地计算不同历史行为的权重,但用户的兴趣是随时间变化的。比如你以前喜欢二次元,现在转向了运动健身。DIEN 用 GRU(门控循环单元)来建模这种兴趣的演变过程。
DIEN 的两个关键创新:
- GRU with Attentional Update Gate(AUGRU): 用 DIN 的注意力权重来调节 GRU 的更新门,让注意力强的行为对当前兴趣的影响更大:
- 传统 GRU 更新门:$z _t = \sigma(W _z \cdot [h _{t-1}, x _t])$
- AUGRU 用注意力权重 $\alpha _t$ 加权历史行为:$h’ _{t-1} = \sum _j \alpha _j \cdot h _j$,然后 $z _t = \sigma(W _z \cdot [h’ _{t-1}, x _t])$,即先用注意力机制过滤历史行为,再输入 GRU
- 辅助损失函数: 在 GRU 的每个时间步加入辅助损失,监督隐状态的变化是否合理:
$$\mathcal{L} _{\text{aux}} = \frac{1}{T} \sum _{t=1}^T \text{BCE}(a _t, \mathbb{I}(y _t = 1))$$
其中 $a _t$ 是 GRU 在时间步 $t$ 的注意力输出,$y _t$ 是用户在该时间步是否产生交互的标签。这个辅助损失防止 GRU 学到噪声,起到正则化的作用。
DIEN 的完整流程:
- Embedding 层:商品 ID → 稠密向量
- 注意力层:DIN 式的注意力计算,得到每个历史行为的权重
- AUGRU 层:用注意力加权的历史行为序列输入 GRU,建模兴趣演化
- 辅助损失:监督每个时间步的兴趣变化
- 最终输出:拼接用户兴趣表示和候选商品 embedding,通过全连接层预测点击率
4. ESMM(阿里巴巴,2018)
一句话解释: 直接预估”点击并购买”的概率 = 点击率 × 购买率,用点击率作为辅助任务,解决了”购买率”样本太稀疏的问题。
详细解释:
在电商中,我们要预估 CVR(转化率,即点击后购买的比例)。但问题在于:
- 我们只有在用户点击了广告后才知道他有没有购买
- 如果直接用点击后的数据训练 CVR 模型,会有严重的样本选择偏差(SSB)——没点击的人我们完全不知道他们的行为模式
- 同时,购买样本远远少于点击样本,数据非常稀疏
ESMM 的巧妙做法:
- 把 P(点击并购买) = P(点击) × P(购买 | 点击) 作为建模目标
- 同时训练两个子任务:CTR 预估和 CTCVR 预估
- 因为 CTR 的样本多(只要曝光就有数据),模型能学到更好的用户表示
- 这些表示被共享给 CVR 任务,缓解了稀疏性
ESMM 的模型结构:
ESMM 假设点击和购买之间满足条件独立性:给定用户和商品的联合表示,购买行为与是否点击条件独立。于是:
$$P _{\text{ctcvr}} = P _{\text{ctr}} \times P _{\text{cvr}}$$
模型架构:
- 共享底层: 用户和商品的 Embedding 层完全共享
- CTR 子网络: 用曝光数据训练(样本最多),输出 $\hat{p} _{\text{ctr}}$
- CTCVR 子网络: 用点击且购买的数据训练(样本最少),输出 $\hat{p} _{\text{ctcvr}}$
- 隐式 CVR: $\hat{p} _{\text{cvr}} = \frac{\hat{p} _{\text{ctcvr}}}{\hat{p} _{\text{ctr}} + \epsilon}$,其中 $\epsilon$ 是极小数防止除零
损失函数:
$$\mathcal{L} = -\frac{1}{N} \sum _{i=1}^N \left[ c _i \log(\hat{p} _{\text{ctr}, i}) + (1-c _i) \log(1-\hat{p} _{\text{ctr}, i}) + v _i \log(\hat{p} _{\text{ctcvr}, i}) + (1-v _i) \log(1-\hat{p} _{\text{ctcvr}, i}) \right]$$
其中 $c _i$ 是点击标签(曝光即有),$v _i$ 是购买标签(仅点击后有值)。
5. MMoE(Google,2018)
一句话解释: 多任务学习时,不同任务之间可能有冲突。MMoE 用多个”专家”网络,每个任务有自己的”门控”来选择从哪些专家那里获取信息。
详细解释:
假设一个推荐系统要同时做三个任务:CTR 预估(是否点击)、CVR 预估(是否购买)、时长预估(停留多久)。
这三个任务可能互相冲突:
- 有些内容让人想点击但不想购买(标题党)
- 有些内容让人点击后停留很久但不购买(长视频)
MMoE 的做法:
- 有多个”专家”网络(Expert),每个专家学习一种模式
- 每个任务有一个”门控”(Gate),决定从各个专家那里获取多少信息
- 点击任务可能主要从”标题党专家”和”长视频专家”获取信息
- 购买任务可能主要从”品质商品专家”获取信息
效果: 比简单的多任务学习(共享底层特征)效果更好,因为它能自动学习任务间的相关性和冲突。
MMoE 的数学描述:
假设有 $T$ 个任务,$G$ 个专家网络 ${e _g(\cdot)} _{g=1}^G$,每个任务 $t$ 有一个门控(Gating)网络 $g^{(t)}(\cdot)$:
- 专家输出: $e _g(x) = W _g^{(e)} x + b _g^{(e)}$
- 任务门控: $g^{(t)}(x) = \text{softmax}(W _g^{(t)} x + b _g^{(t)})$,其中 $g^{(t)}(x) _g$ 表示任务 $t$ 对专家 $g$ 的权重
- 任务特定的专家组合: $\hat{y}^{(t)} = \sum _{g=1}^G g^{(t)}(x) _g \cdot e _g(x)$
每个任务通过自己的门控网络,自动学习从哪些专家获取信息。例如点击任务可能更多地从”标题党专家”获取信息,而购买任务从”品质商品专家”获取信息。
GRU4Rec(2016)
一句话解释: 用户的浏览历史是一个时间序列,用 GRU(一种改进的 RNN)来记住这个序列,预测下一个会点什么。
GRU 核心公式:
GRU 有两个门控机制来控制信息流:
- 更新门(Update Gate): $z _t = \sigma(W _z \cdot [h _{t-1}, x _t])$,决定有多少旧记忆保留
- 重置门(Reset Gate): $r _t = \sigma(W _r \cdot [h _{t-1}, x _t])$,决定多少旧记忆被丢弃
- 候选记忆: $\tilde{h} _t = \text{tanh}(W \cdot [r _t \odot h _{t-1}, x _t])$,$\odot$ 表示逐元素乘法
- 最终记忆: $h _t = (1 - z _t) \odot h _{t-1} + z _t \odot \tilde{h} _t$,新旧记忆按更新门比例融合
预测输出:
$$\hat{y} _i = \text{softmax}(v _i^T \cdot h _t)$$
其中 $v _i$ 是物品 $i$ 的 embedding,$h _t$ 是 GRU 最后一个时间步的隐状态。目标是最大化实际被点击物品的概率。
具体流程:
- 用户行为序列:[商品 A, 商品 C, 商品 E, …]
- 把每个商品 ID 映射成 embedding
- 按时间顺序输入 GRU
- 最后一个时间步的隐状态作为用户兴趣表示
- 和用户 embedding 拼接,预测下一个商品
SASRec(2019)—— 用 Transformer 做序列推荐
一句话解释: 既然 Transformer 在 NLP 领域这么强,那用它来处理用户行为序列(也是序列)会不会更好?
具体流程:
- 用户行为序列:[商品 A, 商品 C, 商品 E, …]
- 把商品 ID 映射成 embedding,加上位置编码(告诉模型每个商品在序列中的位置)
- 通过多层自注意力(Self-Attention)
- 预测下一个商品
自注意力(Self-Attention)核心公式:
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d _k}}\right)V$$
其中 $Q = XW _Q$、$K = XW _K$、$V = XW _V$ 分别是由输入 $X$ 通过可学习权重矩阵投影得到的查询、键、值矩阵,$d _k$ 是键向量的维度。$\frac{QK^T}{\sqrt{d _k}}$ 计算每个物品对其他所有物品的关注程度,除以 $\sqrt{d _k}$ 是为了防止点积过大导致 softmax 梯度消失。然后对输出做归一化,再经过前馈网络(FFN),即 SASRec 中的一层。
因果掩码: 在训练时,用户不能看到未来的行为(防止信息泄露),所以 Self-Attention 矩阵上三角部分被 mask 掉(设为 $-\infty$),保证预测第 $t$ 个物品时只能用前 $t-1$ 个物品的信息。
为什么 Transformer 比 RNN 好?
- RNN 是逐个处理的,前面的信息在序列很长时会”遗忘”
- Transformer 的自注意力可以同时看到序列中的所有物品
- 训练可以并行化,速度更快
BERT4Rec(2019)
一句话解释: 既然 BERT 在 NLP 中通过”遮挡预测下一个词”效果这么好,那对用户的浏览序列也遮挡一些商品,让模型去预测,效果会不会更好?
具体做法:
- 随机遮挡用户序列中的某些商品
- 让模型预测被遮挡的商品
- 训练完后,用这个模型做推荐
BERT4Rec 的训练目标:
与 SASRec(因果 Mask,预测下一个)不同,BERT4Rec 使用双向上下文:
- 以 15% 的概率随机替换用户序列中的某些商品 ID 为
[MASK]token - 训练掩码预测任务:$\mathcal{L} = -\log P(x _t^{\text{orig}} \mid x _t^{\text{masked}}, \text{context})$
- 由于是自注意力机制,模型可以同时看到被遮挡位置的左边和右边所有商品
- 预测时,输出层对商品 ID 做 softmax:$P(x \mid h) = \text{softmax}(W _{\text{item}}^T h + b _{\text{item}})$,其中 $h$ 是 [MASK] 位置的 Transformer 隐状态
BERT4Rec vs SASRec:
- BERT4Rec:双向注意力,能利用未来信息做掩码预测,但不用于推理(推理时仍然用因果 Mask 预测下一个),训练方式类似 BERT
- SASRec:因果 Mask(单向),训练和推理一致,推理时直接预测下一个商品
六、第五阶段:图神经网络时代(2019–2022)
1. 为什么图神经网络适合推荐?
一句话解释: 用户和物品的交互本身就是一张图。GNN 可以在这张图上”传播消息”,让每个用户和物品都聚合到邻居的信息,从而学到更丰富的表示。
举个例子:
1 | 用户 U1 买了 商品 A, 商品 B, 商品 C |
这张交互图可以表示为:
- U1 — A — U2
- U1 — B
- U1 — C
- U2 — D
GNN 的核心操作是”聚合邻居”:
- U1 会聚合 A、B、C 的信息
- A 会聚合 U1、U2 的信息
- U2 会聚合 A、D 的信息
- 经过几轮聚合,U1 和 U2 虽然没直接交互,但通过商品 A 有了间接联系
消息传递公式:
对于一般 GNN,第 $k$ 层的消息传递为:
$$h _v^{(k)} = \text{Aggregate}\left({h _u^{(k-1)} \mid u \in \mathcal{N}(v)}\right)$$
$$h _v^{(k)} = \text{Update}\left(h _v^{(k-1)}, h _v^{(k)}\right)$$
其中 $\mathcal{N}(v)$ 是节点 $v$ 的邻居集合。在推荐场景下,节点分为用户节点和物品节点,边表示用户-物品交互。
2. LightGCN(2020)
一句话解释: 研究发现,在推荐场景下,复杂的 GNN 变体(GCN、GAT 等)并不比简单的线性聚合好。去掉非线性激活函数和特征变换,只用最轻量的邻居聚合,效果反而更好。
详细解释:
之前的图推荐模型(如 GraphSAGE、GAT)会做这些事:
- 聚合邻居特征
- 加一个非线性激活函数(如 ReLU)
- 做一个线性变换(特征变换)
- 做一次归一化
LightGCN 的研究发现:在推荐场景下,步骤 2–4 都不是必须的。去掉这些后,只用最轻量的:
邻居聚合 = 每个邻居的特征 × 归一化权重
效果反而更好,而且速度更快。这背后的原因是:在推荐场景中,用户的偏好不是固定的,而是通过和物品的交互”传播”出来的,不需要复杂的非线性变换。
为什么叫”Light”? 因为轻量化——去掉不必要的操作,让模型更轻更快。
LightGCN 的核心公式:
LightGCN 只保留最基础的邻居聚合操作。设 $E _k$ 为第 $k$ 层的节点表示:
$$E _{k+1} = \tilde{D}^{-\frac{1}{2}} \tilde{A} \tilde{D}^{-\frac{1}{2}} E _k$$
其中 $\tilde{A} = A + I$ 是加入自环的邻接矩阵,$\tilde{D}$ 是对应的度矩阵。归一化因子 $\tilde{D}^{-\frac{1}{2}} _{ii} \tilde{D}^{-\frac{1}{2}} _{jj} = \frac{1}{\sqrt{d _i \times d _j}}$ 保证了聚合时的权重平衡。
最终输出(多层聚合的叠加):
$$E = \sum _{k=0}^K \alpha _k E _k$$
其中 $\alpha _k$ 是第 $k$ 层的权重(通常设为均匀权重 $\alpha _k = \frac{1}{K+1}$)。将 $0 \sim K$ 层的所有表示拼接/相加,而不是只取最后一层,这样可以捕获多跳邻居的信息。
训练损失(BPR 损失):
$$\mathcal{L} = -\sum _{(u, i, j) \in \mathcal{O}} \ln \sigma(\hat{y} _{u, i} - \hat{y} _{u, j}) + \lambda |E|^2$$
其中 $(u, i, j)$ 是三元组:用户 $u$ 正样本物品 $i$,负样本物品 $j$(随机采样用户 $u$ 未交互过的物品),$\hat{y} _{u, i} = e _u^T e _i$ 是用户 $u$ 对物品 $i$ 的预测分数,$\sigma$ 是 sigmoid 函数。BPR 优化的目标是让正样本的分数高于负样本。
3. SGL(2021)
一句话解释: 在推荐场景下,正样本(用户买过的)和负样本(用户没买过的)都太多了。SGL 通过在图上做数据增强,用对比学习来学到更好的表示。
具体做法:
- 在原始图上做增强:随机去掉一些节点、随机去掉一些边、随机掩码属性
- 得到两个不同的图 view
- 对同一个用户/物品,在两个 view 中学到的表示应该尽可能接近(对比学习)
- 对不同的用户/物品,表示应该尽可能远离
核心洞察: 推荐场景下正负样本太多,传统的对比学习需要精心设计负采样策略。SGL 通过图上的数据增强,避免了这个问题。
SGL 的对比学习损失:
SGL 在原始图 $G$ 上做 $M$ 种数据增强操作(随机删边、随机节点掩码、随机边掩码),得到 $M$ 个增强视图 ${G _1, G _2, \ldots, G _M}$,然后用 LightGCN 在每个视图上学到节点表示 $E _1, E _2, \ldots, E _M$。
InfoNCE 损失(对比学习标准损失):
对于一个锚点 $v$ 和其增强视图 $v _m$,损失为:
$$\mathcal{L} _{\text{InfoNCE}} = -\log \frac{\exp(\text{sim}(E _v, E _m) / \tau)}{\sum _{v’ \in \mathcal{B}} \exp(\text{sim}(E _v, E’ _{m’}) / \tau)}$$
其中 $\text{sim}(a, b) = \frac{a^T b}{|a| \cdot |b|}$ 是余弦相似度,$\tau$ 是温度系数,$\mathcal{B}$ 是 batch 中的负样本集合。
最终节点表示:
$$E _v = \sum _{m=1}^M w _m \cdot E _v^{(m)}$$
将 $M$ 个视图中的同一节点的表示加权求和,得到鲁棒的最终表示。
七、第六阶段:大规模工业系统架构
推荐系统在实际工业部署中从来不是单一模型,而是一个分层架构。
1. 召回(Retrieval)
一句话解释: 从几百万个候选物品中,快速选出几千个候选。
为什么需要召回? 精排模型很复杂,要对每个候选做大量计算。如果候选有 1000 万个,精排算不过来。所以先召回几千个,再精排。
主要方法:
- 双塔模型(Two-Tower): 用户一个神经网络(用户塔),物品一个神经网络(物品塔)。两个塔分别编码用户和物品,最后用点积做相似度匹配。线上只需要算一次用户塔的 embedding,然后和所有物品的 embedding 做内积,速度极快。
双塔模型公式:
- 用户塔:$e _u = f _U(x _u)$,其中 $x _u$ 是用户特征(年龄、性别、历史行为统计等),$f _U$ 是一个多层神经网络
- 物品塔:$e _i = f _I(x _i)$,其中 $x _i$ 是物品特征(类别、价格、描述 embedding 等),$f _I$ 是一个多层神经网络
- 相似度:$s(u, i) = e _u^T e _i$(向量点积,也可以加 L2 归一化后做余弦相似度)
- 训练时使用负采样:对于每个正样本 $(u, i)$,采样 $K$ 个负样本物品 $j _1, \ldots, j _K$,用 InfoNCE 损失:
$$\mathcal{L} = -\log \frac{\exp(e _u^T e _i / \tau)}{\sum _{k=0}^K \exp(e _u^T e _{j _k} / \tau)}$$
其中 $j _0 = i$ 是正样本,$\tau$ 是温度系数。
向量检索(FAISS):
当物品数量 $N$ 达到百万级时,暴力计算 $e _u^T e _i$($O(Nd)$)太慢。FAISS 使用近似最近邻搜索(ANN),如 HNSW 或 IVF-PQ,将检索复杂度降至 $O(\log N \cdot d)$,百万级物品的检索可在毫秒级完成。
- 多路召回: 用多种策略并行召回,最后融合。比如:向量召回 1000 个 + 热门召回 500 个 + 协同召回 500 个 + 实时召回 500 个 = 2500 个候选。
2. 粗排(Pre-Ranking)
在召回和精排之间,用轻量模型在几千候选上做初步排序,减少精排的计算量。
3. 精排(Ranking)
用深度模型对几百个候选做精细排序。工业界主流是 DeepFM、DIN、MMoE 等。
4. 重排(Re-Ranking)
在精排之后做业务逻辑调整:
- 打散: 同一品牌的商品不要连续出现
- 多样性: 不要全部推荐同一个品类
- 业务规则: 下架商品排除
- 探索与利用(Bandit): 留出一些流量给新内容,探索用户是否喜欢
八、第七阶段:大语言模型与推荐系统(2023 至今)
1. 为什么 LLM 能做推荐?
一句话解释: LLM 本质上是在做”下一个词预测”。如果把用户历史和物品描述都变成文本,让 LLM 预测”下一个词是商品 ID”,那就等价于做推荐。
举个例子:
输入:
1 | 用户 A 的历史行为:看了 iPhone 15,看了 AirPods Pro,看了 MacBook Air |
输出:
1 | 推荐:Apple Watch Series 9 |
LLM 的核心优势:
- 语义理解: 能理解物品描述的深层含义。比如”口红”和”唇膏”在语义上很近,传统推荐系统可能认为它们是不同的 ID,但 LLM 知道它们是相似的
- 推理能力: 能做链式推理,解释推荐理由。”因为你上次买了口红,这次推荐同色系的唇釉”
- 零样本/少样本: 新用户没有任何行为记录,LLM 也能根据人口统计信息给出推荐
- 统一接口: 一个模型既能做推荐也能做对话
2. 三种基于 LLM 的推荐范式
范式一:LLM 作为排序器
做法: 把用户查询、候选物品的描述拼成 prompt,让 LLM 对候选排序或打分。
例子:
1 | 你是推荐助手。用户 A 喜欢科技产品和运动装备。以下是三个候选物品: |
LLM 输出:1, 2, 3(因为口红和用户兴趣最不相关)
代表工作:
- TALLRec(2023): 利用 LLM 的长上下文能力,处理完整的用户交互历史(几千条行为),传统模型很难处理这么长的序列
- LLM-ReRank(2023): 用 LLM 对传统推荐系统的候选做重排,发现 LLM 在排序任务上表现不错
数学形式化:
给定用户上下文 $C _u$ 和候选物品集合 $\mathcal{I} = {i _1, \ldots, i _N}$,LLM 作为排序器计算每个物品的相对相关性得分:
$$\hat{s} _j = \text{LLM}(C _u, i _j)$$
排序结果为:
$$\text{Rank} = \text{sort}(\hat{s} _1, \hat{s} _2, \ldots, \hat{s} _N)$$
排序的本质等价于最大化条件概率:$\hat{s} _j = P(\text{"item } j \text{ is relevant}\mid C _u)$。
范式二:LLM 作为推荐生成器
做法: 直接把推荐任务看作文本生成。用户输入查询,LLM 输出推荐的物品。
例子:
1 | 输入:我喜欢科幻电影,喜欢诺兰导演的作品 |
代表工作:
- LLM4Rec(2023): 将推荐任务统一为文本生成任务,把物品 ID、标题、描述等信息拼接作为输入
- InstructRec(2023): 用指令微调(Instruction Tuning)让 LLM 适应推荐任务
数学形式化:
生成式推荐的核心是将推荐看作自回归生成:
$$P(i _1, i _2, \ldots, i _k \mid C _u) = \prod _{t=1}^k P(i _t \mid C _u, i _1, \ldots, i _{t-1})$$
其中 $i _1, \ldots, i _k$ 是依次生成的推荐物品序列。每个物品的生成条件于用户上下文和之前已生成的物品。
训练目标(交叉熵):
$$\mathcal{L} = -\sum _{t=1}^T \log P(i _t^\text{true} \mid C _u, i _1^\text{true}, \ldots, i _{t-1}^\text{true})$$
即最大化真实推荐序列的出现概率。这与语言模型的训练完全一致,唯一的区别是输入不是句子而是用户行为序列,输出不是下一个词而是物品 ID。
范式三:LLM 作为特征编码器
做法: 用 LLM 编码物品描述,得到高质量的语义 embedding,再输入到传统推荐模型中。
为什么需要这个? 传统推荐系统中,每个商品只有一个 ID embedding,没有语义信息。LLM 的 embedding 包含了丰富的语义。
数学形式化:
- 物品文本描述 $t _i$ 输入 LLM:$e _i^\text{LLM} = \text{LLM} _\text{enc}(t _i)$
- 其中 $\text{LLM} _\text{enc}$ 通常取 LLM 最后一层的 [CLS] 标记(或平均所有 token 的表示)
- 将 $e _i^\text{LLM}$ 与传统 ID embedding $e _i^\text{ID}$ 拼接:$e _i^\text{hybrid} = [e _i^\text{ID}; e _i^\text{LLM}]$
- 将 $e _i^\text{hybrid}$ 输入到传统推荐模型(如 LightGCN、DeepFM)
这样,即使新物品没有交互数据,LLM 也能通过语义理解给出合理的推荐。
3. 大模型推荐的核心挑战
幻觉问题
问题: LLM 可能”编造”一个不存在的商品,或者推荐一个完全不相关的商品。
解决思路:
- RAG(检索增强): 先检索候选物品,再让 LLM 在候选集中选择。形式化地,先通过传统召回得到候选集 $\mathcal{I} _\text{recall}$,然后 LLM 在 $\mathcal{I} _\text{recall}$ 内排序:
$$P(i _j \mid C _u) = \frac{\exp(\hat{s} _j / \tau)}{\sum _{i _k \in \mathcal{I} _\text{recall}} \exp(\hat{s} _k / \tau)}$$ - 约束解码: 限制 LLM 只能从候选物品 ID 中选择,不能编造新 ID。即解码时只允许输出预定义物品 ID 集合中的 token,其他 token 的概率设为 $-\infty$。
效率问题
问题: LLM 推理很慢,推荐系统需要毫秒级响应。
解决思路:
- 蒸馏: 用 LLM 做 teacher,训练一个轻量模型做线上推理
- 分层架构: LLM 做离线特征计算,线上仍用传统模型
物品规模问题
问题: LLM 的上下文窗口有限(即使是最大的模型也装不下几百万个商品的描述)。
解决思路: 先召回再让 LLM 排序(两阶段架构)
九、第八阶段:生成式推荐(Generative Recommendation,2023 至今)
一句话解释: 传统推荐是”给每个物品打分再排序”,生成式推荐是”直接生成推荐结果”——就像语言模型生成文本一样,把推荐看作一个生成任务。
传统推荐 vs 生成式推荐
传统推荐(判别式):
1 | 用户 A + 商品 1 → 得分 0.8 |
每个商品单独打分,然后排序。数学形式化:
$$\hat{y} _i = f(u, i), \quad \text{Recommend} = \text{Top-K}({\hat{y} _i} _{i=1}^N)$$
其中 $f(u, i)$ 是评分函数,Top-K 选出分数最高的 $K$ 个物品。关键局限: 每个物品的评分独立,无法考虑物品之间的序列依赖。
生成式推荐(生成式):
1 | 用户 A → [商品 3] [商品 1] [商品 2] |
直接生成推荐序列,不需要打分排序。数学形式化:
$$P(\mathbf{i} \mid u) = \prod _{t=1}^K P(i _t \mid u, i _1, \ldots, i _{t-1})$$
物品之间不再独立,后一个物品的生成条件于前一个,天然考虑了物品间的序列依赖。
代表性工作
GenRec(阿里巴巴,2023)
做法: 用自回归语言模型做推荐。用户的行为序列和查询被建模为文本,模型直接生成物品 ID 序列。
关键创新:
- BPE(Byte-Pair Encoding): 用 BPE 压缩物品 ID,减少 token 数量。比如商品 ID “12345678” 可以被压缩成更少的 token
- 统一框架: 序列推荐、知识增强推荐、多模态推荐都能用同一套框架处理
GRec(2023)
做法: 用 LLM 做通用推荐,设计了一个统一的 prompt 模板,一个模型处理多种推荐场景。
关键创新:
- 一个 prompt 模板处理序列推荐、知识增强推荐、多模态推荐等多种场景
- 利用 LLM 的推理能力,能给出推荐理由
UniRec 系列(2023–2024)
做法: 统一的推荐框架,将不同的推荐场景统一为一个生成任务。
生成式推荐的优势
- 端到端: 不需要召回、排序多个阶段,一个模型搞定
- 可解释性: 生成过程天然包含推理链条
- 多模态融合: 文本、图像、视频都可以统一为 token 序列
- 冷启动: LLM 的预训练知识对冷启动有天然帮助
当前局限
- 精度: 在大规模真实场景下,纯生成式方法的精度仍不如传统排序方法
- 可控性: 生成的物品可能不符合业务约束
- 评估: 传统推荐评估指标(Hit Rate、NDCG)在生成式框架下如何定义仍有争议
十、前沿交叉方向
1. LLM + 图神经网络
结合 LLM 的语义理解能力和 GNN 的结构感知能力:
- 用 LLM 给图中的节点(用户、物品)添加文本描述,增强节点表示
- 用 GNN 做消息传递,把图结构信息注入 LLM 的推理过程
2. 多模态推荐
用户和物品的信息不再只是 ID 和评分,还包括图片、视频、音频、文本描述。
做法: 用 CLIP 等预训练模型编码图像和文本,得到统一的向量表示,再融合到推荐模型中。
3. 推荐系统 + Agent
把推荐系统本身看作一个 Agent(智能体):
- Agent 可以主动理解用户意图
- Agent 可以与用户对话,澄清需求(”你送礼物是给男生还是女生?预算大概多少?”)
- Agent 可以自主探索用户兴趣
十一、总结:推荐系统的技术演进图谱
| 阶段 | 时间 | 代表方法 | 核心思想 |
|---|---|---|---|
| 规则与统计 | 1990s 前 | 基于内容、关联规则 | 人工规则、共现统计 |
| 协同过滤 | 1990s–2010s | UserCF、ItemCF、MF | 利用用户-物品交互关系 |
| 特征工程 + ML | 2010–2014 | FM、FFM、LR、GBDT | 人工特征 + 机器学习 |
| 深度学习 | 2014–2019 | Wide&Deep、DeepFM、DIN、DIEN | 神经网络自动学习特征 |
| 序列建模 | 2016–2019 | GRU4Rec、SASRec、BERT4Rec | 用 RNN/Transformer 建模行为序列 |
| 图神经网络 | 2019–2022 | LightGCN、SGL | 图结构上的消息传递 |
| 工业系统架构 | 贯穿始终 | 双塔、多路召回、粗排+精排+重排 | 分层架构应对大规模场景 |
| LLM 推荐 | 2023– | LLM4Rec、TALLRec | 用大语言模型做推荐 |
| 生成式推荐 | 2023– | GenRec、GRec | 把推荐当作生成任务 |
十二、未来展望
从”预测下一个”到”理解用户”
当前推荐系统的核心范式是”预测用户下一个会点什么”,但用户的真实需求远不止于此。LLM 带来的机会是:让推荐系统真正理解用户意图、情绪、目标。
从”千人千面”到”千人千询”
未来的推荐系统可能不再是固定的个性化模型,而是根据用户实时查询动态调整的推荐策略,类似搜索引擎。
从”推荐物品”到”推荐体验”
未来的推荐可能不是推荐某个具体的电影或商品,而是推荐一种体验、一种方案。
从”被动推荐”到”主动交互”
推荐系统与对话系统的融合:用户可以主动问”给我推荐一些适合送给女朋友的礼物”,系统会像真正的助手一样帮你筛选、对比、给出建议。
本文梳理了推荐系统从传统方法到前沿技术的完整演进脉络。推荐系统是一个快速演进的领域,新的方法不断涌现,但核心问题始终不变——在合适的时机,把合适的东西推荐给合适的人。