这篇文章对应视频:【[Agentic RL] 10 分布的视角理解 LLM 的 SFT 训练和 RL 训练,Forward/Reverse KL,分布与奖励】(BV1WvrGBGEbf)。

我会按“分布匹配(distribution matching)”的视角,把 SFT 与 RL(RLHF/RLVR/RFT/GRPO/DAPO…)放到同一个坐标系里解释清楚:

  1. SFT 本质是 forward KL:用数据分布 $P_{\text{data}}$ 去“覆盖”模型分布 $\pi_\theta$(mode-covering)。
  2. 带 KL 正则的 RL 本质是 reverse KL:用模型分布 $\pi_\theta$ 去“追逐”一个由 reward 定义的目标分布 $P^*$(mode-seeking)。
  3. 你在工程里看到的 KL、entropy、以及“reward in loss vs in reward”,都只是这套分布视角的不同落地方式。

系列导航:

关联阅读(建议顺序):

  1. PPO/GRPO 的 loss 组件(含 KL/entropy/聚合)
  2. RL4LLM 最小闭环:reward + PG/KL 的工程细节
  3. Reward Model:BT/MLE 的概率建模视角
  4. 分布一致性:token-in-token-out

配套仓库(你本地已下载)里,本文主要对齐这些笔记:

  • 概率分布视角:SFT forward KL vs RL reverse KL(含 GMM 例子)
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/sft_rl_fkl_rkl.ipynb
  • KL 的数值含义与单位(nats/token、ppl 与 KL 的关系、pytorch 的 forward KL 计算)
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/training_practices/kl_数值内涵.ipynb
  • 工程里 KL “in reward vs as loss”、以及 off-policy 下估计偏差的注意点(可选,偏深)
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/training_practices/review_kl.ipynb

0. 一个统一的视角:你到底在“把哪个分布推向哪个分布”

不管你做的是:

  • SFT(cross entropy / next token prediction)
  • RLHF(PPO/GRPO/RLOO/REINFORCE++)
  • DPO/IPO/SPIN(偏好优化)

你都可以抽象成一句话:

给定一个输入 $x$(prompt/上下文),你在学习一个条件分布 $\pi_\theta(y\mid x)$,让它在某个“目标分布”的意义下更接近最优。

区别只在于:目标分布到底是谁

为了少绕弯,我后面用两类分布来讨论:

  1. 数据分布(人类/合成/标注数据):$P_{\text{data}}(y\mid x)$
  2. 奖励诱导分布(由 reward + reference 共同定义):$P^*(y\mid x)$

其中 $P^*$ 会在 RL 小节里给出闭式形式。


1. SFT:MLE 等价于最小化 Forward KL(mode-covering)

SFT 的目标是最大化对数似然(MLE):

$$
\max_\theta\ \mathbb{E}_{(x,y)\sim P_{\text{data}}}\big[\log \pi_\theta(y\mid x)\big].
$$

把 forward KL 写出来:

$$
\begin{aligned}
D_{\mathrm{KL}}(P_{\text{data}} | \pi_\theta)
&= \mathbb{E}_{(x,y)\sim P_{\text{data}}}\big[\log P_{\text{data}}(y\mid x)-\log \pi_\theta(y\mid x)\big] \\
&= \underbrace{\mathbb{E}_{P_{\text{data}}}\big[\log P_{\text{data}}\big]}_{\text{数据熵(常数)}}

  • \underbrace{\mathbb{E}_{P_{\text{data}}}\big[\log \pi_\theta\big]}_{\text{SFT 目标}}.
    \end{aligned}
    $$

因为第一项和 $\theta$ 无关,所以:

最大化 SFT 的对数似然 $\Longleftrightarrow$ 最小化 $D_{\mathrm{KL}}(P_{\text{data}}|\pi_\theta)$。

1.1 为什么说 forward KL 是“mode-covering”

forward KL 的期望是在 $P_{\text{data}}$ 上取的:

  • 只要数据分布某个区域有概率质量(哪怕很小),模型在那块给得太低,就会被惩罚。
  • 结果是:模型倾向于“覆盖”数据分布中出现过的各种模式(多样性更强)。

这就是为什么纯 SFT 的输出往往更“像人类平均值”:

  • 风格多、表达方式多、语气多;
  • 但对长尾知识/稀有模式的拟合更脆弱,容易出现“形式像但事实不稳”的问题(你可以把它理解成:为了覆盖长尾,模型不得不在低密度区域硬分配概率)。

1.2 一个工程结论:SFT 更像“把分布铺开”,RL 更像“把分布削尖”

这句在 sft_rl_fkl_rkl.ipynb 里说得很直白:

  • SFT 在“模仿”人类分布的平均形态(宽、平缓)
  • RL 在“坍缩”到奖励最高的尖峰(窄、尖锐)

你后面如果看到 RL 模型变得“更固执、更单一”,不要惊讶:这是 reverse KL 的自然产物(下一节解释)。


