这篇文章对应视频:【[Agentic RL] 11 重新理解 DPO,带 KL 正则的 RL 目标函数推导,隐式的奖励模型,DPO 可能的缺陷与不足】(BV1N16ZBuERA)。

我不会把它写成“逐句视频笔记”,而是把 DPO 放回一个更稳的框架里:KL 正则的 RL 目标函数概率建模(Bradley-Terry)。你看完应该能回答这 3 个问题:

  1. DPO 到底在优化什么,它和 “reward - β KL” 的 RL 目标是什么关系?
  2. 为什么说 DPO 有一个“隐式的奖励模型”(implicit RM),它是什么形式?
  3. DPO 为什么会出现一些看起来反直觉的问题(reward hacking / 过拟合 / 生成质量掉 / 长度偏置),以及你在工程里怎么防。

系列导航:

关联阅读(建议顺序):

  1. 先把 KL-constrained RL 的分布视角打通(π* 与 P*)
  2. BT/MLE 的概率建模视角(你会更容易理解 DPO 的 logistic loss)
  3. 如果你最后还是要上 RL,这篇是最小闭环

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

  • DPO 主线(含 KL-RL 目标、π*、DPO loss、缺陷讨论):
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/reward_model/dpo.ipynb
  • DPO 补充(定位:SFT 之后、RL 之前,用作 refinement):
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/reward_model/dpo_supp.ipynb
  • BT / RM 的概率建模(DPO 的“二分类”来自这里):
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/reward_model/Bradley-Terry-RM.ipynb
  • KL-constrained RL 的分布视角(DPO 其实是这条线的一个特例):
    • /Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/sft_rl_fkl_rkl.ipynb

0. 先给结论:DPO 是“KL 正则 RL”的一个离线(offline)特例

你在很多地方看到的 RLHF 目标(写成 sequence-level)大概长这样:

$$
\max_{\pi}\ \mathbb{E}_{x\sim\mathcal{D}}\Big[\ \mathbb{E}_{y\sim\pi(\cdot\mid x)}\big[r(x,y)\big]\ -\ \beta\,D_{\mathrm{KL}}\big(\pi(\cdot\mid x)\ \|\ \pi_{\text{ref}}(\cdot\mid x)\big)\ \Big].
$$

这就是 dpo.ipynb 里写的 “KL-constrained reward maximization objective”。它有两个非常关键的工程含义:

  • 你希望提高 reward(更符合偏好/更正确/更安全)。
  • 你又不希望策略偏离 \\pi\\_{\\text{ref}} 太远(避免跑到 RM/verifier 不可靠的区域,也避免模式坍缩)。

DPO 的核心洞察是:如果你不显式训练 reward model,而是直接拿“偏好对比数据”(winner/loser)来训练 policy,那么在某些假设下,上面这个 RL 目标可以被“降维”为一个监督学习的二分类目标。

这句话要读清楚:

  • DPO 不是 PPO 的替代实现,它更像是:把“在线 rollout + RM 打分 + policy gradient”这条链路,用“离线偏好对比 + log-ratio 分类”替换掉
  • 代价是:它把很多问题“从采样/方差/不稳定”转成了“数据分布/偏好噪声/过拟合”的问题。

1. KL 正则 RL 的解析解:目标分布是 reward-tilted 的 Gibbs 分布

如果我们把上一节的目标写成最优策略 \\pi^*,那么它有一个很漂亮的解析解(这一步在 dpo.ipynb 里给出了关键式子):

$$
\pi^*(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)。

这个式子的直觉非常直接:

  • 参考策略 \\pi\\_{\\text{ref}} 给了你一个“可信的语言分布底座”;
  • reward 通过 \\exp(r/\\beta) 对这个分布做指数加权:
    • reward 高的区域概率被放大;
    • reward 低的区域概率被压低。

分布视角 里你可以把它读成:

你不是在“优化一个神秘 loss”,你是在让策略去拟合一个由 \\pi\\_{\\text{ref}}r 共同定义的目标分布。


2. 隐式奖励模型:reward 可以由 log-ratio 反解出来

上面的解析解可以反过来写成 reward:

$$
r(x,y)=\beta\log\frac{\pi^*(y\mid x)}{\pi_{\text{ref}}(y\mid x)}+\beta\log Z(x).
$$

注意到:

  • \\log Z(x) 只和 x 有关,和 y 无关;
  • 如果我们只关心“同一个 prompt 下,两个回答谁更好”,那么 \\log Z(x) 会在差分里消掉。

