1.1 核心矛盾:相关性 vs 多样性
在信息检索和推荐系统中,最朴素的排序策略是按相关性/预测分数降序排列——但这会产生严重的冗余问题:
- 搜索场景:搜索"Python 教程",前 10 条结果全是同一网站的不同入门页,用户得不到多样化视角。
- 电商发现:用户随手浏览时,系统反复推同品类商品(比如一直推鞋),错失发现新品的机会。
- 推荐系统:用户历史 70% 爱情片、30% 动作片,但推荐列表全是爱情片,违背用户真实兴趣分布。
- Feed 流:CTR 提升的同时,用户浏览深度反而下降——因为高 CTR 内容单调,用户更早离开(RL4CTE 的核心发现)。
多样性的本质是:在候选集中选出一个集合,使得这个集合整体的信息量(覆盖度、用户满意度)最大,而不只是追求列表中每个单项的质量。这是一个集合优化问题(Set Optimization),与逐条排序(point-wise ranking)有本质区别。
1.2 两类多样性目标
研究者逐渐发现"多样性"本身存在两种不同出发点,对应两套解法:
📐 内容多样性(Content Diversity)
集合内各元素之间的相互差异尽量大。目标是:已选的和新候选之间不要太相似。
代表:MMR、DPP
📊 分布校准(Calibration / Coverage)
集合的类目/标签分布要和用户历史兴趣分布对齐。目标是:不要一类推到底,要反映用户多元口味。
代表:Calibrated Rec、Adaptive PD
而 RL4CTE 则从更高层次出发:用强化学习直接优化用户 session 内总点击数,多样性成为提升长期目标的隐式手段,而非显式约束。
1.3 方法演进时间线
提出 Maximal Marginal Relevance,用 λ 参数在相关性与反冗余之间线性插值;引入"边际相关性"概念;通过贪心算法线性时间选集合。影响深远,被后世大量工作直接引用或泛化。
用次模函数(Submodular)替代 MMR 的简单相似度减法,加入个性化类目权重;Thompson Sampling 做 explore-exploit;上线 Amazon Stream 时 CTR 提升 9.82%~12.58%。
从"分布对齐"角度重新定义多样性:推荐列表的类目分布应与用户历史偏好分布一致;用 KL 散度度量偏差;用次模贪心求解 Relevance - λ·KL 目标。
把 DPP(行列式点过程)引入推荐多样化重排;提出基于 Cholesky 分解的快速增量贪心 MAP 推断($O(Mk^2)$);给出滑动窗口流式算法支持工业级实时推断;JD.com 平台 A/B 验证。
发现"CTR 提升但总点击数下降"的矛盾现象;提出 CTE(Click-Through Expectation)作为 session 级累计优化目标;用 REINFORCE 训练 RNN 重排策略;引入 PBR(Position Bounce Rate)建模用户提前离开;离线仿真环境支持 on-policy 训练;线上 AC +6.22%、AD +4.92%。
1.4 方法谱系总图
| 维度 | MMR | Adaptive PD | Calibrated Rec | Fast DPP | RL4CTE |
|---|---|---|---|---|---|
| 多样性定义 | pair-wise 相似度 | 属性覆盖(次模) | 类目分布 KL | 行列式体积 | 隐式(session 总点击) |
| 个性化 | ❌ | ✅ 类目权重 | ✅ 历史分布 | ⚠️ 可扩展 | ✅ 用户 embedding |
| 优化目标 | 单步贪心 | 次模 + CELF | Rel - λKL | MAP 行列式 | 长期 CTE(RL) |
| 是否端到端 | ❌ | ❌ | ❌ | ❌ | ✅ |
| 落地场景 | 文档摘要/检索 | 视觉发现(时装) | 电影推荐 | 商品推荐 | Feed 流推荐 |
2.0 MMR 在推荐链路的位置
先明确 MMR 做的是哪个环节,以及重排(Re-ranking)和混排(Blending/Fusion)的区别:
↓ 数万 → 数千个候选
粗排(轻量模型,线性/简单 NN,快速过滤)
↓ 数千 → 数百个候选
精排(精细深度模型 DeepFM / DIN 等,输出 CTR/pctr 分)
↓ 数百个候选 + 每个的精排分
【重排 Re-ranking】← MMR / DPP / Calibrated Rec 在这里做
↓ 重排后的单一有序列表(约 50~200 条)
【混排 Blending】← 广告插入 / 运营位 / 多路合并在这里做
↓ 最终 Feed 流(下发给用户)
🔵 重排(Re-ranking)
输入:精排给出的单一候选列表,每个 item 有精排分。
做什么:在这一个列表内部调整顺序——减少冗余、保证类目覆盖、注入多样性。
输出:同一批候选,不同顺序(也可能丢掉一些)。
例:精排给 200 个商品,全是运动鞋。重排(MMR)后保留 10 双鞋 + 选入 5 个帽子 + 5 件上衣,共 50 个多样化商品。
🔴 混排(Blending/Fusion)
输入:多个来源的候选列表(推荐池 + 广告池 + 运营坑位 + 直播等)。
做什么:按照频控规则、运营策略、竞价结果,把多路候选交织插入成一条展示流。
输出:一条混合了不同来源 item 的最终 Feed。
例:重排完的推荐商品 + 广告系统出的广告(每 4 条推荐插 1 条广告)+ 运营固定在位置 1 的 banner。
- 精排是 point-wise 的:精排模型对每个 item 独立打分(给定 user+item 特征预测 CTR),不感知"这个 item 和列表里其他 item 的关系"。它的目标是单项分数准,不是集合分数好。
- 重排是 list-wise / set-wise 的:重排把整个候选集作为输入,目标是选出一个集合使得整体价值(相关性 + 多样性)最大。需要 item 之间互相感知。
- 效率分层:精排需要对每个 item 单独跑复杂模型(DeepFM 级别),候选集缩减到几百以内再做集合优化才合理。
2.1 问题定义
MMR 产生于文档摘要和信息检索场景:给定查询 $Q$,从文档集 $R$ 中已选出一个子集 $S$,现在要再挑一篇文档加入 $S$,使得它既与 $Q$ 相关,又与 $S$ 中已有文档不重复。
这是一个非常经典的"边际效益递减"问题:第一篇搜索结果带来很多信息,第二篇如果和第一篇一模一样,边际信息量接近于零。MMR 的贡献就是把"边际相关性"(Marginal Relevance)这个直觉形式化。
2.2 核心公式
每次贪心选下一个文档 $d_i$,选的标准是最大化:
逐项解读:
- $\text{Sim}_1(d_i, Q)$:$d_i$ 与查询 $Q$ 的相关度(TF-IDF cosine 或 BM25 分数)。
- $\max_{d_j \in S}\text{Sim}_2(d_i, d_j)$:$d_i$ 与已选集合 $S$ 中最相似文档的相似度——代表"冗余度"。
- $\lambda \in [0,1]$:$\lambda=1$ 退化为纯相关性排序;$\lambda=0$ 只最大化多样性。
经济学中"边际"是"再多一单位带来的额外收益"。在 MMR 里,$d_i$ 对查询 $Q$ 的边际相关性 = 全部相关性 − 已被 $S$ 覆盖掉的冗余部分。形式上用最大相似度来估计冗余。
注意:$\text{Sim}_1$ 和 $\text{Sim}_2$ 可以是不同的相似度函数,作者并不要求它们相同。
2.3 贪心算法流程
每轮需要计算所有剩余文档的 MMR 分数,总复杂度 $O(k \cdot n)$($n$ 为候选集大小),是线性时间算法。
2.4 推荐系统实例:快手/淘宝商品搜索重排
场景:用户在电商 App 搜索"跑步装备",精排输出 top-200 个商品(每个商品有精排分)。现在做 MMR 重排选出 top-20 展示。
| item | 商品描述 | 精排分(Sim₁) | 类目 |
|---|---|---|---|
| A | 耐克 React 跑步鞋(黑) | 0.92 | 跑步鞋 |
| B | 耐克 React 跑步鞋(白) | 0.90 | 跑步鞋 |
| C | 阿迪 Ultraboost 跑步鞋 | 0.88 | 跑步鞋 |
| D | 跑步专用手臂包 | 0.72 | 跑步配件 |
| E | 耐克跑步短裤 | 0.70 | 运动服 |
| F | 运动水壶(650ml) | 0.65 | 运动配件 |
| G | 跑步心率手表 | 0.62 | 运动配件 |
| H | 压缩裤(跑步款) | 0.60 | 运动服 |
每个 item 用商品图文 embedding(维度 128)表示。相似度矩阵(关键值,越高越相似):A-B 余弦相似度 0.95(都是 React 跑鞋,颜色不同);A-C 相似度 0.78(都是跑鞋但不同品牌);A-D 相似度 0.12(鞋 vs 手臂包)。设 $\lambda = 0.6$(略偏相关性)。
第 1 轮:$S = \emptyset$,冗余项为 0,MMR 分 = 精排分。选 A(分 0.92)。$S = \{A\}$
第 2 轮:计算各候选的 MMR 分:
- B:$0.6 \times 0.90 - 0.4 \times \max\text{Sim}(B,A) = 0.54 - 0.4 \times 0.95 = 0.54 - 0.38 = \mathbf{0.16}$(高冗余大幅扣分)
- C:$0.6 \times 0.88 - 0.4 \times 0.78 = 0.528 - 0.312 = \mathbf{0.216}$
- D:$0.6 \times 0.72 - 0.4 \times 0.12 = 0.432 - 0.048 = \mathbf{0.384}$(跑步手臂包,与鞋差异大!)
选 D(MMR 分 0.384,手臂包虽然精排分较低,但与已选鞋高度不同,边际贡献最大)。$S = \{A, D\}$
第 3 轮:
- E(跑步短裤):与 A 相似度 0.30,与 D 相似度 0.15。$0.6 \times 0.70 - 0.4 \times 0.30 = 0.42 - 0.12 = \mathbf{0.30}$
- F(运动水壶):与 A 相似度 0.08,与 D 相似度 0.20。$0.6 \times 0.65 - 0.4 \times 0.20 = 0.39 - 0.08 = \mathbf{0.31}$
- C(阿迪鞋):与 A 相似度 0.78。$0.216$(和第 2 轮一样,未改变)
选 F(运动水壶,0.31)。$S = \{A, D, F\}$
第 4 轮:选 E(跑步短裤,与 A/D/F 都差异大)。
持续循环,最终 top-20 中:跑步鞋约 6 双(多品牌/色彩分散)+ 配件 6 个 + 运动服 5 件 + 心率手表等 3 个,比直接按精排分取 top-20(基本全是跑步鞋)多样化得多。
- $\text{Sim}_1$(查询相关性):直接用精排模型输出的 pctr 分,不需要重新计算。
- $\text{Sim}_2$(item 间相似度):离线预计算好 item embedding(用图文多模态模型),上线时候选集不超过 200 个,计算 pair-wise 余弦相似度约 $200^2/2 = 2$ 万次,在 RT 预算内。
- $\lambda$ 的业务含义:搜索场景用户意图明确,$\lambda$ 通常取 0.7~0.8(偏相关性);发现/浏览场景用户无明确意图,$\lambda$ 通常取 0.4~0.6(更看重多样性)。
- 候选集截断:通常先把精排 top-200 压缩到 top-50(粗过滤)再做 MMR,进一步节省计算。
2.5 深度分析与局限
✅ 优点
- 公式简洁,直觉清晰,实现极简(约 5 行代码)。
- $\lambda$ 提供连续插值控制,业务调参方便。
- 与具体相似度函数无关,适配性强(可用任意 embedding)。
- 第一篇基础性工作,后续几乎所有多样化方法都引用。
❌ 局限
- 无个性化:$\lambda$ 对所有用户相同,无法区分每个用户对多样性的偏好。
- pair-wise 视角不够全局:只考虑最相似的那篇,忽略集合整体多样性结构(DPP 用行列式解决)。
- 贪心不可逆:每次选择不考虑后续影响,次优性有理论下界但实际可能不够好。
- 无分布概念:不能保证结果集的类目分布满足某个目标(Calibrated Rec 补足了这点)。
- $\lambda$ 调参依赖经验:不同业务最优 $\lambda$ 差别很大,没有自动学习机制。
MMR 的核心贡献不是算法本身的效果,而是正式定义了"多样性重排"这个任务框架:从集合 $R$ 中选出子集 $S$ 使得相关性和多样性的加权目标最大。后来的 Adaptive PD、Calibrated Rec、DPP 都在这个框架下改进了"如何度量多样性"这个核心问题。
3.1 问题背景:视觉浏览发现
这篇论文来自 Amazon Stream——一个类似"无限 feed 流"的时装浏览产品。用户没有明确搜索意图,只是随手滚动,期望被"惊喜"地发现感兴趣的商品。
系统面临两个核心挑战:
- 冷启动 + 曝光不足:新品或冷门商品被曝光少,模型对其点击概率估计不准,容易一直推热门商品。
- 多样性需求:用户研究表明,多样化的展示流能让用户更快发现感兴趣的品类,从而提升 CTR 和停留时长。纯按预测分排序会造成品类聚集。
解决方案分三层:① 相关性打分(Thompson Sampling)→ ② 次模多样化重排 → ③ 个性化类目权重。
3.2 第①层:Thompson Sampling 打分(解决"新品永远不被看见")
最朴素的打分方法:每个商品有个历史点击率,直接按历史 CTR 排序。
问题:一件新上架的 Gucci 白鞋,还没几个人看过,历史 CTR 为 0。一双已经卖了 3 年的耐克老款,历史 CTR = 5%。
→ 系统永远把老耐克排前面,Gucci 白鞋永远排不进首屏 → Gucci 白鞋永远没有曝光 → 永远没有点击数据 → CTR 永远是 0 → 死循环。
这就是冷启动 / 探索困境:热门商品一直被强化,新品没有机会证明自己。
什么是 Beta 分布?
Beta 分布是专门用来描述"一个概率值大概在哪个范围"的分布。它的参数是两个正整数 $\alpha$ 和 $\beta$:
直觉上:$\alpha$ 是"成功的次数",$\beta$ 是"失败的次数",均值 = 成功率。方差越大,说明数据越少,对这个成功率越不确定。
- Beta(1, 1):均值 0.5,方差极大 → 分布从 0 到 1 几乎均匀分布。这是"完全不知道点击率是多少"的初始状态。采样结果可能是 0.01,也可能是 0.99,完全随机。
- Beta(5, 95):均值 0.05,方差中等 → 有一些数据了,但还不够多。分布主要集中在 2%~8% 区间,但偶尔也有偏离。
- Beta(150, 2850):均值 0.05,方差极小 → 数据非常充足。分布窄到几乎是 4.8%~5.2% 的一个小尖峰。采样结果几乎总是 0.05 左右。
关键规律:$\alpha + \beta$ 越大(总观察次数越多),分布越窄,采样越稳定;$\alpha + \beta$ 越小(数据越少),分布越宽,采样越随机。
Thompson Sampling 的核心思想:对每个商品不是存"一个固定的 CTR 数值",而是维护一个Beta 分布,表示"这个商品的真实点击率大概在哪个范围"。每次打分时从 Beta 分布里随机抽一个值用,而不是总用均值。
更新规则很简单:如果展示后被点击了,$\alpha$ 加 1;如果没被点击,$\beta$ 加 1。不需要重新训练模型,O(1) 实时更新。
商品 A(耐克爆款跑鞋):被展示了 3000 次,被点击了 150 次。
→ Beta 分布参数:Beta(150, 2850),均值 5%,分布极窄,采样值几乎总是 0.05 左右。
商品 B(Gucci 新款白鞋):才上架 2 天,被展示了 2 次,点击了 1 次。
→ Beta 分布参数:Beta(1, 1),均值 50%(但完全不可信),分布极宽,采样值可能是 0.03 也可能是 0.82。
本次请求打分结果:
| 商品 | Beta 分布 | 本次采样值 | 说明 |
|---|---|---|---|
| 耐克爆款跑鞋(A) | Beta(150, 2850),窄 | 0.051 | ✅(稳定利用) |
| Gucci 新款白鞋(B) | Beta(1, 1),极宽 | 0.82(运气好!) | ✅(随机探索) |
| 某热门凉鞋(C) | Beta(80, 720),中等 | 0.09 | ❌(本次分低) |
这次 Gucci 白鞋采样得 0.82,排名第 1。如果用户点了,下次变成 Beta(2, 1);没点变成 Beta(1, 2)。几十次展示后,系统就对它的真实质量有了准确估计。
关键:不是每次都给 Gucci 白鞋高分——只是偶尔,概率性地给它高分。热门商品数据多,采样稳定,不会因为随机性被大幅拖累。新品数据少,随机性高,有机会"运气好"被看见。
论文中实际使用的打分模型比 Beta 分布更复杂——用 Bayesian Linear Probit 回归,考虑商品属性(品牌、颜色等):
其中 $\Phi^{-1}$ 是 probit 函数,$x_i$ 是商品属性的权重(也用 Bayesian 后验分布维护)。但核心思想不变:每个参数不是存一个固定值,而是存一个分布,采样时随机抽取。
这一层解决的是:候选池里每个商品的打分(类似精排的功能,但加了探索性)。打完分后,进入第②层做多样化重排。
3.3 第②层:次模多样化重排(解决"品类全是鞋")
假设 Thompson Sampling 打完分,前 10 名分别是:耐克跑鞋 0.51、阿迪跑鞋 0.49、彪马跑鞋 0.48、新百伦跑鞋 0.46 ......
全是跑鞋!用户 Alice 确实喜欢鞋,所以鞋的分数高。但她的首页全是鞋,她会感到厌倦,甚至错失她也感兴趣的手表和包。
→ 需要一个算法,在保证总体相关性的前提下,强制引入品类多样性。
核心目标函数:给定 $n$ 个商品的类目属性向量 $\mathbf{a}_i \in \{0,1\}^d$(one-hot 类目编码)和用户类目偏好向量 $\mathbf{w} \in \mathbb{R}^d$,选 $k$ 个商品子集 $A_k$ 最大化:
逐项翻译成大白话:
- 第一项(多样性项):对每个类目 $j$,计算 $\log(1 + \text{已选商品中属于 }j\text{ 类的数量}) \times w_j$,然后对所有类目求和。log 保证同一品类选得越多,边际增益越小(这就是"次模"——边际收益递减)。$w_j$ 是类目 $j$ 的权重,来自第③层。
- 第二项(相关性项):$\sum s(a_i)$ 就是把选入的每件商品的 Thompson Sampling 打分加起来,鼓励整体相关性高。
次模函数的数学定义:集合函数 $f$ 是次模的,当且仅当 $\forall A \subseteq B$,$\forall x \notin B$:
大白话:集合越大,再加一个元素带来的边际收益越小。这保证了贪心算法有 $(1 - 1/e)$ 近似比——虽然贪心不是最优解,但至少不会比最优解差太多。
贪心运行方式:从空集合 $A_0 = \emptyset$ 开始,每轮从候选池中找"加入后 $\varrho$ 增量最大的商品",选它,重复 k 次。复杂度 $O(dkn)$,用 CELF 加速(利用次模性延迟重计算,实际比暴力快很多)。
假设 Alice 的类目权重(来自第③层,先假设已知):鞋=0.6,手表=0.3,其他=0.1。
目标函数中的多样性项(鞋类部分)= $0.6 \times \log(1 + \text{鞋的数量})$
| 当前已选鞋的数量 | 再加第 N 双鞋的多样性增量 | 说明 |
|---|---|---|
| 0 → 1 | $0.6 \times [\log 2 - \log 1] = 0.6 \times 0.693 = \mathbf{0.416}$ | 第 1 双鞋贡献很大(从无到有) |
| 1 → 2 | $0.6 \times [\log 3 - \log 2] = 0.6 \times 0.405 = \mathbf{0.243}$ | 第 2 双鞋贡献减半 |
| 2 → 3 | $0.6 \times [\log 4 - \log 3] = 0.6 \times 0.288 = \mathbf{0.173}$ | 继续减小 |
| 5 → 6 | $0.6 \times [\log 7 - \log 6] = 0.6 \times 0.154 = \mathbf{0.092}$ | 已经很小了 |
相比之下,Alice 还没选过手表(手表数量=0),此时第 1 块手表的多样性增量 = $0.3 \times \log 2 = 0.208$。
结论:当鞋选了 2~3 双之后,第 3 双鞋的多样性增量(0.173)已经低于第 1 块手表的增量(0.208)。只要手表的 Thompson Sampling 分不是太差,手表就会被选进来。
第 1 轮(集合为空):多样性增量全部是"从 0 到 1"的初始值。
- Gucci 鞋:多样性增量 0.416 + Thompson 分 0.82 = 1.236
- 耐克鞋:多样性增量 0.416 + Thompson 分 0.51 = 0.926
- Casio 手表:多样性增量 0.208 + Thompson 分 0.18 = 0.388
→ 选 Gucci 鞋(分最高)。集合 = {Gucci鞋},鞋的数量=1。
第 2 轮(鞋已有 1 双):
- 耐克鞋(鞋的第 2 双):多样性增量变为 0.243(边际递减!)+ 0.51 = 0.753
- Casio 手表(手表第 1 块,还没选过手表):多样性增量 0.208 + 0.18 = 0.388
→ 选耐克鞋(0.753 仍高于 0.388,因为耐克 Thompson 分明显更高)。集合 = {Gucci鞋, 耐克鞋},鞋的数量=2。
第 3 轮(鞋已有 2 双):
- 阿迪鞋(鞋的第 3 双,Thompson 分 0.48):多样性增量 0.173 + 0.48 = 0.653
- Casio 手表:多样性增量 0.208 + 0.18 = 0.388
- Gucci 手提包(Thompson 分 0.55,包类第 1 件):多样性增量 $0.1 \times 0.693 + 0.55 = \mathbf{0.619}$
→ 选阿迪鞋(0.653)。但 Gucci 手提包已经很接近了(0.619)。随着鞋越选越多,包和手表的胜出只是时间问题。
最终 10 件结果(示意):鞋子 5 双 + 手表 2 块 + 包 2 个 + 运动短裤 1 条。
3.4 第③层:个性化类目权重(解决"每个人喜好不同")
第②层的次模函数里有个参数 $\mathbf{w}$(类目权重)。如果鞋=0.6、手表=0.3 对所有用户一样,就没有个性化。
- 用户 Alice:历史 80% 点鞋,10% 手表 → 她应该看更多鞋
- 用户 Bob:历史 10% 点鞋,80% 手表 → 他应该看更多手表
全局统一的 $\mathbf{w}$ 无法区分 Alice 和 Bob 的不同偏好。
① 全局类目权重(Baseline)
先用全局数据给每个类目算一个"基础权重",作为所有用户的先验:
$c_j$ = 全站类目 $j$ 的总点击数,$v_j$ = 全站类目 $j$ 的总曝光数。$\alpha, \beta$ 是平滑参数(类似 Beta 分布的先验),防止数据少的类目权重为 0。
大白话:每个类目在全站的"受欢迎程度"。
② 个性化用户权重:Dirichlet-Multinomial 模型
对用户 $u$,假设他的类目兴趣比例 $\mathbf{w}_u$ 是一个概率向量(各类目之和=1),用 Dirichlet 分布建模:
大白话翻译:
- $\mathbf{c}_u$ 是用户 $u$ 在各类目的点击次数(比如 Alice:[鞋50, 手表5, 上衣3, 包2])。这个用 Multinomial(多项分布)建模——每次点击像"掷骰子",各类目的概率不同。
- $\mathbf{w}_u$ 就是那个骰子的概率向量——我们想要的东西。但它是隐变量,不能直接观测。用 Dirichlet 分布建模"这个概率向量本身的不确定性"。
- Dirichlet 和 Multinomial 是共轭分布(就像 Beta 和 Binomial 是共轭的一样),所以后验均值有简洁公式:
其中 $\boldsymbol{\alpha}_0$ 是先验参数(通常取全局类目权重对应的 $\alpha$ 值),$\|\cdot\|_1$ 是向量各分量之和。
大白话:用户的类目权重 = (用户自己的点击计数 + 全局先验) 的归一化。全局先验防止冷启动用户权重全是 0。
用户 Alice(喜欢鞋):
历史点击:鞋=50次,手表=5次,上衣=3次,包=2次,其他=0次
先验 $\boldsymbol{\alpha}_0$(每类目加 3,防止为 0):
$\hat{\mathbf{w}}_{Alice} = [53, 8, 6, 5, 3] / 75 \approx [0.71, 0.11, 0.08, 0.07, 0.04]$
→ Alice 的鞋权重 0.71,手表权重 0.11
用户 Bob(喜欢手表):
历史点击:鞋=5次,手表=50次,上衣=3次,包=2次,其他=0次
$\hat{\mathbf{w}}_{Bob} = [8, 53, 6, 5, 3] / 75 \approx [0.11, 0.71, 0.08, 0.07, 0.04]$
→ Bob 的手表权重 0.71,鞋权重 0.11
代入第②层的效果差异:
- Alice 的第 2 双鞋多样性增量:$0.71 \times 0.243 = 0.173$(鞋权重高,多选鞋仍有价值)
- Bob 的第 2 双鞋多样性增量:$0.11 \times 0.243 = 0.027$(鞋权重低,再选鞋没什么价值)
- Bob 的第 1 块手表多样性增量:$0.71 \times 0.693 = 0.492$(手表权重高,第 1 块手表非常有价值)
→ 对 Bob 来说,选完 1 双鞋之后,下一件几乎肯定选手表。同样的算法,不同用户的推荐结果自动不同。
③ 类目兴趣扩散(把隐性兴趣挖出来)
用户 Alice 只点过鞋和手表,从没点过跑步裤——那跑步裤权重为 0 吗?用类目共现矩阵 $M$($M_{ij}$ = 同时点过类目 $i$ 和 $j$ 的用户比例)做扩散:
大白话:把用户当前的类目权重向量,乘以类目之间的共现矩阵,再归一化。效果是"喜欢鞋的人也喜欢跑步裤"这种关联会被传导过来。
从全体用户行为数据里统计:同时点过"鞋"和"跑步裤"的用户占点过"鞋"的用户的 40%。
这意味着:喜欢鞋的用户,有 40% 也喜欢跑步裤。Alice 喜欢鞋(鞋权重高),所以她对跑步裤也可能感兴趣,即使她从未点过跑步裤。
扩散后:Alice 的跑步裤权重从 0 → $0.40 \times 0.71 = 0.28$(鞋权重的 40% 传导给跑步裤)。
→ 跑步裤有机会出现在 Alice 的推荐里,帮她发现自己可能感兴趣但还没探索到的品类。
3.5 三层串联:完整流程总结
以用户 Alice(喜欢鞋和手表)为例,从一次首页推荐请求到最终展示的完整链路:
第③层(离线/近实时计算,拿来即用):
系统已计算好 Alice 的类目权重 $\tilde{\mathbf{w}}_{Alice} = \{$鞋:0.71, 手表:0.11, 跑步裤:0.05, 上衣:0.08, 包:0.05$\}$(来自历史点击 + 共现扩散)。
第①层(实时打分):
候选池 100 件商品,每件都有 Beta 分布参数。
本次请求从每件商品的 Beta 分布里采样一个值作为打分:
→ 耐克爆款:0.051(稳定);Gucci 白鞋(新品):0.82(运气好,探索);Casio 手表:0.18;跑步裤:0.15;……
第②层(实时重排):
用 Alice 的权重 $\tilde{\mathbf{w}}_{Alice}$ + 第①层打分,运行次模贪心,选 10 件:
→ 第 1 件:Gucci 白鞋(打分高 0.82 + 鞋类初始多样性增量大)
→ 第 2 件:耐克跑鞋(打分 0.051 低,但鞋第 2 双多样性增量仍 0.243,总体还行)
→ 第 3 件:Casio 手表(此时鞋已选 2 双,第 3 双鞋增量 0.173 低于手表首次入场 0.076,手表胜出)
→ ……最终 10 件:鞋 5 双 + 手表 2 块 + 跑步裤 1 条 + 上衣 1 件 + 包 1 个
对比直接按打分排序的 top-10:耐克鞋/阿迪鞋/彪马鞋/Gucci鞋/……共 8~9 双鞋,Alice 刷 5 秒就腻了。
3.6 分析
✅ 优点
- 三组件(探索打分 + 次模多样化 + 个性化)分层解耦,各自可替换。
- Dirichlet-Multinomial 共轭,更新 $O(d)$ 极快,支持实时流式更新。
- 次模保证贪心有理论近似比 $(1-1/e)$,效果有保障。
- 线上 A/B:CTR +9.82%(次模 vs 多项式随机)、+8.29%(自适应权重 vs 手动权重)、+12.58%(个性化权重 vs 全局权重)。
❌ 局限
- 属性空间粗化:把数百万 SKU 属性映射到约 100 个互斥类目,细粒度差异消失。
- 非端到端:相关性打分和多样化重排是两个独立阶段,联合优化没有做。
- 次模目标 ≠ 用户满意度:类目覆盖不等于用户真实期望,损失函数与业务指标不对齐。
Adaptive PD 把 MMR 的"最大化单个 pair-wise 相似度差"升级为"最大化整体集合的属性覆盖(次模函数)",并加入了个性化:不同用户、不同类目的权重不同。这是从 query-level 多样性迈向 user-level 个性化多样性的关键一步。
4.1 核心思想:分布对齐
Steck 提出了一个全新的多样性视角:推荐列表的类目分布应该与用户历史偏好分布一致。
用户历史看过 70% 爱情片、30% 动作片,那么推荐列表也应该大约 70% 爱情片、30% 动作片——而不是全推爱情片(即使爱情片预测分更高)。
这与 MMR / Adaptive PD 的"内容多样性"不同:后者关注集合内元素之间的差异,Calibrated Rec 关注集合的统计分布与目标分布的偏差(distribution matching)。如果用户兴趣本身就是多元的,纯按分数排序会导致"赢者通吃"——高分类目占据整个列表,用户也感兴趣的低分类目被完全忽略。
4.2 分布度量:KL 散度
定义用户 $u$ 的目标分布 $P(H_u)$ 和实现分布 $Q(L_u)$:
- $H_u$ 是用户历史交互集合,$g(i)$ 是 item $i$ 的类目集合(一个电影可以属于多个类目)。
- $w_{u,i}$ 是用户对 item $i$ 的评分(或隐式反馈权重)。
- $\text{prop}(g|i) = 1/|g(i)|$ 是类目 $g$ 在 item $i$ 中的占比(均分)。
实现分布 $Q(L_u)$ 计算完全类似,只是把 $H_u$ 换成推荐列表 $L_u$,$w_{u,i}$ 换成预测分 $\hat{w}_{u,i}$。
用 KL 散度度量两个分布的偏差:
KL 散度三个关键性质:① $P = Q$ 时 KL = 0(完美校准);② 对小概率类目的偏差敏感;③ 倾向于均匀分布(防止极端集中)。
如果某类目在用户历史中占比很小,直接用 KL 会导致该类目一旦出现就"过度代表"。Steck 提出平滑:
$$\tilde{q}(g|u) = (1-\alpha) \cdot q(g|u) + \alpha \cdot p(g|u)$$常用 $\alpha = 0.01$,让实现分布向目标分布轻微回归,避免极端稀疏。
4.3 目标函数与优化
最终目标是在相关性和校准之间权衡:
其中 $\text{REL}(L_u) = \sum_{i \in L_u} \hat{w}_{u,i}$,$\lambda \in [0,1]$ 控制权衡:$\lambda=0$ 为纯相关性,$\lambda=1$ 为纯校准。这是 NP-hard 的组合优化问题,用次模贪心求解,保证 $(1-1/e)$ 近似比:
4.4 推荐系统实例:快手短视频 Feed 重排
场景:用户 Bob 在快手刷短视频。Bob 过去 30 天的浏览记录中,看了美食 70%、搞笑 20%、体育 10%。现在要给他生成下一屏的 10 个短视频。
Step 1:目标分布 P(用户历史口味)
直接从 Bob 最近的浏览记录统计各类目的占比:
这不是说每屏严格按比例,而是整体趋势应该对齐。如果 10 个视频全是美食,那 Bob 对搞笑和体育的兴趣就被完全忽略了。
Step 2:精排直接 top-10 的问题("赢者通吃")
精排模型(比如 DeepFM)给每个视频预测一个 CTR 分数。因为 Bob 看美食多,美食视频的 CTR 预估普遍偏高。按分数排序取 top-10:
| 位置 | 视频 | 类目 | 精排分 |
|---|---|---|---|
| 1 | 红烧肉教程 | 美食 | 0.85 |
| 2 | 火锅探店 | 美食 | 0.82 |
| 3 | 糖醋排骨 | 美食 | 0.80 |
| 4 | 街边烤串 | 美食 | 0.78 |
| 5 | 蛋糕烘焙 | 美食 | 0.76 |
| 6 | 螺蛳粉测评 | 美食 | 0.75 |
| 7 | 烧烤合集 | 美食 | 0.73 |
| 8 | 凉皮教程 | 美食 | 0.72 |
| 9 | 猫咪搞笑 | 搞笑 | 0.65 |
| 10 | 足球集锦 | 体育 | 0.60 |
实现分布 $Q = \{$美食:0.80, 搞笑:0.10, 体育:0.10$\}$。和目标分布 $P$ 差很远!
现在算 KL 散度来量化这个偏差:
- 美食:$0.70 \times \log(0.70/0.80) = 0.70 \times (-0.134) = -0.094$。美食在推荐里占 80%,但 Bob 的目标只有 70%,所以这部分是"过度代表"的,贡献负值。
- 搞笑:$0.20 \times \log(0.20/0.10) = 0.20 \times 0.693 = +0.139$。搞笑在推荐里只占 10%,但 Bob 的目标有 20%,所以这部分是"不足代表"的,贡献正值。
- 体育:$0.10 \times \log(0.10/0.10) = 0$。刚好对齐,不贡献偏差。
KL 总分 = $-0.094 + 0.139 + 0 = +0.045$。值越大 = 偏差越大 = 校准越差。
KL 散度衡量的是"推荐给你的比例"和"你期望的比例"之间的差距。每一项的公式 $p \times \log(p/q)$:
- 如果 $q > p$(推荐过多),$\log(p/q) < 0$,这一项是负值——说明你在浪费推荐位推用户不需要那么多的类目。
- 如果 $q < p$(推荐不足),$\log(p/q) > 0$,这一项是正值——说明用户想要的类目没得到足够展示。
- KL 越接近 0 = 推荐分布和用户期望越一致 = 校准越好。
Step 3:Calibrated 贪心重排(逐个解释每一步)
Calibrated Rec 的目标函数:
设 $\lambda = 0.5$,意思是"一半权重给相关性,一半权重给分布对齐"。贪心过程:每次从候选池里选一个加入列表 $L$,选让目标函数增长最多的那个。
第 1 轮:列表 $L$ 为空,$Q$ 为空。
因为列表里没有任何视频,KL 项没法算(技术上用 KL = 0 初始化)。所以这一轮纯粹按相关性选,选最高分的红烧肉教程(精排分 0.85)。
第 2 轮:$L$ = [红烧肉],$Q$ = {美食:1.0}。
现在列表里只有美食视频,分布极度偏斜。来对比两个候选:
| 候选 | 精排分 | 类目 | 加入后 REL 变化 | 加入后 KL 变化 | 总边际收益 |
|---|---|---|---|---|---|
| 火锅探店 | 0.82 | 美食 | +0.82 | 变得更偏美食(更差),KL 增大约 +0.05 | $0.5 \times 0.82 - 0.5 \times 0.05 = \mathbf{0.385}$ |
| 猫咪搞笑 | 0.65 | 搞笑 | +0.65 | 搞笑从 0% → 有代表(大幅改善),KL 减小约 -0.10 | $0.5 \times 0.65 - 0.5 \times (-0.10) = 0.325 + 0.05 = \mathbf{0.375}$ |
火锅探店虽然相关性更高(0.82 > 0.65),但让 KL 变更差了(美食过度代表更严重)。猫咪搞笑虽然相关性低一点,但让 KL 大幅改善(引入了搞笑类目)。最终火锅探店略胜(0.385 > 0.375),被选中。
核心机制:KL 项相当于给"缺失类目"的候选加了一个奖励分,给"过度类目"的候选加了一个惩罚分。
第 3~4 轮:继续选。每多选一个美食视频,美食的"过度代表"程度加剧,KL 惩罚越来越大;而搞笑和体育的视频因为能弥补分布缺陷,获得越来越大的 KL 奖励。到第 4 轮时,一个搞笑视频的 KL 奖励已经超过它比美食视频少的那点相关性分,所以猫咪搞笑被选中。
最终 10 个视频:
| 位置 | 视频 | 类目 |
|---|---|---|
| 1 | 红烧肉教程 | 美食 |
| 2 | 火锅探店 | 美食 |
| 3 | 糖醋排骨 | 美食 |
| 4 | 蛋糕烘焙 | 美食 |
| 5 | 凉皮教程 | 美食 |
| 6 | 猫咪搞笑 | 搞笑 |
| 7 | 职场吐槽 | 搞笑 |
| 8 | 足球集锦 | 体育 |
| 9 | 街边烤串 | 美食 |
| 10 | 螺蛳粉测评 | 美食 |
实现分布 $Q = \{$美食:0.60, 搞笑:0.20, 体育:0.10$\}$。和目标分布 $P=\{$美食:0.70, 搞笑:0.20, 体育:0.10$\}$ 接近多了!美食占比从 80% 降到 60%,搞笑和体育得到了应有的展示位。
注意:美食占比 60% < 70%,这是 $\lambda=0.5$ 的结果——相关性让步了一些但没完全按 70/20/10 分配。$\lambda$ 越大,分布对齐越严格;$\lambda$ 越小,相关性越优先。
实际工程中的补充考量
- 类目粒度选择:Netflix 实际用的类目粒度是"大类目"(爱情、动作等约 20 个),而不是细粒度标签(否则历史数据太稀疏,KL 计算不稳定)。快手/抖音做短视频推荐时,类目层级可以是:美食/穿搭/体育/搞笑等一级类目。
- 历史时间窗口:用最近 30~90 天的观看记录计算 $P(H_u)$,太老的兴趣分布不代表当前需求。
- 平滑处理:若 Bob 的历史里从来没看过音乐片,$p(\text{音乐}|\text{Bob}) = 0$,则任何音乐片推荐都会让 KL = ∞。用平滑 $\alpha = 0.01$ 给各类目一个微小先验概率。
4.5 分析
✅ 优点
- 个性化分布目标:每个用户的目标分布不同,自动适应用户兴趣的多元程度。
- 理论清晰:KL 散度是信息论标准工具,性质明确,可解释性强。
- 与 base ranker 解耦:任何排序模型都可以作为输入,校准作为后处理独立运行。
- MovieLens 数据集上 $\lambda=0.5$ 时 NDCG 几乎不降,但 KL 散度大幅下降。
❌ 局限
- 历史偏好 ≠ 未来期望:用户过去看了 70% 爱情片,不代表未来还想要 70%——兴趣会漂移。
- 冷启动无解:新用户没有历史,无法构建目标分布 $P(H_u)$。
- 类目粒度敏感:"爱情片"包含各种风格,细粒度差异无法捕捉。
- 非端到端:校准和相关性打分分离,联合优化没有做。
Calibrated Rec 开创了"分布校准"研究方向,2025 年综述论文(arXiv:2507.02643)统计了 53 篇相关工作,其中 88% 采用 Steck 的框架。后续改进包括:其他散度度量(JS 散度、Earth Mover's Distance)、个性化 $\lambda$、多目标校准、端到端学习等。
5.1 问题背景
MMR 的 pair-wise 相似度减法只考虑"最像已选中哪篇",没有捕捉集合整体的多样性结构。两篇文章各自和已选集合相似度都很低,但它们彼此相似——这种情况 MMR 处理不了。
行列式点过程(Determinantal Point Process, DPP)用矩阵的行列式来度量集合的"体积"——行列式越大,意味着集合中的向量越"张成"高维空间,即集合越多样。这是从代数几何角度对多样性的精确刻画。
5.2 DPP 数学基础
给定 $n$ 个 item,每个 item 用向量 $\phi_i \in \mathbb{R}^d$ 表示(embedding),定义核矩阵(Kernel Matrix)$L \in \mathbb{R}^{n \times n}$:
其中 $r_i$ 是 item $i$ 的相关性分数(标量),$\phi_i^T \phi_j$ 是归一化后的 item 间余弦相似度,$\alpha$ 是权衡参数。
DPP 定义子集 $Y \subseteq \{1,...,n\}$ 的概率为:
其中 $L_Y$ 是 $L$ 在 $Y$ 对应行列上的子矩阵。
从线性代数角度:$\det(L_Y)$ 等于以 $\{r_i \phi_i\}_{i \in Y}$ 为边的平行多面体的体积平方。向量越正交(多样性越好),体积越大;越相近(冗余越高),体积越接近 0。
因此 $\det(L_Y)$ 大的集合 $Y$ 同时满足:① 单个 item 相关性 $r_i$ 高;② item 之间不相似(多样)。这正是我们想要的。
5.3 MAP 推断
MAP 推断是找最大概率子集,即最大化 $\det(L_Y)$(等价于最大化 $\log \det(L_Y)$)。这是 NP-hard 问题,用贪心近似:
利用行列式的 Schur 补公式,加入一个新 item $i$ 后行列式的增量为:
直觉:这个增量等于 item $i$ 在已选集合 $Y$ 的向量空间中的"剩余分量"的长度平方。如果 $i$ 与 $Y$ 中的 item 高度相似(冗余),增量趋近于 0;如果 $i$ 与 $Y$ 正交(多样),增量接近 $L_{ii} = r_i^2$。
5.4 快速 Cholesky 增量算法
暴力计算每次更新 $\det(L_{Y \cup \{i\}})$ 需要 $O(n^3)$,总复杂度 $O(n^3 k)$,工业场景不可接受。Chen et al. 用 Cholesky 分解实现 $O(Mk^2)$ 的快速增量更新($M$ 为候选集大小,$k$ 为目标选取数量)。
核心思路:维护一个 Cholesky 分解 $L_Y = C_Y C_Y^T$,当加入新 item $i$ 时:
每轮复杂度 $O(Mk)$,总复杂度 $O(Mk^2)$,比暴力快 $O(n^2/k)$ 倍,实际工业场景 $n \gg k$ 时提速明显。
5.5 滑动窗口流式 DPP
工业推荐系统通常是实时流式服务,商品集合每次请求不同。论文提出滑动窗口 DPP:
- 维护一个大小为 $W$ 的历史窗口,窗口内保存已展示 item 的 embedding。
- 新请求来时,先用 DPP MAP 推断在当前候选集中选出多样子集;同时考虑窗口内已展示 item 的冗余度(避免跨次请求重复)。
- 窗口更新:滑出旧 item,滑入新 item,Cholesky 分解做降秩更新($O(k^2)$)。
这使得系统可以在毫秒级完成 DPP 重排,支持工业级实时服务。
5.6 推荐系统实例:快手/京东商品详情页"猜你喜欢"
用户在看索尼耳机详情页。候选池里有:
- 索尼 WH-1000XM5(A)——用户正在看这款
- AirPods Pro(B)——和索尼耳机很像(都是降噪耳机)
- Bose QC45(C)——也和索尼耳机很像(头戴降噪)
- 3.5mm 音频线(D)——和耳机不同类(配件)
MMR 第 1 轮选 A。第 2 轮看 B 和 C:B 和 A 的相似度 0.80,C 和 A 的相似度 0.75,MMR 选相似度更低的 C。
问题:B 和 C 之间也高度相似(0.88)!MMR 只看"和已选 item 的最大相似度",不感知"B 和 C 之间也很像"。如果 C 选了,B 再选就没意义了——但 MMR 不知道这件事,可能第 3 轮又把 B 选进来。结果{A, B, C}三款全是降噪耳机,品类高度重复。
DPP 解决的正是这个问题:它看的是整个集合的"体积",而不是逐对比较。
DPP 的核心原理:行列式 = 集合的"体积"
把每个商品的 embedding 想象成一个向量箭头,从原点出发指向某个方向。
如果两个商品的箭头方向几乎相同(相似度高),那它们画出来的面积很小——就像两根几乎重叠的箭头,撑不出什么空间。
如果两个商品的箭头方向差异很大(几乎垂直),那它们画出来的面积很大——像两根互相垂直的箭头,撑出一个大矩形。
如果有三个商品,行列式就是它们撑出的三维体积。方向越分散,体积越大。
DPP 的目标就是找到 k 个商品,使得它们的箭头撑出的体积最大。体积大 = 方向分散 = 商品之间差异大 = 多样性好。
具体到我们的例子:
- 三款降噪耳机 A、B、C 的箭头方向几乎相同 → {A,B,C} 的"体积"极小(箭头重叠,撑不出什么空间)
- A(耳机)+ D(音频线)的箭头方向差异大 → {A,D} 的"体积"大(箭头接近垂直,撑出大面积)
- 所以 DPP 更倾向于选 {A, D},而不是 {A, B} 或 {A, C}
核矩阵 L:把"相关性"和"相似度"融合在一起
核矩阵 $L$ 的每个元素同时考虑了两个因素:
大白话翻译:
- $r_i \cdot r_j$:两个商品的相关性分数乘积。如果两个商品本身质量高(分数高),它们之间的连接就更强——这是"鼓励选高质量商品"的部分。
- $\phi_i^T \phi_j$:两个商品的 embedding 余弦相似度。如果两个商品方向相同(相似),连接也更强——但行列式的数学性质会自动惩罚这种强连接(让体积缩小),所以相似商品不会被同时选中。
DPP 的精妙之处:核矩阵把相关性和相似度融合在一起,但行列式会自动惩罚相似度过高的组合——它们会让行列式变小(体积缩小),从而不会被选。
| item | 描述 | 精排分 $r_i$ | embedding(2D示意) | "方向"直觉 |
|---|---|---|---|---|
| A | 索尼 WH-1000XM5 | 0.90 | [0.95, 0.10] | ≈水平方向(耳机降噪) |
| B | AirPods Pro | 0.85 | [0.90, 0.20] | ≈水平方向(耳机降噪) |
| C | Bose QC45 | 0.82 | [0.93, 0.15] | ≈水平方向(耳机降噪) |
| D | 3.5mm 音频线 | 0.60 | [0.20, 0.85] | ≈竖直方向(配件) |
| E | 耳机收纳包 | 0.55 | [0.10, 0.90] | ≈竖直方向(配件) |
核矩阵关键值:
- $L_{AA} = 0.90 \times 0.90 \times 1.0 = 0.81$(自相关,越大 = 商品本身质量越高)
- $L_{AB} = 0.90 \times 0.85 \times 0.95 = 0.73$(A-B 方向几乎相同,连接很强)
- $L_{AD} = 0.90 \times 0.60 \times 0.20 = 0.11$(A-D 方向接近垂直,连接很弱)
关键观察:A-B 之间的核值远大于 A-D(0.73 >> 0.11)。乍看好像应该优先选 B,但行列式恰恰相反——A 和 B 方向太相似,加入 B 只会让行列式变小(体积被压缩)。加入 D 反而会让行列式变大(体积被撑开)。
贪心 MAP 推断:每轮选"撑开体积最多的商品"
想象已选集合 {A} 占了一个"水平方向"。现在看 B:
- B 的箭头几乎和 A 重叠 → B 在 A 方向上的投影占 95%,残差(没有被 A 覆盖的部分)只剩 5% → 加入 B 对体积的贡献很小
再看 D:
- D 的箭头几乎垂直于 A → D 在 A 方向上的投影只占 20%,残差高达 80% → 加入 D 对体积的贡献很大
每轮选择残差最大的商品 = 选择对当前集合"撑开体积"贡献最大的商品。
第 1 蛤:集合为空,残差 = 自相关 $L_{ii}$。A 的 $L_{AA}=0.81$ 最大 → 选 A(索尼耳机)。
第 2 蛤:A 占了"水平方向"。计算各候选的残差:
- B(AirPods):95% 的分量和 A 重叠 → 残差 ≈ $0.72 - 0.73^2/0.81 \approx \mathbf{0.06}$(几乎没贡献)
- C(Bose):类似,残差 ≈ 0.05
- D(音频线):只有 20% 的分量和 A 重叠 → 残差 ≈ $0.36 - 0.01 = \mathbf{0.35}$(贡献巨大!)
- E(收纳包):残差 ≈ 0.28
选 D(音频线,残差 0.35 最大)。现在集合 = {A, D},占据了水平+竖直两个方向。
第 3 蛤:A 和 D 已经撑出了一个大面积。新候选的残差要减去它在 A 和 D两个方向上的投影:
- B:B 在水平方向(A)投影 95%,竖直方向(D)投影 20% → 残差只剩 5% × 80% ≈ 0.04(几乎没用了)
- E:E 在水平方向(A)投影 10%,竖直方向(D)投影 85% → 残差 ≈ 0.15
- F(清洁工具):残差 ≈ 0.12
选 E(收纳包,残差 0.15)。继续循环...
最终 6 件:{A(索尼耳机), D(音频线), E(收纳包), B(AirPods), F(清洁工具), 某蓝牙发射器}。降噪耳机只选了 2 款,配件覆盖了 3 种不同品类。而不是纯按分数排序的{A, B, C, 同类4, 同类5, 同类6}。
- embedding 来源:用多模态商品 embedding(图文联合模型),或者 ID-based 协同过滤 embedding。embedding 质量决定 DPP 效果——如果 embedding 不能准确区分"耳机 vs 音频线",DPP 的行列式度量就会失效。
- 核矩阵的 $\alpha$:$L_{ij} = \alpha \cdot r_i \cdot r_j \cdot \phi_i^T \phi_j$。$\alpha$ 越小,越偏向多样性;越大,越偏向相关性。
- 候选集截断:DPP 复杂度 $O(Mk^2)$,$M$ 建议不超过 100~200。先用精排分截断候选再做 DPP。
5.7 分析
✅ 优点
- 全局多样性建模:行列式捕捉集合整体的"体积",不像 MMR 只看 pair-wise 最大相似度。
- 相关性与多样性统一:$L_{ij} = r_i r_j \phi_i^T \phi_j$ 把相关性和相似度融合在同一核矩阵中。
- 快速算法:Cholesky 增量更新实现 $O(Mk^2)$,工业可用。
- JD.com 平台 A/B 实验:多样性指标显著提升,CTR 持平或微升。
❌ 局限
- 核矩阵设计敏感:embedding 的质量直接影响 DPP 效果,如果 embedding 不能准确刻画语义,行列式度量失效。
- 非个性化(基础版):论文基础版不区分用户,所有用户同一核矩阵;需要额外设计才能做个性化。
- 非端到端:相关性打分和 DPP 重排是两个独立阶段。
- $\alpha$ 调参:控制相关性/多样性权衡的 $\alpha$ 同样需要手动调节。
DPP 用行列式替代了 MMR 的 max-similarity,从代数几何角度精确刻画"集合体积",能捕捉集合内所有 item 之间的交叉相互作用,而不只是 pair-wise 最大相似度。代价是计算复杂度更高(但 Cholesky 增量算法解决了这个问题)。
6.1 问题背景:CTR 提升但总点击数下降
作者在优化 Feed 流推荐时发现了一个反直觉的现象:把基础模型从 DeepFM 升级为 DeepFMV2 后,CTR 提升了(从 0.0403 提到 0.0428),但用户每次 session 的总点击数反而下降,同时浏览深度(用户滚动到第几条就离开)也缩短了。
高 CTR 的内容往往是高度针对用户当前"显性兴趣"的内容——但这类内容往往单调(比如一直推跑鞋,因为用户刚买了跑鞋,对跑鞋的 CTR 最高)。用户很快感到无聊,提前离开了 session。CTR 是即时指标,而"用户愿意继续看"是长期指标,两者可能不一致。
这说明:推荐系统应该优化 session 内的累计总点击数,而不是单条的 CTR。这自然引出了强化学习——因为这是一个序列决策问题,当前推什么会影响用户是否继续浏览,进而影响后续能不能再次推荐。
6.2 CTE 优化目标
定义两个核心概念:
- CTR$(u, t, i_t, \mathcal{H}_t)$:用户 $u$ 在位置 $t$ 看到 item $i_t$ 且浏览历史为 $\mathcal{H}_t$ 的条件点击概率。
- PBR$(u, t, i_t, \mathcal{H}_t)$(Position Bounce Rate):用户在位置 $t$ 离开(bounce)的条件概率。
Session 内总点击数的期望(Click-Through Expectation, CTE):
逐项理解:
- $\text{CTR}_t$ 是用户在位置 $t$ 点击的概率(前提是他还没离开)。
- $\prod_{k=1}^{t-1}(1 - \text{PBR}_k)$ 是用户能浏览到位置 $t$ 的概率(前 $t-1$ 个位置都没有 bounce)。
- 两者相乘 = 用户在位置 $t$ 实际贡献一个点击的期望。
- 对所有位置求和 = session 内总点击期望 CTE。
纯 CTR 优化只看 $\text{CTR}_t$,完全忽视了 $\prod(1 - \text{PBR}_k)$。如果推一个高 CTR 但用户看完就想走的内容,PBR 高,后续的潜在点击全部丢失。CTE 把这个损失显式建模出来,因此优化 CTE 会自然倾向于推"用户点击了还愿意继续看"的内容,而这类内容往往比较多样,不会让用户产生疲惫感。
6.3 MDP 建模
将推荐过程建模为 MDP $\mathcal{M} = \langle S, A, P, R, \gamma \rangle$:
- 状态 $s_t$:包含用户画像 $u$、候选集 $\mathcal{I}$、已推荐历史 $\mathcal{H}_{t-1}$、当前位置是否 bounce $B(t, i_t)$。
- 动作 $a_t$:从候选集中选下一个要推的 item。
- 奖励 $R(s_t, a_t)$:用户是否点击了 item $a_t$(即 $C(t+1, a_t) \in \{0,1\}$)。
- 状态转移:由 PBR 决定——以概率 $\text{PBR}_{t+1}$ 进入终止状态(用户离开),以概率 $1 - \text{PBR}_{t+1}$ 继续。
- 累计折扣奖励:$G_t = \sum_{t=0}^{T-1} C(t+1, a_t)$($\gamma = 1$)等于 CTE。
与已有 DRL 推荐工作的关键区别:状态转移由 bounce(离开行为)驱动,而不是用户的点击/评分反馈。这样状态转移在 session 结束时才触发,避免了对每条推荐实时等待用户反馈的需求——这在工业环境的延迟反馈场景下更现实。
6.4 模型架构与训练
策略网络
策略 $\pi_\theta(a|s)$ 由三层网络组成:
- 融合层(Fusion Layer):用 FM + MLP 生成每个 item $i$ 与用户 $u$ 的交互 embedding $e_i = \text{MLP}(\text{FM}(\hat{u}, \hat{i}))$。
- 编码层(Encoding Layer):用 RNN(GRU cell)对候选集内所有 item embedding 序列编码,得到包含上下文的隐状态 $h_i^t$——这使得推荐策略能感知"前面已经推了什么"。
- 预测层:对 $h_i^t$ 做 softmax 得到 action 分布 $\pi_\theta(a|s)$,从中采样选出下一个 item。
仿真环境
直接在线训练 RL 代价高昂,因此用离线日志训练一个仿真环境(Simulation Environment, SE),用于预测给定状态下的 CTR 和 PBR。SE 使用 Transformer 编码器(比策略网络的 RNN 更强,离线训练不受限于在线延迟)。策略网络通过与 SE 交互来训练,而不是直接与真实用户交互。
REINFORCE 训练
用 REINFORCE 策略梯度算法:
其中 $G'_t$ 是带基线的累计奖励,用于减少方差。论文对比了两种基线:
- Whitening:用 episode 内的均值和标准差对 return 做归一化,$G'_t = (G_t - \hat{G}) / \sigma_G$。
- Sampled Baseline(推荐):对同一状态采样 $N$ 条轨迹,用其余 $N-1$ 条的平均 return 作为基线,$G'_{j,t} = G_{j,t} - \frac{1}{N-1}\sum_{b \neq j} G_{b,t}$。
Sampled Baseline 在实验中表现更好,因为它用"同一状态下的多条轨迹"来估计基线,比全局归一化更精确。
6.5 推荐系统实例:快手 Feed 流——MDP 建模与训练全流程
第一步:把推荐问题建模为 MDP
用户 Chris 打开快手刷 Feed,系统每次推一条视频,整个过程建模为:
| MDP 元素 | 推荐中的对应 | 具体表示 |
|---|---|---|
| State $s_t$ | 当前时刻的"上下文" | 用户 embedding $u$ + GRU 隐状态 $h_t$ $h_t = \text{GRU}(h_{t-1}, e_{i_{t-1}})$,编码已推历史序列 |
| Action $a_t$ | 从候选池选一条视频 | 在精排后约 200 条候选中选 item $i_t$ |
| Transition | 用户看完后的反应 | ① 点击(CTR);② 划走;③ 退出 Feed(PBR = bounce) |
| Reward $r_t$ | 这一步的即时收益 | $= \hat{\text{ctr}}_t \times \prod_{j=1}^{t-1}(1 - \hat{\text{pbr}}_j)$ |
| Policy $\pi_\theta$ | 排序策略网络 | 给定 $s_t$ 和候选 embedding,输出动作概率分布,据此选下一条 |
第二步:CTE 目标——为什么不直接优化 CTR?
系统最大化的不是每条视频的点击率,而是整个 session 的总点击数:
大白话拆解:
- $\hat{\text{ctr}}_t$:第 $t$ 条被点击的概率(来自 SE 预测)
- $\prod_{j=1}^{t-1}(1 - \hat{\text{pbr}}_j)$:用户一直留着看到第 $t$ 条的概率(每一步都没退出)
- 两者相乘 = 用户实际能看到并点击第 $t$ 条的期望值
- 对所有位置求和 = session 总点击期望,这就是 CTE
假设一直推搞笑视频,每条 CTR = 0.40,但连续看 5 条后用户无聊,第 6 条的 PBR(退出概率)升到 0.35。
反而如果在第 3 条插一条萌宠视频(CTR=0.28,PBR=0.03),用户退出概率大幅降低,后续视频还有机会被看到和点击,总点击数反而更多。
CTE 把 CTR 和 PBR 都纳入一个统一指标,能捕捉这种 trade-off。
第三步:完整 session 数值演示
Chris 这次 Feed,对比纯 CTR 策略(方案 A)和 RL4CTE 策略(方案 B)推了 5 条视频:
| 位置 $t$ | 方案 A(纯 CTR) | CTR | PBR | 方案 B(RL4CTE) | CTR | PBR |
|---|---|---|---|---|---|---|
| 1 | 搞笑视频 #1 | 0.42 | 0.05 | 搞笑视频 #1 | 0.42 | 0.05 |
| 2 | 搞笑视频 #2 | 0.40 | 0.10 | 萌宠视频 #1 | 0.28 | 0.03 |
| 3 | 搞笑视频 #3 | 0.38 | 0.18 | 搞笑视频 #2 | 0.40 | 0.05 |
| 4 | 搞笑视频 #4 | 0.35 | 0.28 | 美食视频 #1 | 0.22 | 0.03 |
| 5 | 搞笑视频 #5 | 0.33 | 0.35 | 搞笑视频 #3 | 0.40 | 0.06 |
注意:方案 A 的 PBR 随搞笑视频越叠越多不断上升;方案 B 通过穿插萌宠/美食让 PBR 保持低位。
用公式 $r_t = \hat{\text{ctr}}_t \times \prod_{j $t=1$:还没 bounce 过,到达概率=1。$r_1 = 0.42 \times 1.0 = \mathbf{0.420}$ $t=2$:看完第 1 条,$(1-0.05)=0.95$ 的概率还在。$r_2 = 0.40 \times 0.95 = \mathbf{0.380}$ $t=3$:还在概率 = $0.95 \times (1-0.10) = 0.855$。$r_3 = 0.38 \times 0.855 = \mathbf{0.325}$ $t=4$:还在概率 = $0.855 \times (1-0.18) = 0.701$。$r_4 = 0.35 \times 0.701 = \mathbf{0.245}$ $t=5$:还在概率 = $0.701 \times (1-0.28) = 0.505$。$r_5 = 0.33 \times 0.505 = \mathbf{0.167}$ CTE_A = 0.420 + 0.380 + 0.325 + 0.245 + 0.167 = 1.537
$t=1$:$r_1 = 0.42 \times 1.0 = \mathbf{0.420}$
$t=2$:还在概率 0.95。$r_2 = 0.28 \times 0.95 = \mathbf{0.266}$(萌宠 CTR 低,这步收益低)
$t=3$:还在概率 = $0.95 \times (1-0.03) = 0.922$(PBR 只有 0.03,用户几乎没走!)
$r_3 = 0.40 \times 0.922 = \mathbf{0.369}$(搞笑回来,CTR 高,用户还在)
$t=4$:还在概率 = $0.922 \times (1-0.05) = 0.876$。$r_4 = 0.22 \times 0.876 = \mathbf{0.193}$(美食 CTR 低)
$t=5$:还在概率 = $0.876 \times (1-0.03) = 0.850$(还是很高!)
$r_5 = 0.40 \times 0.850 = \mathbf{0.340}$(搞笑,CTR 高,用户还在 85%)
CTE_B = 0.420 + 0.266 + 0.369 + 0.193 + 0.340 = 1.588
CTE_B(1.588)> CTE_A(1.537),方案 B 高出约 3%。
方案 B 在 $t=2, 4$ 用了 CTR 更低的萌宠/美食视频,那两步收益确实低(0.266 < 0.380,0.193 < 0.245)。
但 PBR 的持续低位让用户一直留着。到了 $t=5$:
- 方案 B:用户还有 85% 在看,$r_5 = 0.40 \times 0.850 = 0.340$
- 方案 A:用户只剩 50.5% 在看,$r_5 = 0.33 \times 0.505 = 0.167$
核心逻辑:牺牲短期 CTR,换取用户留存,长期总点击更多。
第四步:策略网络三层结构——模型长什么样?(论文 Section 4.1)
推荐系统返回的是整屏 list,不是一条一条交互。但这个 list 是怎么生成的?策略网络在服务端内部迭代 k 步,每步从候选集 $\mathcal{I}$(N 个 item)里选出 1 个放到当前位置,选完 k 个位置后,整个 list 返回给用户。
关键:状态通过 RNN hidden state 在步骤间传递,下一步知道上一步选了什么,从而感知 list 里已有的内容,自动做出有多样性的选择。
① Fusion Layer:为候选集里每个 item 生成用户相关的 embedding
候选集 $\mathcal{I}$ 有 $N$ 个 item,对每个 item $i \in \mathcal{I}$:
FM 提取用户特征 $\hat{u}$ 和 item 特征 $\hat{i}$ 的交叉特征($x_{u1}x_{i1}, x_{u1}x_{i2}, \ldots$),MLP 再压缩为高维 embedding $e_i$。结果是候选集矩阵 $E$,每列是一个 item 的 embedding,已经融合了用户个性化信息。
② Encoding Layer:RNN 对整个候选集 E 做序列编码,传入上一步的历史
这是最核心的一层。RNN(GRU)把 $E$ 里的 N 个 embedding 依次全部输入:
其中初始隐状态的传递方式是:
大白话:第 $t$ 步选第 $t$ 个位置时,用上一步(第 $t-1$ 步)选完后 RNN 最终的隐状态 $h_N^{t-1}$ 作为初始输入。这就是"历史感知"的来源——RNN 在编码当前候选时,带着"我上一步选了谁"的记忆。
输出 $O_H^t = \{h_1^t, \ldots, h_N^t\}$ 是对所有候选 item 的"上下文感知 embedding",包含了"在这个推荐上下文里,每个候选有多适合作为当前位置的选择"的信息。
③ Prediction Layer:对 $O_H^t$ 做 softmax,选出当前位置的 item
训练时:按概率分布采样(保证探索);推理时:argmax 选分最高的。
初始:$h_0^1 = \mathbf{0}$
步骤 t=1(选位置1):
$\quad$ 对所有 N 个候选 item 依次过 RNN:$h_i^1 = \text{RNN}(e_i, h_{i-1}^1)$,得到 $O_H^1$
$\quad$ softmax($O_H^1$) → 选出 item $a_1$(位置1的内容)
$\quad$ 保存 $h_N^1$(本步 RNN 最终隐状态)
步骤 t=2(选位置2):
$\quad$ 初始隐状态 $h_0^2 = h_N^1$(传入上一步的记忆:选了 $a_1$)
$\quad$ 对所有 N 个候选依次过 RNN:$h_i^2 = \text{RNN}(e_i, h_{i-1}^2)$,得到 $O_H^2$
$\quad$ softmax($O_H^2$) → 选出 item $a_2$(位置2)
…重复 k 次…
最终:list = [$a_1, a_2, \ldots, a_k$] → 一次性返回给用户
多样性从哪里来:假设位置1、2选了搞笑视频,$h_N^2$ 里编码了这个信息。步骤3时以 $h_N^2$ 为初始输入对所有候选过 RNN,此时搞笑候选的 $h_i^3$ 得分经过训练会较低(这种组合 CTE 低,梯度把分压低了),而萌宠/美食候选的得分更高。多样性是从奖励信号里学出来的,不是规则。
第五步:仿真环境 SE——替代真实用户反馈的"环境模型"
这是 on-policy REINFORCE,必须和环境实时交互:策略选一个 action,环境立刻给 reward,再选下一个。但真实用户的 click/bounce 需要时间才回传,而且 on-policy 探索时会推出很差的内容伤害用户体验。SE 解决这个问题:
SE 不直接输出 reward,而是输出用户行为的预测值(CTR 和 PBR),reward 需要再从这两个值计算出来。所以 SE 更准确地说是"环境模型"(Environment Model):模拟用户对当前推荐的反应,而不是直接打分。但功能上等价于 reward model——所有 reward 信号都来自 SE。
| 策略网络(被训练) | 仿真环境 SE(提供 reward 信号) | |
|---|---|---|
| 结构 | Fusion(FM+MLP) + GRU + Softmax,轻量 | Fusion(FM+MLP) + Transformer(更强,离线可以用) |
| 输入 | 用户 $\hat{u}$ + 整个候选集 $\mathcal{I}$(N 个 item) | 用户 $\hat{u}$ + 已推序列 $H_t$(含位置信息)+ 当前 item |
| 输出 | 候选集上的概率分布,采样/argmax 得动作 | 预测 $\widehat{\text{CTR}}_t$ 和 $\widehat{\text{PBR}}_t$(两个 [0,1] 标量) |
| 训练 | REINFORCE 每 batch 更新 | 离线日志预训练(click/bounce 二分类),之后固定不变 |
SE 输出 CTR/PBR → 怎么变成 reward?
SE 对每一步输出两个值后,分三个层级计算:
| 层级 | 符号 | 含义与公式 |
|---|---|---|
| 即时 reward | $r_t$ | 位置 $t$ 对 CTE 的贡献 = 这步被点击的概率 × 用户还没走的概率 $$r_t = \widehat{\text{CTR}}_t \times \prod_{j=1}^{t-1}(1 - \widehat{\text{PBR}}_j)$$ |
| 累积回报 | $G_t^j$ | 从位置 $t$ 到结束的所有即时 reward 之和(不是整个 session,也不是单步) $$G_t^j = \sum_{k=t}^{T} r_k = r_t + r_{t+1} + \cdots + r_T$$ |
| 整个 session | $G_0^j$ | $G_0^j = \sum_{k=1}^{T} r_k$ = 整条 list 的 CTE,$G_t^j$ 是它从位置 $t$ 开始的后缀 |
REINFORCE 更新时对每个位置 $t$ 单独算一次梯度,用 $G_t^j$ 而不是 $G_0^j$:位置 $t$ 的选择只影响 $t$ 之后的结果,用 $G_t^j$ 排除了 $t$ 之前无关的 reward,方差更小。
第六步:多轨迹采样与 Sampled Baseline——这是关键设计
对同一个用户(同一候选集 $\mathcal{I}$),策略网络不只生成 1 条 list,而是采样 N 条不同的 list(每次策略按概率随机采样,得到不同的序列)。这 N 条轨迹共享同一个用户上下文,用于计算 Sampled Baseline:
大白话:第 $j$ 条轨迹第 $t$ 步的"相对收益" = 它的回报 − 其他 $N-1$ 条轨迹在同一步的平均回报。
baseline 的目的是减少梯度方差。Sampled Baseline 的关键优势:同一用户同一候选集下,N 条轨迹面对的是完全相同的状态,对比更公平(不受用户偏好波动影响)。比 Whitening(跨 batch 均值标准化)更稳定。
这和 GRPO(Group Relative Policy Optimization)思想完全一致:GRPO 对同一个 prompt 采样 G 个 response,用组内均值作 baseline;RL4CTE 对同一个用户候选集采样 N 条轨迹,用组内均值作 baseline。本质都是"组内相对打分"。
候选集固定(都是 Chris 的候选),策略随机采样 4 条 list:
| 轨迹 | 位置2选了 | $G_2^j$(位置2之后的 CTE) |
|---|---|---|
| j=1 | 萌宠视频 | $0.26 + 0.35 + 0.19 + 0.28 = \mathbf{1.08}$ |
| j=2 | 游戏视频 | $0.20 + 0.33 + 0.22 + 0.30 = \mathbf{1.05}$ |
| j=3 | 萌宠视频 | $0.27 + 0.36 + 0.18 + 0.31 = \mathbf{1.12}$ |
| j=4 | 搞笑视频(同质) | $0.38 + 0.30 + 0.18 + 0.08 = \mathbf{0.94}$(用户疲劳) |
对位置 $t=2$,各轨迹的 Sampled Baseline 和相对收益:
- 轨迹 4 的 baseline = $(1.08 + 1.05 + 1.12)/3 = 1.083$,$G_2^{4\prime} = 0.94 - 1.083 = \mathbf{-0.143}$(负)→ 降低"位置2再推搞笑"的概率
- 轨迹 3 的 baseline = $(1.08 + 1.05 + 0.94)/3 = 1.023$,$G_2^{3\prime} = 1.12 - 1.023 = \mathbf{+0.097}$(正)→ 增大"位置2推萌宠"的概率
经过大量这样的 batch,策略学会:在刚推了搞笑之后($h_N^1$ 带着这个信息),把萌宠/游戏等多样化内容的分数打高,把同类搞笑的分数打低。多样性从 reward 信号里自发习得。
完整训练循环(Algorithm 1 逐行解读)
从离线日志采样 $(u, H_{t-1}, i_t, \text{click\_label}, \text{bounce\_label})$
用 BCE loss(点击+bounce 二分类)训练 SE,收敛后固定参数
阶段二:On-policy 训练策略网络
repeat:
从数据集采样一批用户 $B = \{(u, \mathcal{I}, \emptyset)\}$
for 每个用户 $b$ in $B$:
repeat 直到 M 有 N 条轨迹(对同一用户采样 N 条 list):
for t = 1 to k:
策略 $\pi_\theta$ 采样 $a_t$(随机探索)
SE 给出 $\widehat{\text{CTR}}_t, \widehat{\text{PBR}}_t$,计算 $r_t$
存入 replay buffer M
计算每步累积回报 $G_t^j$,计算 Sampled Baseline $G_t^{j\prime}$
更新:$\theta \leftarrow \theta + \alpha \cdot G_t^{j\prime} \cdot \nabla \log \pi_\theta(a_t | s_t)$
until 收敛
6.6 分析
✅ 优点
- 长期优化:直接优化 session 总点击数,而不是单步 CTR,与业务目标一致。
- 多样性的隐式涌现:系统自动学到"适当多样的推荐能让用户多看几屏",不需要显式加多样性约束。
- 端到端:排序策略和多样性目标在同一个网络中联合优化,而非后处理重排。
- 线上 A/B(对比 WGCAR α=0.6):AC +6.22%、AD +4.92%;KL@5/KL@10 更低(多样性更好)。
❌ 局限
- 训练复杂:需要离线仿真环境 SE,SE 本身的质量上限决定了策略的质量上限;如果 SE 不准,会引入 bias。
- On-policy 高方差:REINFORCE 方差大,Sampled Baseline 有所缓解但训练不稳定性仍存在。
- 延迟反馈仍是挑战:用户 bounce 只在 session 末尾观测,稀疏奖励问题依然存在。
- 候选集规模受限:策略网络需要处理整个候选集 $\mathcal{I}$,线上 RT 敏感,需要工程优化(论文将复杂度从 $O(k^2n)$ 降到 $O(kn)$)。
前四篇(MMR / APD / Calibrated Rec / DPP)都是在已有打分的基础上做后处理重排:先有相关性分数,再最大化多样性目标。RL4CTE 则是端到端地学习排序策略,把"用户是否继续浏览"这个长期信号直接用于训练。多样性不再是约束条件,而是 RL 策略为了最大化累计奖励自发习得的行为。
7.1 设计空间全面对比
| 维度 | MMR | Adaptive PD | Calibrated Rec | Fast DPP | RL4CTE |
|---|---|---|---|---|---|
| 多样性度量 | max pair-wise 相似度 | 次模属性覆盖 | KL 散度 | 行列式体积 | 无显式度量(隐式) |
| 优化目标 | Rel - (1-λ)·冗余 | 次模函数最大化 | Rel - λ·KL | log det(L) | CTE(session 总点击) |
| 时间视野 | 单步(贪心) | 单步(贪心) | 单步(贪心) | 单步(贪心) | 多步(session 级 RL) |
| 个性化 | ❌ | ✅ 类目权重 | ✅ 历史分布 | ⚠️(可扩展) | ✅ 用户 embedding |
| 是否端到端 | ❌ | ❌ | ❌ | ❌ | ✅ |
| 训练数据 | 无需训练 | 无需训练 | 无需训练 | 无需训练 | 需大量离线日志 |
| 在线延迟 | 极低 | 低 | 低 | 低(Cholesky加速) | 中(RNN 推断需工程优化) |
| 可解释性 | 高 | 高 | 高 | 中 | 低 |
7.2 方法适用场景对比
🔍 搜索/IR 场景
首选:MMR
候选集由搜索引擎产出,相关性已有良好评分,只需在此基础上减少冗余。MMR 简单直接,$\lambda$ 调参快速,部署成本最低。
🛒 电商浏览/发现
首选:Adaptive PD 或 DPP
需要品类覆盖(APD 更直接)或向量空间多样性(DPP 更精确)。如果有足够的用户行为数据,APD 的个性化权重效果好。
📺 Feed 流/长 session
首选:RL4CTE
当 session 足够长、多步决策的序列效果显著时,RL 端到端优化更有优势。同时考虑 Calibrated Rec 作为后处理保证分布合理性。
7.3 算法复杂度对比
| 方法 | 离线训练 | 在线推断(候选 $n$,输出 $k$) |
|---|---|---|
| MMR | 无 | $O(kn)$ |
| Adaptive PD | $O(d)$ 权重更新 | $O(dkn)$(CELF 加速后更快) |
| Calibrated Rec | 无 | $O(|G|kn)$($|G|$ 为类目数) |
| Fast DPP | 无 | $O(nk + Mk^2)$ |
| RL4CTE | $O(\text{大量离线日志})$ | $O(kn)$(工程优化后) |
8.1 核心脉络回顾
这五篇工作勾勒出多样性重排领域 20 年来的演进主线:
8.2 未解决的关键问题
- 多样性 vs 相关性 vs 公平性的三方博弈:除了用户的多样性需求,还有 item 提供方(商家/内容创作者)的公平性需求——热门内容不能一直霸榜。如何在三者之间找到最优均衡?
- 多样性的评估指标问题:CC@K(品类覆盖率)和 KL@K(分布距离)是代理指标,并不直接对应用户满意度。如何设计真正衡量"用户是否因为多样性而更满意"的指标?
- 长期兴趣演化:Calibrated Rec 假设历史分布代表用户偏好,但用户兴趣会随时间变化。如何动态调整目标分布?
- RL 的 off-policy 数据利用:RL4CTE 用 on-policy REINFORCE,样本效率低。如何利用大量历史 off-policy 数据?(这是电商 RL 推荐的通用难题)
- 大模型时代的多样性重排:LLM 作为 Ranker 时,如何在 beam search 或采样层面注入多样性约束?这与传统重排方法框架完全不同。
8.3 工程实践建议
- 先上线 Calibrated Rec:实现成本最低(后处理),可解释性强,能快速验证分布校准对业务的价值。$\lambda=0.5$ 作为起点。
- 用 DPP 替换或增强多样性度量:如果有商品 embedding,DPP 能捕捉更细粒度的语义多样性;Cholesky 增量更新支持工业级延迟。
- 在长 session 场景引入 RL:当用户浏览深度是关键指标时,RL4CTE 类的方法能带来额外增益;但需要足够的训练数据和工程投入。
- 多样性永远是 tradeoff:多样性过强会伤害头部相关性,业务上需要 A/B 实验确认整体指标(GMV/DAU/留存)的变化,而不只是 CTR 或多样性指标。