2. 带 KL 正则的 RL:目标函数等价于最小化 Reverse KL(mode-seeking)

在 RL4LLM 里,你最常见的目标(写成 sequence-level)大概是:

$$
J(\theta)=\mathbb{E}_{y\sim \pi_\theta(\cdot|x)}[R(x,y)]-\beta D_{\mathrm{KL}}(\pi_\theta(\cdot|x)|\pi_{\text{ref}}(\cdot|x)).
$$

其中:

  • $R(x,y)$ 是 reward(来自 RM/verifier/规则/指标等)
  • $\pi_{\text{ref}}$ 常见是 SFT 模型(anchor)
  • $\beta$ 控制“奖励最大化”与“保持分布不跑飞”的权衡

这玩意看起来像“奖励 - KL 正则”,但它更有用的理解方式是:

它定义了一个目标分布 $P^*$,而训练就是让 $\pi_\theta$ 去逼近 $P^*$。

2.1 奖励诱导分布 $P^*$:指数加权(Gibbs / Boltzmann)

如果你把 $P^*$ 定义成:

$$
P^*(y\mid x)=\frac{1}{Z(x)}\ \pi_{\text{ref}}(y\mid x)\ \exp\Big(\frac{R(x,y)}{\beta}\Big),
$$

其中 $Z(x)$ 是归一化常数(partition function)。

那么可以推到一个非常关键的等价关系(sft_rl_fkl_rkl.ipynb 里给了详细推导):

$$
\max_\theta J(\theta)\ \Longleftrightarrow\ \min_\theta D_{\mathrm{KL}}(\pi_\theta | P^*)\quad (\text{Reverse KL}).
$$

这句话的含义非常大:

  • RL 不是“在最小化一个随便写的 loss”
  • RL 在做的是:用 $\pi_\theta$ 去匹配一个由 reward 指定的目标分布(并且是 reverse KL)

2.2 为什么 reverse KL 是“mode-seeking”

reverse KL 的期望是在 $\pi_\theta$ 上取的:

$$
D_{\mathrm{KL}}(\pi_\theta|P^*)=\mathbb{E}_{y\sim \pi_\theta}\Big[\log \pi_\theta(y|x)-\log P^*(y|x)\Big].
$$

这会产生一个很强的倾向:

  • 如果某些区域奖励低、$P^*$ 很小,那么只要 $\pi_\theta$ 不去采样那块(概率趋近 0),那块就几乎不会贡献 loss。
  • 所以策略会把概率质量集中到少数高 reward 的区域(尖峰),形成“坍缩/削尖”。

这就是为什么:

  • RL 后分布会变窄、熵降低(更确定、更固执)
  • 同时也解释了 reward hacking:只要 RM/verifier 有漏洞,策略会把概率质量挤到漏洞区域,把 $P^*$ 的尖峰“造出来”

2.3 KL 约束的工程意义:限制在 RM 的可信域附近

上面 $P^*$ 里有 $\pi_{\text{ref}}$。这不是数学装饰,而是工程护栏:

  • RM 是在某个数据分布上训练出来的,只在那附近可靠
  • 让策略偏离太远,RM 打分就可能失真(OOD)
  • 用 KL 把策略锚在 ref 附近,相当于把探索限制在“RM 可信域”

这件事我在 RM 那篇里也强调过:KL 约束更多是在保护“评估系统”的有效性,而不只是保护语言质量。


3. Forward vs Reverse KL:一个经典直觉(GMM 例子)

你可以用一个“双峰分布 vs 单峰近似”的例子建立直觉:

  • target 分布 $P$ 是双峰混合高斯(两个 mode)
  • model 分布 $Q_\theta$ 是单峰高斯(只能选一个 mode 或者折中)
  1. 最小化 forward KL:$D_{\mathrm{KL}}(P|Q_\theta)$
    • 因为期望在 $P$ 上取,$Q$ 必须在两个峰附近都给出足够概率,否则会被惩罚
    • 结果通常是:$Q$ 会把方差拉大,去“覆盖”两个峰(mode-covering)
  2. 最小化 reverse KL:$D_{\mathrm{KL}}(Q_\theta|P)$
    • 因为期望在 $Q$ 上取,$Q$ 只需要把概率质量放在一个峰上就能获得较小 KL
    • 结果通常是:$Q$ 会选择其中一个峰并收缩(mode-seeking)

把它映射回 LLM:

  • SFT(forward KL)更倾向覆盖多样性
  • RL(reverse KL)更倾向追逐高 reward 的尖峰

这也是为什么“只靠 SFT 很难得到极致对齐/极致偏好”,而“只靠 RL 很容易变单一且 reward-hack”:它们本质上在优化不同方向的 KL。


4. KL 在 LLM 里怎么算:token-level、nats/token、以及 ppl 的关系

这一节的目标是:让你能读懂训练日志里的 KL 数值到底是什么量纲、为什么会随聚合方式变化。

4.1 KL 的单位:nats/token(以及它和 ppl 的指数关系)

kl_数值内涵.ipynb 里给了一个很实用的等式:

$$
D_{\mathrm{KL}}(P|Q)=H(P,Q)-H(P),
$$

以及 perplexity 的关系:

$$
\frac{\mathrm{ppl}(P,Q)}{\mathrm{ppl}(P)}=\exp\big(D_{\mathrm{KL}}(P|Q)\big).
$$

工程直觉:

  • 你看到的 KL(如果是按 token 平均)就是“每个 token 平均多付出了多少信息量”
  • exp(KL) 就是 perplexity 的倍率变化

4.2 forward KL(全词表求和)vs sampled KL(只用 logprob 差)

严格的 forward KL(下一 token 分布)是对词表求和:

$$
D_{\mathrm{KL}}(P|Q)=\sum_v P(v)\,[\log P(v)-\log Q(v)].
$$

在 PyTorch 里常见写法(来自 notebook):

1
2
3
log_q = log_softmax(logits, dim=-1)        # Q
log_p = log_softmax(ref_logits, dim=-1) # P
kl = F.kl_div(log_q, log_p, reduction=\"none\", log_target=True)

但在大模型 RL 训练里,很多时候不会每步都算“全词表 KL”(太贵),而是用更便宜的 sampled proxy:

  • 在 rollout 采样到的 token 上,记录 logp_new - logp_ref
  • 聚合成 token-level 或 sequence-level 的平均

这类 proxy 更接近 $D_{\mathrm{KL}}(\pi_\theta|\pi_{\text{ref}})$(reverse KL)的 Monte Carlo 估计。

因此你在日志里看到的 KL 需要先问清楚两件事:

  1. 是 forward 还是 reverse(期望在哪个分布上)
  2. 是全词表 KL 还是 sampled proxy(计算口径完全不同)

5. “KL in reward” vs “KL as loss”:它们不是口味差异,是估计器差异

你会看到两类常见写法:

  1. PPO 风格:把 KL 惩罚写进每步 reward(in reward)
  2. GRPO/DAPO 风格:把 KL 写成独立 loss(as loss)

review_kl.ipynb 里还提到了一类常见的 “k3” 形式(非负、凸、二阶匹配):

$$
k_3(x)=\frac{\pi_{\text{ref}}(x)}{\pi_\theta(x)}-1-\log \frac{\pi_{\text{ref}}(x)}{\pi_\theta(x)}.
$$

这些写法背后的关键不是“哪个更优雅”,而是:

  • 你在用哪个 KL 的方向(mode-seeking vs mode-covering)
  • 你在用哪个估计器(on-policy vs off-policy、是否引入 importance ratio)
  • 你在用哪个聚合口径(token/seq/group mean/sum)

所以我建议你把“KL 放哪”理解成:选择一个在你当前采样/并行/代价约束下可实现、且数值稳定的估计器

(这部分展开会很深;如果你后面要细抠 GRPO/DAPO 的 KL 估计偏差,再回看 review_kl.ipynb 会更合适。)


6. 对 deep research / agentic RL 的落地启示:reward 其实是在“塑形目标分布”

当你接受了 $P^*(y|x)\propto \pi_{\text{ref}}(y|x)\exp(R/\beta)$ 这个视角之后,reward 设计就变得更清晰:

  • reward 不是“让模型变聪明”的魔法分数
  • reward 是在改变目标分布的形状:你在用 $\exp(R/\beta)$ 对参考分布做指数加权

于是你会自然地得到两个工程原则:

  1. reward 越尖(极端偏好/离散 0-1/强 bias),$P^*$ 越尖,策略越容易坍缩
  2. reward 越不可靠(verifier 漏洞/启发式偏差),$P^*$ 的尖峰越可能落在漏洞上 → reward hacking

因此对 deep research agent,我更建议你:

  • 优先用可验证信号(引用可追溯、事实一致性、覆盖率、成本、时延)
  • 把不可验证的“写作风格/逻辑性”放在次级 reward,并做分层/多目标
  • 始终用 token-in-token-out 保证分布一致性(否则你连 “$\pi_\theta$ 产生了什么” 都说不清)

7. 小结(你只需要记住的 6 句话)

  1. SFT 的 MLE 等价于最小化 forward KL:$D_{\mathrm{KL}}(P_{\text{data}}|\pi_\theta)$(mode-covering)。
  2. 带 KL 正则的 RL 等价于最小化 reverse KL:$D_{\mathrm{KL}}(\pi_\theta|P^*)$(mode-seeking)。
  3. $P^*$ 的形状由 reward 决定:$P^* \propto \pi_{\text{ref}}\exp(R/\beta)$,reward 就是在塑形目标分布。
  4. forward KL 更保多样性但更像“平均人类”;reverse KL 更会削尖分布但更容易坍缩与 reward hacking。
  5. 训练日志里的 KL 必须先问清楚口径(方向/估计器/聚合/是否 sampled)。
  6. 真正工程上最重要的是:把策略限制在评估系统(RM/verifier)可信域附近,让“优化”这件事有意义。