于是我们得到一个非常重要的结构:

reward 差分 r(x,y\\_w)-r(x,y\\_l) 本质上就是 policy vs reference 的 log-ratio 差分

这就是所谓的 implicit reward model:你根本不需要显式训练一个 R\_\\phi(x,y),因为在 KL 正则 RL 的最优解附近,reward 已经“编码在 log-ratio 里”了。


3. 为什么 DPO 的 loss 是 logistic regression:Bradley-Terry 一步到位

偏好数据通常长这样:对同一个 x,有一对回答:

  • winner:y\\_w
  • loser:y\\_l

Bradley-Terry(BT)建模的核心是假设:

$$
\mathbb{P}(y_w \succ y_l\mid x)=\sigma\big(r(x,y_w)-r(x,y_l)\big),
$$

其中 \\sigma(\\cdot) 是 sigmoid。

把上一节的 reward 差分用 log-ratio 替换(把 \\log Z(x) 消掉),我们可以得到 DPO 的典型目标(这也是 dpo.ipynb 里写出的那条公式):

$$
\mathcal{L}_{\text{DPO}}(\pi_{\theta};\pi_{\text{ref}})
=-\mathbb{E}_{(x,y_w,y_l)\sim\mathcal{D}}
\Big[
\log\sigma\big(
\beta\,\Delta\log\pi_\theta
-\beta\,\Delta\log\pi_{\text{ref}}
\big)
\Big],
$$

其中

$$
\Delta\log\pi_\theta
=\log\pi_\theta(y_w\mid x)-\log\pi_\theta(y_l\mid x),
\quad
\Delta\log\pi_{\text{ref}}
=\log\pi_{\text{ref}}(y_w\mid x)-\log\pi_{\text{ref}}(y_l\mid x).
$$

把它翻译成一句工程话:

  • 你在做一个二分类:让 y\\_w 的“相对 log-ratio”大于 y\\_l
  • \\beta 控制这个 margin 推得多激进;
  • reference 的 logprob 负责把优化约束在“可信域”附近(并且也显式进入了 margin)。

4. 从公式到代码:DPO 实现的最小骨架(LLM 版)

DPO 的实现本质上只需要两件事:

  1. 当前策略 \\pi\\_\\theta 对两条序列的 logprob(通常是 token logprob 的 sum)。
  2. 参考策略 \\pi\\_{\\text{ref}} 对两条序列的 logprob。

伪代码(关键是“同一个 prompt 的 winner/loser 要用同一个 mask 与聚合口径”):

1
2
3
4
5
6
7
8
9
10
11
12
13
# x: prompt
# y_w, y_l: winner/loser response tokens
# model: pi_theta
# ref_model: pi_ref (frozen)

logp_w = sum_token_logp(model, x, y_w, mask_w) # log pi_theta(y_w|x)
logp_l = sum_token_logp(model, x, y_l, mask_l) # log pi_theta(y_l|x)
ref_logp_w = sum_token_logp(ref_model, x, y_w, mask_w)
ref_logp_l = sum_token_logp(ref_model, x, y_l, mask_l)

logits = beta * ((logp_w - ref_logp_w) - (logp_l - ref_logp_l))
loss = -log_sigmoid(logits).mean()
loss.backward()

三个实现细节我建议你显式写在日志里(否则你很难解释训练曲线):

  1. 你用的是 sum 还是 mean(长度偏置会完全不同)。
  2. mask 是不是严格 token-in-token-out(别把 pad/EOS 之后的 token 混进去)。
  3. ref_logp 是不是用同一个 tokenizer / 同一个对齐方式算出来的(否则会出现“分母错位”的怪现象)。

5. DPO 的“好处”到底是什么:它把 RL 的难点换成了数据难点

和 PPO/GRPO 这种 RLHF 方式比,DPO 的优势主要是工程上的:

  • 不需要 online rollout:不用 vLLM 跑一堆采样,不用处理采样吞吐瓶颈。
  • 不需要显式 RM:不训练 R\_\\phi,也减少了“RM 不稳定 + KL 约束必须很强”的复杂度。
  • 训练更像标准的 SFT:一个固定数据集上做稳定的梯度下降,调试成本低很多。

但它并不是“白捡”。它真正的隐含假设是:

你的偏好数据 \\mathcal{D} 足够代表“模型未来会生成的分布”,以及 BT 偏好概率确实能被某个标量 r(x,y) 解释。

一旦这个假设不成立,你会看到很多 DPO 的反直觉现象。


6. DPO 的缺陷与不足:不是“实现问题”,而是目标函数的自然后果

dpo.ipynb 的 Discussion 里点了几个我认为非常重要的问题。我用更工程化的方式把它们整理出来。

6.1 “评价能力”不等于“生成能力”:你在学打分,不一定学会决策

DPO 的梯度来自:

  • y\\_w 的相对 log-ratio 更大;
  • y\\_l 的相对 log-ratio 更小。

这更像是“学会把一对答案区分开”(ranking / scoring),而不是“在实际 generation 时做出全局最优决策”。

你可以把它类比成:

  • 读棋谱可以让你更会评价棋,但并不保证你下棋就一定更强;
  • 如果模型的 “evaluation” 和 “generation” 没有足够一致的表示结构,DPO 的提升会卡住,甚至出现行为退化。

6.2 Reward hacking / 过拟合:log-ratio 可以被刻意做大

这是 DPO 最容易被忽略、但最值得警惕的一点:

在 DPO loss 里,只要

$$
\frac{\pi_\theta(y_w\mid x)}{\pi_{\text{ref}}(y_w\mid x)}
$$

被推得足够大,loss 就会变小。

模型可以用一种“非常不语言模型”的方式去做大这个 ratio:把概率质量挤到 reference 认为极低概率的区域,从而制造巨大的 log-ratio。

结果可能是:

  • 某些奇怪 token/短语被过度提权;
  • 生成质量(流畅性/可读性)下降,但 loss 仍然很好看;
  • 或者出现局部模式坍缩。

这不是“实现 bug”,而是 objective 的自然后果:你优化的是 log-ratio margin,而不是直接优化 “human-looking / fluent” 的 token NLL。

6.3 长度偏置(Length Bias):sum logprob 会天然惩罚长序列

如果你用 sequence logprob 的 sum

$$
\log\pi(y\mid x)=\sum_{t=1}^{T}\log\pi(a_t\mid s_t),
$$

那么长序列更负(更小),这会把 DPO 的 margin 结构和长度强耦合起来。

常见现象:

  • winner 比 loser 更长时,DPO 可能需要更大的 \\beta 才能把 margin 推过去;
  • 你会在训练过程中看到模型开始偏向短答(或者偏向高概率的模板化答法)。

工程上常见的缓解方式是做 length-normalized logprob(mean),但这会改变目标函数,你需要在论文/对比里说清楚口径。

6.4 偏好噪声与 intransitivity:BT 的建模假设会变成上限

如果偏好数据是:

  • 噪声大;
  • 或者存在明显 intransitivity(A>B, B>C, 但 C>A);

那么 BT 形式的 logistic loss 会“变钝”(这点在 RM 那篇里已经解释过)。

你会看到:

  • loss 下降但行为不动;
  • 或者为了拟合噪声,模型开始做极端 log-ratio(对应 6.2 的过拟合风险)。

7. 把 DPO 放进 Agentic RL / Deep Research:我建议你怎么用

如果你的目标是 agentic RL 用于 deep research,我建议你把 DPO 放在一个更保守的位置:

  • 它更适合做 SFT 之后的 refinement(把“偏好”压进去,让输出更符合风格/格式/规范)。
  • 但如果你的核心指标是 可验证正确性(引用可追溯、事实一致性、推理正确率、成本/时延),最终往往还是要回到:
    • verifier / rule-based reward / outcome reward;
    • 以及更偏 on-policy 的优化(哪怕是 GRPO/RLOO 这类不训练 critic 的算法)。

你可以把 DPO 当成“更稳定的对齐步骤”,但不要把它当成“能替代整个 RL 闭环”的魔法。


8. 小结

  1. DPO 的数学骨架来自 KL 正则 RLreward - β KL
  2. 解析解 \\pi^* \\propto \\pi\\_{ref}\\exp(r/\\beta) 给出了一个关键映射:reward 可以由 log-ratio 反解(隐式 RM)。
  3. BT 偏好建模把它降维成监督学习:DPO loss 就是对 log-ratio margin 做 logistic regression。
  4. DPO 的风险也来自同一个结构:log-ratio 可以被极端放大(reward hacking/过拟合),并且与长度偏置/数据噪声强耦合。
  5. 对 agentic RL/deep research:我更建议把 DPO 用作 refinement,而把“可验证指标”的提升交给 verifier + on-policy 优化闭环。