Files
2026-07-13 13:37:02 +08:00

1211 lines
124 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kl Divergence Rlhf Tutorial</title>
<meta name="generator" content="ARIS render-html (academic, v1)">
<meta name="aris:source-path" content="docs/tutorials/kl_divergence_rlhf_tutorial.md">
<meta name="aris:source-sha256" content="f0b8b5e62023c40790eecc3c8e2e1afdf9fceea26ffa5b9859d0d4382cb7ea4a">
<meta name="aris:generated-at" content="2026-05-19 19:13 UTC">
<!-- MathJax 3 -->
<script>
window.MathJax = {
tex: { inlineMath: [['$', '$'], ['\\(', '\\)']], displayMath: [['$$', '$$'], ['\\[', '\\]']], processEscapes: true },
options: { skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'] }
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" async></script>
<!-- highlight.js -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-light.min.css">
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
<script>document.addEventListener('DOMContentLoaded', () => hljs.highlightAll());</script>
<style>
:root {
--bg: #fdfcf7;
--bg-soft: #f4f1ea;
--bg-code: #f8f5ec;
--ink: #1a1a1a;
--ink-soft: #4a4a4a;
--ink-muted: #6b6b6b;
--primary: #1a4a8c;
--primary-soft: #2d6cb8;
--accent: #b8390e;
--warn: #b45309;
--warn-bg: #fef3c7;
--info-bg: #dbeafe;
--good-bg: #d1fae5;
--good: #065f46;
--bad-bg: #fee2e2;
--bad: #991b1b;
--border: #d6d0c0;
--border-soft: #e8e3d5;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
font-family: "Source Serif Pro", "Source Serif 4", "Crimson Pro", "Georgia", "Songti SC", "STSong", serif;
line-height: 1.65;
color: var(--ink);
background: var(--bg);
margin: 0;
padding: 0;
font-size: 16px;
}
.layout {
max-width: 1280px;
margin: 0 auto;
display: grid;
grid-template-columns: 260px 1fr;
gap: 48px;
padding: 40px 32px;
}
nav.toc {
position: sticky;
top: 24px;
align-self: start;
font-size: 13px;
max-height: calc(100vh - 48px);
overflow-y: auto;
border-right: 1px solid var(--border-soft);
padding-right: 16px;
}
nav.toc h3 {
margin: 0 0 12px;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--ink-muted);
font-weight: 600;
}
nav.toc ol { list-style: none; padding: 0; margin: 0; counter-reset: toc; }
nav.toc ol li { margin: 5px 0; counter-increment: toc; }
nav.toc ol li::before { content: counter(toc) ". "; color: var(--ink-muted); margin-right: 4px; }
nav.toc a {
color: var(--ink-soft);
text-decoration: none;
border-bottom: 1px dotted transparent;
}
nav.toc a:hover { color: var(--primary); border-bottom-color: var(--primary); }
nav.toc ul { list-style: none; padding-left: 14px; margin: 3px 0; font-size: 12px; }
nav.toc ul li::before { content: "→ "; color: var(--border); }
main { min-width: 0; }
header.hero {
border-bottom: 3px double var(--primary);
padding-bottom: 24px;
margin-bottom: 32px;
}
header.hero .eyebrow {
color: var(--accent);
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.12em;
font-weight: 600;
margin-bottom: 8px;
}
header.hero h1 {
font-size: 32px;
line-height: 1.2;
margin: 0 0 12px;
color: var(--ink);
font-weight: 700;
letter-spacing: -0.01em;
}
header.hero .subtitle {
font-size: 16px;
color: var(--ink-soft);
margin: 0 0 8px;
font-style: italic;
}
header.hero .byline {
font-size: 14px;
color: var(--ink-soft);
margin: 0 0 20px;
}
header.hero .byline strong {
color: var(--ink);
font-weight: 600;
}
header.hero .meta {
display: flex;
gap: 20px;
flex-wrap: wrap;
font-size: 12px;
color: var(--ink-muted);
border-top: 1px solid var(--border-soft);
padding-top: 14px;
}
header.hero .meta span strong { color: var(--ink-soft); }
header.hero .meta code {
font-family: "JetBrains Mono", "SF Mono", "Menlo", "Consolas", monospace;
font-size: 11px;
background: var(--bg-soft);
padding: 1px 5px;
border-radius: 3px;
border: 1px solid var(--border-soft);
}
h2 {
font-size: 24px;
margin: 44px 0 14px;
padding-bottom: 8px;
border-bottom: 1px solid var(--border);
color: var(--ink);
font-weight: 700;
}
h2 .num { color: var(--primary); font-weight: 600; margin-right: 8px; }
h3 { font-size: 19px; margin: 28px 0 10px; color: var(--primary); font-weight: 600; }
h4 { font-size: 16px; margin: 20px 0 8px; color: var(--ink); font-weight: 600; }
p { margin: 10px 0; }
ul, ol { padding-left: 22px; margin: 10px 0; }
ul li, ol li { margin: 4px 0; }
ul li::marker { color: var(--primary); }
strong { color: var(--accent); font-weight: 600; }
em { color: var(--ink-soft); }
a { color: var(--primary); }
a:hover { color: var(--accent); }
code:not(.hljs) {
font-family: "JetBrains Mono", "SF Mono", "Menlo", "Consolas", monospace;
font-size: 0.86em;
background: var(--bg-code);
padding: 1px 5px;
border-radius: 3px;
border: 1px solid var(--border-soft);
color: var(--accent);
}
pre {
background: #fafaf6;
border: 1px solid var(--border);
border-left: 4px solid var(--primary);
padding: 0;
overflow-x: auto;
border-radius: 4px;
margin: 14px 0;
}
pre code, pre code.hljs {
background: transparent !important;
display: block;
padding: 14px 18px !important;
font-size: 13px;
line-height: 1.55;
font-family: "JetBrains Mono", "SF Mono", "Menlo", monospace;
color: var(--ink);
}
pre.diagram {
background: #f9f6ed;
border-left: 4px solid var(--accent);
font-size: 12.5px;
line-height: 1.4;
}
.callout {
margin: 16px 0;
padding: 12px 16px;
border-radius: 4px;
border-left: 4px solid;
font-size: 15px;
}
.callout-title {
font-weight: 600;
margin-bottom: 6px;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.callout-info { background: var(--info-bg); border-left-color: var(--primary); }
.callout-info .callout-title { color: var(--primary); }
.callout-warn { background: var(--warn-bg); border-left-color: var(--warn); }
.callout-warn .callout-title { color: var(--warn); }
.callout-good { background: var(--good-bg); border-left-color: var(--good); }
.callout-good .callout-title { color: var(--good); }
.callout-bad { background: var(--bad-bg); border-left-color: var(--bad); }
.callout-bad .callout-title { color: var(--bad); }
table {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
font-size: 14px;
border: 1px solid var(--border);
border-radius: 4px;
overflow: hidden;
}
thead { background: var(--primary); color: white; }
th, td {
text-align: left;
padding: 9px 12px;
border-bottom: 1px solid var(--border-soft);
vertical-align: top;
}
th { font-weight: 600; font-size: 13px; letter-spacing: 0.02em; }
tr:last-child td { border-bottom: none; }
tbody tr:nth-child(even) { background: var(--bg-soft); }
details.qa, details {
background: white;
border: 1px solid var(--border-soft);
border-radius: 6px;
margin: 10px 0;
padding: 0;
}
details summary {
cursor: pointer;
padding: 10px 14px;
font-weight: 600;
font-size: 14px;
color: var(--primary);
list-style: none;
user-select: none;
}
details summary::-webkit-details-marker { display: none; }
details summary::before {
content: "▸ ";
margin-right: 4px;
display: inline-block;
transition: transform 0.15s;
}
details[open] summary::before { transform: rotate(90deg); }
details[open] summary { border-bottom: 1px solid var(--border-soft); }
details > :not(summary) { padding: 10px 14px; }
details p:first-of-type { margin-top: 8px; }
mjx-container[display="true"] { margin: 12px 0 !important; }
footer.aris-footer {
margin-top: 60px;
padding-top: 20px;
border-top: 1px solid var(--border);
font-size: 12px;
color: var(--ink-muted);
}
footer.aris-footer a { color: var(--ink-muted); border-bottom: 1px dotted var(--border); }
@media (max-width: 900px) {
.layout { grid-template-columns: 1fr; gap: 20px; padding: 20px 16px; }
nav.toc {
position: static;
max-height: none;
border-right: none;
border-bottom: 1px solid var(--border-soft);
padding-right: 0;
padding-bottom: 14px;
}
header.hero h1 { font-size: 24px; }
h2 { font-size: 20px; }
}
@media print {
nav.toc { display: none; }
.layout { grid-template-columns: 1fr; padding: 0; }
body { background: white; }
header.hero { border-bottom-color: var(--ink); }
}
</style>
</head>
<body>
<div class="layout">
<nav class="toc">
<h3>Contents</h3>
<ol>
<li><a href="#0-tldr-cheat-sheet">§0 TL;DR Cheat Sheet</a>
</li>
<li><a href="#1-kl-基础">§1 KL 基础</a>
<ul>
<li><a href="#11-定义性质记号">1.1 定义、性质、记号</a></li>
<li><a href="#12-forward-kl-vs-reverse-klmass-covering-还是-mode-seeking">1.2 Forward KL vs Reverse KLmass-covering 还是 mode-seeking</a></li>
<li><a href="#13-与其他-divergence-的关系">1.3 与其他 divergence 的关系</a></li>
<li><a href="#14-为什么-rlhf-要加-kl">1.4 为什么 RLHF 要加 KL</a></li>
</ul>
</li>
<li><a href="#2-kl-estimatorsk1--k2--k3面试核心">§2 KL Estimatorsk1 / k2 / k3):面试核心</a>
<ul>
<li><a href="#21-问题设置">2.1 问题设置</a></li>
<li><a href="#22-k1-estimator--直接代入定义">2.2 k1 estimator —— &quot;直接代入定义&quot;</a></li>
<li><a href="#23-k2-estimator--l2-form">2.3 k2 estimator —— &quot;$L^2$ form&quot;</a></li>
<li><a href="#24-k3-estimator-schulman-2020-blog--非负无偏-value-estimator但作为-loss-项是-biased-gradient见-36">2.4 k3 estimator (Schulman 2020 blog) —— **非负无偏 value estimator**(但作为 loss 项是 biased gradient,见 §3.6</a></li>
<li><a href="#25-三者对比表">2.5 三者对比表</a></li>
<li><a href="#26-代码三估计器--variance-对比-simulation">2.6 代码:三估计器 + variance 对比 simulation</a></li>
</ul>
</li>
<li><a href="#3-kl-在-rlhf-中的两种放置">§3 KL 在 RLHF 中的两种放置</a>
<ul>
<li><a href="#31-option-ain-reward-shapingppo-rlhf--instructgpt-标准做法">3.1 Option AIn-reward shapingPPO RLHF / InstructGPT 标准做法)</a></li>
<li><a href="#32-option-bin-loss-regularizationgrpo--dapo-做法">3.2 Option BIn-loss regularizationGRPO / DAPO 做法)</a></li>
<li><a href="#33-两者数学上等价工程上不等价">3.3 两者数学上等价?工程上不等价</a></li>
<li><a href="#34-实操哪一种用在哪">3.4 实操:哪一种用在哪?</a></li>
<li><a href="#36-estimator-placement-的-gradient-bias-分析rethinking-kl-regularization-in-rlhf">3.6 Estimator placement 的 gradient bias 分析(Rethinking KL Regularization in RLHF</a></li>
</ul>
</li>
<li><a href="#4--调度">§4 β 调度</a>
<ul>
<li><a href="#41-固定---baseline">4.1 固定 β —— baseline</a></li>
<li><a href="#42-adaptive---schulman-ppo-penalty-原版">4.2 Adaptive β —— Schulman PPO-Penalty 原版</a></li>
<li><a href="#43--annealing-schedule--类似-learning-rate-schedule">4.3 β annealing schedule —— 类似 learning rate schedule</a></li>
<li><a href="#44--失败模式">4.4 β 失败模式</a></li>
<li><a href="#45-adaptive--代码示例">4.5 Adaptive β 代码示例</a></li>
</ul>
</li>
<li><a href="#5-kl-与-dpo--grpo--simpo--kto--ipo-的关系">§5 KL 与 DPO / GRPO / SimPO / KTO / IPO 的关系</a>
<ul>
<li><a href="#51-dpoimplicit-reward----sequence-log-density-ratio">5.1 DPOimplicit reward = β × sequence log-density ratio</a></li>
<li><a href="#52-grpok3-kl-in-loss">5.2 GRPOk3 KL in loss</a></li>
<li><a href="#53-simpo去掉-reference没有-kl-anchor">5.3 SimPO:去掉 reference,没有 KL anchor</a></li>
<li><a href="#54-kto--ipo--orpo-的-kl-处理">5.4 KTO / IPO / ORPO 的 KL 处理</a></li>
<li><a href="#55-recent-papers-2024-2026">5.5 Recent papers (2024-2026)</a></li>
</ul>
</li>
<li><a href="#6-theoreticalkl-regularized-rl-的最优-policy--reward-overoptimization">§6 TheoreticalKL-Regularized RL 的最优 policy + Reward Overoptimization</a>
<ul>
<li><a href="#61-kl-regularized-rl-闭式解dpo-的数学基础">6.1 KL-Regularized RL 闭式解(DPO 的数学基础)</a></li>
<li><a href="#62-从最优-policy-反解-implicit-reward">6.2 从最优 policy 反解 implicit reward</a></li>
<li><a href="#63-bradley-terry-偏好模型下的-rl-等价于-dpo">6.3 Bradley-Terry 偏好模型下的 RL 等价于 DPO</a></li>
<li><a href="#64-reward-overoptimizationgao-schulman-hilton-2023-icml">6.4 Reward OveroptimizationGao, Schulman, Hilton 2023 ICML</a></li>
<li><a href="#65-kl-与-chi2-gap-的关系">6.5 KL 与 $\chi^2$ gap 的关系</a></li>
<li><a href="#66-sequence-level-vs-token-level-kl">6.6 Sequence-level vs Token-level KL</a></li>
</ul>
</li>
<li><a href="#7-实践--代码">§7 实践 + 代码</a>
<ul>
<li><a href="#71-ppo-风格in-reward-shaping-实现">7.1 PPO 风格:In-reward shaping 实现</a></li>
<li><a href="#72-grpo-风格in-loss-regularization-实现k3">7.2 GRPO 风格:In-loss regularization 实现(k3</a></li>
<li><a href="#73-dpo-闭式-loss--implicit-reward-监控">7.3 DPO 闭式 loss + implicit reward 监控</a></li>
<li><a href="#74-reward-overoptimization-监控">7.4 Reward overoptimization 监控</a></li>
<li><a href="#75-工程清单debug-checklist">7.5 工程清单(debug checklist</a></li>
</ul>
</li>
<li><a href="#8-失败模式kl-collapse--runaway--reward-hacking">§8 失败模式:KL Collapse / Runaway / Reward Hacking</a>
<ul>
<li><a href="#81-kl-collapse-过大或-entropy-太低">8.1 KL Collapse(β 过大或 entropy 太低)</a></li>
<li><a href="#82-kl-runaway-过小或-reward-信号太强">8.2 KL Runaway(β 过小或 reward 信号太强)</a></li>
<li><a href="#83-reward-overoptimizationkl-距离的-inverted-u">8.3 Reward OveroptimizationKL 距离的 inverted-U</a></li>
<li><a href="#84-length-biasdpo-特有也可视作-kl-anchor-不够强">8.4 Length biasDPO 特有,也可视作 KL anchor 不够强)</a></li>
<li><a href="#85-reference-policy-wrong-checkpoint-failure">8.5 Reference policy &quot;wrong checkpoint&quot; failure</a></li>
</ul>
</li>
<li><a href="#9-25-高频面试题">§9 25 高频面试题</a>
<ul>
<li><a href="#l1-必会题10-题">L1 必会题(10 题)</a></li>
<li><a href="#l2-进阶题10-题">L2 进阶题(10 题)</a></li>
<li><a href="#l3-顶级-lab-题5-题">L3 顶级 lab 题(5 题)</a></li>
</ul>
</li>
<li><a href="#a-附录参考文献清单">§A 附录:参考文献清单</a>
</li>
</ol>
</nav>
<main>
<header class="hero">
<h1>Kl Divergence Rlhf Tutorial</h1>
<div class="meta">
<span><strong>Source:</strong> <code>docs/tutorials/kl_divergence_rlhf_tutorial.md</code></span>
<span><strong>SHA256:</strong> <code>f0b8b5e62023</code></span>
<span><strong>Rendered:</strong> 2026-05-19 19:13 UTC</span>
</div>
</header>
<h2 id="0-tldr-cheat-sheet">§0 TL;DR Cheat Sheet</h2>
<div class="callout callout-info"><div class="callout-title">8 句话搞定 RLHF 里的 KL</div><p>一页拿下面试核心要点(详见后文 §1–§8 推导)。</p></div>
<ol><li><strong>定义</strong>$\text{KL}(p \| q) = \mathbb{E}_{x \sim p}[\log(p(x)/q(x))]$,非负、不对称、非度量;在 RLHF 里 $p = \pi_\theta$、$q = \pi_\text{ref}$,作用是把 RL 后的 policy 锚在 SFT 附近防止 reward hacking。</li><li><strong>Forward vs Reverse</strong>:约定 $p$ 为数据/目标、$q_\theta$ 为变分/优化分布——<strong>Forward KL</strong> = $\text{KL}(p\|q_\theta)$mass-covering),<strong>Reverse KL</strong> = $\text{KL}(q_\theta\|p)$mode-seeking)。RLHF 用 $\text{KL}(\pi_\theta \| \pi_\text{ref})$,按这个约定属于 <strong>reverse KL</strong>$\pi_\theta$ 是变分一侧),mode-seeking 性质正好符合 RL 目标:让 $\pi_\theta$ 在 $\pi_\text{ref}$ 高密度区域选 reward 高的 mode;工程上也可行——直接对 rollout 采样估计即可。注意不同社区命名稍有差异,但 DPO / RLOO / "Rethinking KL" / "Comedy of Estimators" 这类 2024-2026 RLHF 文献都把 $\text{KL}(\pi_\theta \| \pi_\text{ref})$ 称 reverse KL。</li><li><p><strong>三大 KL Estimator (Schulman 2020 blog <code>joschu.net/blog/kl-approx.html</code>)</strong></p>
<ul><li><strong>k1</strong> = $\log(\pi_\theta/\pi_\text{ref})$ — 无偏但方差大、可负(不可读做"距离")。</li><li><strong>k2</strong> = $\tfrac{1}{2}(\log(\pi_\theta/\pi_\text{ref}))^2$ — 总是非负但<strong>有偏</strong>(二阶 Taylor 近似)。</li><li><strong>k3</strong> = $(\pi_\text{ref}/\pi_\theta) - \log(\pi_\text{ref}/\pi_\theta) - 1$ — <strong>无偏 + 非负 + 低方差</strong>,从恒等式 $\mathbb{E}_q[f(\log p/q)]$$f(x)=e^x-x-1$)导出。</li></ul></li><li><strong>两种放置</strong>(a) <strong>In-reward shaping</strong>$\tilde{r}_t = r_t - \beta \cdot \text{KL}_t$,与 advantage / GAE 一起算;(b) <strong>In-loss regularization</strong>$\mathcal{L} = \mathcal{L}_\text{PG} + \beta \cdot \mathbb{E}[\text{KL}]$。<strong>InstructGPT/Anthropic PPO 用 (a)GRPO 用 (b) + k3 estimator</strong><strong>目标函数相同,但梯度路径不同</strong>——在 principled estimator 下(如 (a) k1-in-reward 或 (b) k2-as-losson-policy 是 gradient-equivalentGRPO 的 (b) k3-as-loss 实际有 $O(\Delta^2)$ first-order Taylor bias(见 §3.6 + Rethinking KL 2510.01555)。两种 placement 对 PPO clip / importance ratio 截断的响应也不同。</li><li><strong>β 调度</strong>:固定 β(最简单)、<strong>Adaptive β</strong>PPO-Penalty 原版,按 measured KL 距 target 拉 β)、Annealing β(早期紧后期松,类似 SFT-to-RL 过渡)。<strong>β 过大学不到东西</strong>policy 卡在 ref 附近),<strong>β 过小 reward hack</strong>policy 漂掉、长答案/谄媚)。</li><li><strong>KL-regularized RL 闭式最优 policy</strong>:对 BT-style reward 目标 $\max_\pi \mathbb{E}[r] - \beta \cdot \text{KL}(\pi\|\pi_\text{ref})$ 求解,唯一闭式解为 $\pi^*(y|x) \propto \pi_\text{ref}(y|x) \exp(r(x,y)/\beta)$。<strong>DPO 就是把这个反解代入 Bradley-Terry</strong>,得到 $r = \beta \log(\pi^*/\pi_\text{ref}) + \beta\log Z$partition function $\log Z$ 在 pairwise 差里<strong>消掉</strong></li><li><strong>DPO/GRPO/SimPO 中 KL 的位置</strong>DPO 的 implicit reward $\hat r_\theta = \beta\log(\pi_\theta/\pi_\text{ref})$ 是 sequence-level log-ratio(取 $y\sim\pi_\theta$ 期望才等于 $\beta\cdot$KLDPO 训练时 $y$ 来自 preference 数据所以不是 KL 本身,但 reference 出现在分母里仍带来隐式 anchoring);GRPO 用 k3 KL 进 loss(注意 k3-as-loss 的 gradient 是 first-order 近似,见 §3.6);SimPO 直接<strong>砍掉 reference</strong>,所以<strong>没有 KL 约束</strong>——对 β/γ/length-norm 更敏感。</li><li><strong>失败模式</strong>KL 爆炸(β 过小、importance ratio 过大)、KL collapse(β 过大或 entropy 太低,policy 卡死)、<strong>Reward Overoptimization</strong> (Gao 2023 ICML)proxy reward 随 KL 单调升,gold reward 先升后降(inverted-U),KL 距离是 overoptimization 的天然 axis。</li></ol>
<h2 id="1-kl-基础">§1 KL 基础</h2>
<h3 id="11-定义性质记号">1.1 定义、性质、记号</h3>
<p><strong>定义</strong>(离散):</p>
<p>$$\boxed{\;\text{KL}(p \| q) \triangleq \sum_x p(x) \log \frac{p(x)}{q(x)} = \mathbb{E}_{x \sim p}\!\left[\log \frac{p(x)}{q(x)}\right]\;}$$</p>
<p>约定 $0 \log 0 = 0$、$0 \log(0/0) = 0$、$p \log(p/0) = +\infty$。连续分布把 $\sum$ 换成 $\int$。</p>
<p><strong>核心性质</strong>(面试常被串问):</p>
<table><thead><tr><th>性质</th><th>一句话表述</th><th>简证</th></tr></thead><tbody><tr><td><strong>非负</strong></td><td>$\text{KL} \ge 0$</td><td>Jensen + $-\log$ 凸:$\text{KL} = -\mathbb{E}_p \log(q/p) \ge -\log \mathbb{E}_p(q/p) = 0$</td></tr><tr><td><strong>等号</strong></td><td>$\text{KL} = 0$ 当且仅当 $p = q$ a.e.</td><td>Jensen 等号条件</td></tr><tr><td><strong>不对称</strong></td><td>$\text{KL}(p,q) \ne \text{KL}(q,p)$(在 $\text{KL}$ 的不对称参数中)</td><td>直接构造例子可见</td></tr><tr><td><strong>不满足三角不等式</strong></td><td>不是 metric</td><td>故"KL distance"是不严谨的口语化</td></tr><tr><td><strong>凸性</strong></td><td>$\text{KL}(\cdot,\cdot)$ 对 $(p,q)$ 联合凸</td><td>log-sum 不等式</td></tr><tr><td><strong>链式法则</strong></td><td>联合 KL 等于边际 KL 加条件 KL 期望(见下方 display 公式)</td><td>直接拆 log</td></tr><tr><td><strong>参数化不变</strong></td><td>对 $x \mapsto T(x)$ 同形变换不变(仅在可逆 $T$ 下取等号)</td><td>测度变换 + Jacobian 抵消</td></tr></tbody></table>
<p>链式法则的完整形式:</p>
<p>$$\text{KL}(p(x,y) \,\|\, q(x,y)) = \text{KL}(p(x) \,\|\, q(x)) + \mathbb{E}_{p(x)}\!\big[\text{KL}(p(y|x) \,\|\, q(y|x))\big]$$</p>
<div class="callout callout-good"><div class="callout-title">链式法则在 RLHF 里 = per-token KL 加总</div><p>Sequence-level KL 是 trajectory log-ratio 之和的<strong>期望</strong>$\text{KL}_\text{seq} = \mathbb{E}_{y\sim\pi_\theta}[\sum_t \log\pi_\theta(y_t|s_t)/\pi_\text{ref}(y_t|s_t)]$。实际实现里对每条 rollout 做 $\sum_t \log r_t$ 是<strong>单条 MC estimator</strong>k1 的 sequence 形式);要得到 true expected KL 需对 batch 内 rollout 平均。<strong>真实的 token-level KL</strong> $D_\text{KL}(\pi_\theta(\cdot|s_t)\|\pi_\text{ref}(\cdot|s_t))$ 还需对该 prefix 上整个 vocab 求和(full-vocab KL),而非只在 sampled token 上算 log-ratio。这两者<strong>期望相等</strong>但 estimator 形式不同:sum-over-rollout 的 sampled log-ratio 是 cheap-but-noisy estimator。</p></div>
<h3 id="12-forward-kl-vs-reverse-klmass-covering-还是-mode-seeking">1.2 Forward KL vs Reverse KLmass-covering 还是 mode-seeking</h3>
<p>记 $p$ 是数据/真实分布,$q_\theta$ 是参数化模型。两种 KL 在拟合策略上行为完全不同:</p>
<table><thead><tr><th>方向</th><th>形式(见下方 display</th><th>期望对谁取</th><th>行为</th><th>经典用途</th></tr></thead><tbody><tr><td><strong>Forward KL</strong></td><td>$\text{KL}(p\,\</td><td>\,q_\theta) = \mathbb{E}<em>{p}[\log(p/q</em>\theta)]$</td><td>$p$(数据/目标)</td><td><strong>mass-covering / mean-seeking</strong>:哪里 $p > 0$$q_\theta$ 必须 &gt; 0,否则 $\log(p/q) \to \infty$</td><td>MLE / 蒸馏(学生覆盖老师)</td></tr><tr><td><strong>Reverse KL</strong></td><td>$\text{KL}(q_\theta\,\</td><td>\,p) = \mathbb{E}<em>{q</em>\theta}[\log(q_\theta/p)]$</td><td>$q_\theta$(变分/优化分布)</td><td><strong>mode-seeking / minorization</strong>:哪里 $q_\theta > 0$$p$ 必须 &gt; 0$q_\theta$ 倾向找单一 mode 缩进去</td><td>VI、RLHF、GAN-like 训练</td></tr></tbody></table>
<p>记号约定:</p>
<p>$$\text{Forward KL}: \text{KL}(p \,\|\, q_\theta) = \mathbb{E}_{p}\!\left[\log\frac{p}{q_\theta}\right],\qquad \text{Reverse KL}: \text{KL}(q_\theta \,\|\, p) = \mathbb{E}_{q_\theta}\!\left[\log\frac{q_\theta}{p}\right]$$</p>
<p>经典图(双峰 $p$,单峰 $q_\theta$):</p>
<ul><li>Forward KL 拟合 → $q_\theta$ 拉宽,跨越两个 mode<strong>mass-covering</strong>)。</li><li>Reverse KL 拟合 → $q_\theta$ 选其中一个 mode 缩进(<strong>mode-seeking</strong>)。</li></ul>
<div class="callout callout-warn"><div class="callout-title">命名约定的现代共识</div><p>变分推断、DPO、RLOO、"Rethinking KL Regularization in RLHF" (arXiv 2510.01555)、"A Comedy of Estimators" (arXiv 2512.21852) 等 2024-2026 RLHF 文献都用统一约定:$\text{KL}(q_\theta\|p)$ 叫 reverse KL$q_\theta$ 是变分/优化分布),$\text{KL}(p\|q_\theta)$ 叫 forward KL。本教程跟随这个标准约定。少数早期 RL 教材按采样分布命名,建议在面试时直接给出公式,避免标签歧义。</p></div>
<p><strong>RLHF 用哪一种?</strong> 几乎所有主流实现(InstructGPT / Anthropic PPO / DeepSeekMath GRPO)都用 $\text{KL}(\pi_\theta \| \pi_\text{ref})$<strong>reverse KL</strong> 形式:$\pi_\theta$ 是变分一侧,$\pi_\text{ref}$ 是 target)。<strong>根本原因</strong>:训练时我们已经从 $\pi_\theta$ 采样(rollout),算 $\mathbb{E}_{\pi_\theta}[\log \pi_\theta/\pi_\text{ref}]$ 直接用样本就行;同时 reverse KL 的 mode-seeking 行为正好符合 RL 目标——在 $\pi_\text{ref}$ 高密度区找 reward 高的 mode,而不是"覆盖整个 $\pi_\text{ref}$"。</p>
<div class="callout callout-info"><div class="callout-title">Tip</div><p>注意:把 $\pi_\theta$ 与 $\pi_\text{ref}$ 角色对调时(forward KL = $\text{KL}(\pi_\text{ref}\|\pi_\theta)$),要从 $\pi_\text{ref}$ 采样,工程上需要 IS、贵且语义不直接(我们要训的是 $\pi_\theta$ 不是 $\pi_\text{ref}$)。所以 RLHF 极少用 forward 方向。</p></div>
<h3 id="13-与其他-divergence-的关系">1.3 与其他 divergence 的关系</h3>
<table><thead><tr><th>Divergence</th><th>定义(见下方 display</th><th>特点</th><th>备注</th></tr></thead><tbody><tr><td><strong>JS</strong></td><td>KL 到混合 $m = (p+q)/2$ 的对称平均</td><td>对称、有界($\le \log 2$)、是 metric 的平方根</td><td>$\sqrt{\text{JS}}$ 是 metricEndres-Schindelin 2003 IEEE TIT 49(7));GAN 原版判别 loss 等价于 $2\cdot\text{JSD} - \log 4$RLHF 极少用</td></tr><tr><td><strong>α-divergence</strong></td><td>$\frac{1}{\alpha(1-\alpha)}(1 - \int p^\alpha q^{1-\alpha})$</td><td>含 KL 作为极限</td><td>统一框架,$\alpha \to 1$ 给 forward KL、$\alpha \to 0$ 给 reverse KL</td></tr><tr><td><strong>Hellinger</strong></td><td>$H^2(p,q) = \tfrac{1}{2}\int(\sqrt{p}-\sqrt{q})^2$</td><td>对称、有界、$0 \le H^2 \le 1$</td><td>与 KL 关系:$H^2 \le \tfrac{1}{2}\text{KL}$</td></tr><tr><td><strong>$\chi^2$</strong></td><td>$\chi^2(p,q) = \int \frac{(p-q)^2}{q}$</td><td>是 $f$-divergence 在 $f(t) = (t-1)^2$ 时的特例</td><td>与 KL 关系:$\text{KL} \le \log(1 + \chi^2)$</td></tr><tr><td><strong>TV</strong></td><td>$\tfrac{1}{2}\int \lvert p-q\rvert$</td><td>是 metric、$\in [0,1]$</td><td><strong>Pinsker</strong>$\text{TV} \le \sqrt{\text{KL}/2}$</td></tr></tbody></table>
<p>四个常见 $f$-divergence 的完整形式:</p>
<p>$$\text{JS}(p, q) = \tfrac{1}{2}\text{KL}(p \,\|\, m) + \tfrac{1}{2}\text{KL}(q \,\|\, m),\quad m = (p+q)/2$$</p>
<p>$$\chi^2(p, q) = \int \frac{(p(x) - q(x))^2}{q(x)}\,dx,\qquad \text{Pinsker: } \mathrm{TV}(p,q) \le \sqrt{\text{KL}(p \,\|\, q) / 2}$$</p>
<div class="callout callout-info"><div class="callout-title">为什么 RLHF 没用 JS / α-divergence</div><p>主要是工程惯性 + 闭式优势:在 PPO/DPO 框架里 KL 有干净的 per-token 拆分(链式法则)、闭式最优解(softmax-style),且 likelihood ratio 直接给出 KL token 增量,免去额外网络估计。JS / α-divergence 要么数学没这么干净,要么需要额外 density ratio estimator。</p></div>
<h3 id="14-为什么-rlhf-要加-kl">1.4 为什么 RLHF 要加 KL</h3>
<p>把"无 KL"和"有 KL"的目标摆一起:</p>
<p>$$\text{无 KL}:\quad \max_\pi \mathbb{E}_{x,\,y \sim \pi(\cdot|x)}[r(x,y)]$$</p>
<p>$$\text{有 KL}:\quad \max_\pi \mathbb{E}_{x,\,y \sim \pi(\cdot|x)}[r(x,y)] - \beta\,\mathbb{E}_x\,\text{KL}\!\big(\pi(\cdot|x)\,\big\|\,\pi_\text{ref}(\cdot|x)\big)$$</p>
<p><strong>没有 KL 会发生什么?</strong></p>
<ol><li><strong>Reward hacking</strong>:policy 找到 RM 盲点(更长答案 / "As an AI..." 套话 / 谄媚 / 格式 hack)拿高 RM 分,人感受变差。</li><li><strong>语言流畅性塌掉</strong>policy 会输出 RM "喜欢"但人类看着像鬼话的 token 序列(极端时退化到只重复某 token / 完全不语法)。</li><li><strong>Distribution shift</strong>policy 跑远了 $\pi_\text{ref}$,连 RM 自己都很难评分(off-distributionRM 越没把握、reward 越随机)。</li></ol>
<p>加 KL 后:</p>
<ul><li><strong>β 提供 RM error 的 implicit regularization</strong>:当 RM 不可靠时,KL 把 policy 拉回 SFT 已知良好分布。</li><li><strong>闭式最优 policy 存在</strong>(§6.1 推导),整个 RLHF 有数学基础。</li><li><strong>DPO / KTO / GRPO 都依赖这条 KL anchor</strong>:去掉 reference 的 SimPO 实测对超参更敏感。</li></ul>
<h2 id="2-kl-estimatorsk1--k2--k3面试核心">§2 KL Estimatorsk1 / k2 / k3):面试核心</h2>
<h3 id="21-问题设置">2.1 问题设置</h3>
<p>实际训练里我们要在每一个 mini-batch 估计 $\text{KL}(\pi_\theta \| \pi_\text{ref})$。但完整求和 $\sum_y \pi_\theta(y) \log \pi_\theta(y)/\pi_\text{ref}(y)$ 不可行($y$ 是整段 response,组合爆炸)。<strong>只能 Monte Carlo</strong>:用从 $\pi_\theta$ 采样的样本估 KL。</p>
<p>记 $\log r = \log(\pi_\theta(y)/\pi_\text{ref}(y))$(不是 importance ratio,是策略 log-ratio)。我们有 $y \sim \pi_\theta$ 的样本,想估 $\mathbb{E}_{\pi_\theta}[\log r] = \text{KL}(\pi_\theta \| \pi_\text{ref})$。</p>
<div class="callout callout-warn"><div class="callout-title">记号统一</div><p>本节 $\log r$ 始终表示 <strong>policy log-ratio</strong> $\log \pi_\theta - \log \pi_\text{ref}$<strong>不是</strong> PPO importance ratio $\pi_\theta / \pi_\text{old}$)。两者形式相近但含义不同:前者衡量"离 reference 多远",后者衡量"离 sampling policy 多远"。</p></div>
<h3 id="22-k1-estimator--直接代入定义">2.2 k1 estimator —— "直接代入定义"</h3>
<p>$$\boxed{\;\widehat{\text{KL}}_1 = \log\frac{\pi_\theta(y)}{\pi_\text{ref}(y)} = \log r\;}$$</p>
<ul><li><strong>无偏</strong>$\mathbb{E}_{y\sim\pi_\theta}[\log r] = \text{KL}(\pi_\theta\|\pi_\text{ref})$ by definition。</li><li><strong>可负</strong>:单个样本下 $\log r$ 可正可负(log-ratio 没有"非负"约束)。</li><li><strong>方差大</strong>tails 上 $\log r$ 可以非常大或非常小,特别是 $\pi_\theta$ 和 $\pi_\text{ref}$ 不重叠的区域。</li></ul>
<p><strong>问题</strong>:用 k1 作为"KL 监控指标"会看到<strong>负值</strong>,工程上会让 logger 显示负 KL,新人会困惑(KL 不该非负吗?)。这是因为<strong>期望非负不代表每个样本非负</strong>。但作为 reward shaping 的 per-token KL,可以接受(关键是均值无偏)。</p>
<h3 id="23-k2-estimator--l2-form">2.3 k2 estimator —— "$L^2$ form"</h3>
<p>$$\boxed{\;\widehat{\text{KL}}_2 = \tfrac{1}{2}\!\left(\log\frac{\pi_\theta(y)}{\pi_\text{ref}(y)}\right)^2 = \tfrac{1}{2}(\log r)^2\;}$$</p>
<ul><li><strong>总是非负</strong></li><li><strong>有偏</strong>$\mathbb{E}[\tfrac{1}{2}(\log r)^2] \ne \text{KL}$。</li><li><strong>小 KL 极限下</strong>Taylor 展开 $\log r = (r - 1) - \tfrac{1}{2}(r-1)^2 + O((r-1)^3)$,当 $\pi_\theta \approx \pi_\text{ref}$ 时 $\log r$ 小,$\tfrac{1}{2}(\log r)^2$ 与 KL 在二阶近似下相等(KL 在 $p=q$ 附近 = Fisher 信息度规的二次型)。</li><li><strong>方差小于 k1</strong>:因为平方后正负不再相消,但仍然不是最优。</li></ul>
<p>实践中 k2 主要用于<strong>监控</strong>(提供"non-negative,但有偏"的视觉化指标);很少用于 reward shaping。</p>
<h3 id="24-k3-estimator-schulman-2020-blog--非负无偏-value-estimator但作为-loss-项是-biased-gradient见-36">2.4 k3 estimator (Schulman 2020 blog) —— <strong>非负无偏 value estimator</strong>(但作为 loss 项是 biased gradient,见 §3.6</h3>
<h4 id="241-构造">2.4.1 构造</h4>
<p>考虑函数 $f(x) = e^x - x - 1$。由 $e^x \ge 1 + x$(实数 $x$)得 $f(x) \ge 0$,且 $f(0) = 0$。</p>
<p>把 $x = \log(\pi_\text{ref}(y)/\pi_\theta(y)) = -\log r$ 代入:</p>
<p>$$f(-\log r) = e^{-\log r} - (-\log r) - 1 = \frac{1}{r} + \log r - 1 = \frac{\pi_\text{ref}(y)}{\pi_\theta(y)} + \log\frac{\pi_\theta(y)}{\pi_\text{ref}(y)} - 1$$</p>
<p>等价地(用 $\Delta = -\log r = \log(\pi_\text{ref}/\pi_\theta)$ 写):$\frac{\pi_\text{ref}}{\pi_\theta} - \log\frac{\pi_\text{ref}}{\pi_\theta} - 1$(注意 $-\log(\pi_\text{ref}/\pi_\theta) = \log(\pi_\theta/\pi_\text{ref})$,两形式等价)。</p>
<p>等价地(这是 Schulman blog 中的标准写法):</p>
<p>$$\boxed{\;\widehat{\text{KL}}_3 = \frac{\pi_\text{ref}(y)}{\pi_\theta(y)} - \log\frac{\pi_\text{ref}(y)}{\pi_\theta(y)} - 1 = e^{\Delta} - \Delta - 1,\quad \Delta = \log\frac{\pi_\text{ref}(y)}{\pi_\theta(y)} = -\log r\;}$$</p>
<h4 id="242-三大性质必考">2.4.2 三大性质(必考)</h4>
<p><strong>性质 1(非负)</strong></p>
<p>由 $e^\Delta - \Delta - 1 \ge 0$ 对所有 $\Delta \in \mathbb{R}$(凸函数 $e^\Delta$ 在 $\Delta = 0$ 切线 $1 + \Delta$ 之上),$\widehat{\text{KL}}_3 \ge 0$ 总是成立。</p>
<p><strong>性质 2(无偏)</strong></p>
<p>要证 $\mathbb{E}_{y \sim \pi_\theta}[\widehat{\text{KL}}_3] = \text{KL}(\pi_\theta\|\pi_\text{ref})$。</p>
<p>$$\mathbb{E}_{\pi_\theta}\!\left[\frac{\pi_\text{ref}}{\pi_\theta}\right] = \sum_y \pi_\theta(y) \cdot \frac{\pi_\text{ref}(y)}{\pi_\theta(y)} = \sum_y \pi_\text{ref}(y) = 1$$</p>
<p>$$\mathbb{E}_{\pi_\theta}\!\left[-\log\frac{\pi_\text{ref}}{\pi_\theta}\right] = \mathbb{E}_{\pi_\theta}\!\left[\log\frac{\pi_\theta}{\pi_\text{ref}}\right] = \text{KL}(\pi_\theta\|\pi_\text{ref})$$</p>
<p>所以:</p>
<p>$$\mathbb{E}_{\pi_\theta}[\widehat{\text{KL}}_3] = 1 + \text{KL}(\pi_\theta\|\pi_\text{ref}) - 1 = \text{KL}(\pi_\theta\|\pi_\text{ref}) \quad \checkmark$$</p>
<p><strong>性质 3(方差通常小于 k1</strong></p>
<p>直观:$\widehat{\text{KL}}_3$ 把 $\log r$ 的线性项($-\log r/\pi_\theta$ 部分,即 k1 的等价形式 $\mathbb{E}_{\pi_\theta}[-\log(\pi_\text{ref}/\pi_\theta)]$)和一个<strong>期望为 1 的控制变量</strong> $\pi_\text{ref}/\pi_\theta - 1$ 相加。控制变量降方差(control variate):当 $r$ 大时 $\log r$ 大但 $1/r$ 小,反之亦然,<strong>两者负相关</strong>,加起来方差比单独 k1 小。</p>
<p>形式化:$\widehat{\text{KL}}_3 = \widehat{\text{KL}}_1 + (\frac{\pi_\text{ref}}{\pi_\theta} - 1)$,加项 $(\frac{\pi_\text{ref}}{\pi_\theta} - 1)$ 期望为 0,但与 $\log r$ 强负相关 → 减方差。</p>
<div class="callout callout-info"><div class="callout-title">k3 的 elegance</div><p>Schulman blog 2020 给出的 derivation 等价于上面:他<strong>先找一个 $f(x) \ge 0$ 且 $\mathbb{E}_q f(\log p/q) = \text{KL}$ 的函数</strong>,然后挑 $f(x) = e^x - x - 1$(最简单的非负、可微、不是 trivial 的选择)。所以 k3 不是"灵感来的"——它是"非负 + 无偏"约束下的最自然构造。</p></div>
<h4 id="243-变种与简化">2.4.3 变种与简化</h4>
<p>实际代码经常写成(<strong>对 PPO ratio $r = \pi_\theta / \pi_\text{old}$ 同样适用</strong>,但语义不同——这是 importance ratio approx,不是 policy log-ratio):</p>
<pre><code class="language-python">approx_kl_to_old = ((ratio - 1) - torch.log(ratio.clamp_min(1e-8))).mean()</code></pre>
<p>即 $\widehat{\text{KL}}_3 \approx (r - 1) - \log r$,是上面 $e^\Delta - \Delta - 1$ 的等价对偶(把 $r = e^{\log r}$ 视作 $e^\Delta$ 即可,符号约定换一下)。<strong>TRL / OpenRLHF / verl 默认 <code>approx_kl</code> 都是这个</strong></p>
<h3 id="25-三者对比表">2.5 三者对比表</h3>
<table><thead><tr><th>Estimator</th><th>形式</th><th>无偏?</th><th>非负?</th><th>方差</th><th>在 RLHF 里典型用途</th></tr></thead><tbody><tr><td><strong>k1</strong></td><td>$\log r$</td><td></td><td></td><td></td><td>InstructGPT PPO reward shapingper-token KL</td></tr><tr><td><strong>k2</strong></td><td>$\tfrac{1}{2}(\log r)^2$</td><td>❌ value-estimator 有偏(二阶近似 KL</td><td></td><td></td><td>value 视角常用作监控;<strong>loss-gradient 视角是 principled k2-as-loss</strong>——on-policy 下与 k1-in-reward gradient-equivalent,见 §3.6</td></tr><tr><td><strong>k3</strong></td><td>$e^{-\log r} + \log r - 1$</td><td>✅(作为 <strong>value estimator</strong></td><td></td><td></td><td>DeepSeekMath GRPO / DAPO 历史用法(作为 <strong>loss</strong> 时其梯度是 biased first-order approx,见 §3.6 + Rethinking KL 论文)</td></tr></tbody></table>
<h3 id="26-代码三估计器--variance-对比-simulation">2.6 代码:三估计器 + variance 对比 simulation</h3>
<pre><code class="language-python">import torch
import torch.nn.functional as F
def k1_estimator(logp_theta, logp_ref):
&quot;&quot;&quot;k1: log(π_θ / π_ref) — unbiased, but can be negative, high variance.&quot;&quot;&quot;
return logp_theta - logp_ref # [B, T]
def k2_estimator(logp_theta, logp_ref):
&quot;&quot;&quot;k2: 0.5 (log(π_θ / π_ref))^2 — biased, non-negative, mid variance.&quot;&quot;&quot;
return 0.5 * (logp_theta - logp_ref) ** 2
def k3_estimator(logp_theta, logp_ref):
&quot;&quot;&quot;k3 (Schulman 2020): exp(log π_ref - log π_θ) + log(π_θ/π_ref) - 1
= (π_ref/π_θ) - log(π_ref/π_θ) - 1 [letting Δ = log π_ref - log π_θ]
Value-estimator properties: unbiased, non-negative, low variance.
⚠️ Recommended for KL value MONITORING, NOT as a loss term — k3-as-loss
gives gradient (1 - e^{-Δ})∇logπ_θ = (Δ - ½Δ² + O(Δ³))∇logπ_θ, a
first-order Taylor approximation of reverse-KL gradient with O(Δ²) bias.
For principled reverse-KL gradient, use k2-as-loss (gradient-equivalent
to k1-in-reward on-policy) or k1-in-reward via score function. See §3.6.
&quot;&quot;&quot;
log_r = logp_theta - logp_ref # log(π_θ/π_ref)
log_ratio_rev = -log_r # Δ = log(π_ref/π_θ)
return torch.exp(log_ratio_rev) - log_ratio_rev - 1
# Variance comparison: 1D synthetic
def compare_kl_estimators(n_samples=10_000, seed=0):
&quot;&quot;&quot;
Synthetic: π_θ = N(0, 1), π_ref = N(μ, 1). True KL = μ^2 / 2.
Sample y ~ π_θ; evaluate the three estimators.
&quot;&quot;&quot;
torch.manual_seed(seed)
mu = 0.5
true_kl = mu ** 2 / 2.0 # closed-form for Gaussians w/ same σ
y = torch.randn(n_samples) # y ~ N(0, 1) = π_θ
# log-pdf of N(0,1) vs N(μ,1) at y (drop common -0.5 log 2π):
logp_theta = -0.5 * y ** 2
logp_ref = -0.5 * (y - mu) ** 2
k1 = k1_estimator(logp_theta, logp_ref)
k2 = k2_estimator(logp_theta, logp_ref)
k3 = k3_estimator(logp_theta, logp_ref)
print(f&quot;true KL = {true_kl:.4f}&quot;)
for name, vals in [(&quot;k1&quot;, k1), (&quot;k2&quot;, k2), (&quot;k3&quot;, k3)]:
print(f&quot; {name}: mean={vals.mean().item():+.4f} var={vals.var().item():.4f} &quot;
f&quot;min={vals.min().item():+.3f} max={vals.max().item():+.3f}&quot;)
# Expected output: k1 mean ≈ 0.125 (unbiased), but min &lt; 0;
# k2 mean &gt; 0.125 (biased upward);
# k3 mean ≈ 0.125 (unbiased), min ≥ 0, var(k3) &lt; var(k1).</code></pre>
<div class="callout callout-good"><div class="callout-title">运行 simulation 你会看到</div></div>
<ul><li>k1 mean ≈ 0.125, min 约 1.5(可负),var 大。</li><li>k2 mean ≈ 0.18(偏高),min ≥ 0var 中。</li><li>k3 mean ≈ 0.125(无偏),min ≥ 0var <strong>明显小于</strong> k1。</li></ul>
<p>这正是 Schulman blog 给出的 takeaway<strong>k3 同时拿到 unbiased + non-negative + 较低方差</strong></p>
<h2 id="3-kl-在-rlhf-中的两种放置">§3 KL 在 RLHF 中的两种放置</h2>
<h3 id="31-option-ain-reward-shapingppo-rlhf--instructgpt-标准做法">3.1 Option AIn-reward shapingPPO RLHF / InstructGPT 标准做法)</h3>
<p>把 KL <strong>塞进 per-token reward</strong>,再正常跑 PPO + GAE</p>
<p>$$\boxed{\;\tilde{r}_t = \underbrace{\mathbb{1}[t = T] \cdot R(x, y)}_{\text{terminal RM reward}} - \beta \cdot \underbrace{\log\frac{\pi_\theta(y_t \mid x, y_{<t})}{\pi_\text{ref}(y_t \mid x, y_{<t})}}_{\text{per-token KL (k1)}}\;}$$</p>
<p>注意细节:</p>
<ul><li><strong>per-token</strong>:每生成一个 token,就计算这个 token 的 log-prob ratio,作为该步 reward 的一部分。</li><li><strong>k1 estimator</strong>:这里直接用 $\log(\pi_\theta/\pi_\text{ref})$k1)。注意它<strong>单 token 可为负</strong>,但作为 reward shaping 只要均值/总和符合 KL 期望即可。</li><li><strong>terminal RM reward</strong>:RM 给整段答案的 scalar,只放在最后一个 token 上(其余 token RM reward = 0)。</li></ul>
<p>放完后跑 GAE</p>
<p>$$\delta_t = \tilde{r}_t + \gamma V(s_{t+1}) - V(s_t),\quad A_t^{\text{GAE}} = \sum_{l \ge 0} (\gamma\lambda)^l \delta_{t+l}$$</p>
<p>KL penalty 通过 advantage 自然 propagate 到 policy gradient<strong>每步 token 的"动作概率提升"被 KL "拉回 reference" 抵消</strong>,最终 RL 目标 = expected $R$ $\beta$ · KL。</p>
<h3 id="32-option-bin-loss-regularizationgrpo--dapo-做法">3.2 Option BIn-loss regularizationGRPO / DAPO 做法)</h3>
<p>把 KL <strong>不放 reward</strong>,作为单独 loss 项:</p>
<p>$$\boxed{\;\mathcal{L}_\text{full}(\theta) = -\underbrace{\mathbb{E}\!\left[\min(\rho_t A_t, \text{clip}(\rho_t, 1\!-\!\epsilon, 1\!+\!\epsilon) A_t)\right]}_{\text{PPO surrogate / GRPO surrogate}} + \beta \cdot \underbrace{\mathbb{E}\!\left[\widehat{\text{KL}}_\text{loss}(\pi_\theta \| \pi_\text{ref})\right]}_{\text{KL loss term}}\;}$$</p>
<p>GRPO 的<strong>历史实现</strong>DeepSeekMath / DAPO)把 $\widehat{\text{KL}}_\text{loss}$ 取作 <strong>k3</strong>per-token):</p>
<ul><li>用 k3 estimatorper-token)。</li><li>KL <strong>不进 advantage 计算</strong>;直接作为正则项加到 loss 上。</li><li>Advantage 由组内 reward 归一化得到($\hat{A}_i = (r_i - \bar{r})/\sigma_r$),所有 token 共享。</li></ul>
<div class="callout callout-warn"><div class="callout-title">重要 caveat</div><p>把 k3 直接当 loss 反传<strong>不是</strong>精确的 reverse-KL gradient——它是一个 biased first-order approximation(详见 §3.6 + 2025 "Rethinking KL Regularization in RLHF" 论文)。on-policy 下更 principled 的两种选择是:(1) <strong>k1 in reward</strong>KL 进 rewardPPO/GRPO 通过 score-function 反传,gradient 严格无偏);(2) <strong>k2 as loss</strong>$\tfrac12 (\log r)^2$$\nabla\mathcal L = \Delta\,\nabla\log\pi_\theta$on-policy 下与 (1) <strong>gradient-equivalent</strong>,都是严格 reverse-KL gradient)。off-policy 还需 IS correction。下方 §3.6 给出对比表。</p></div>
<h3 id="33-两者数学上等价工程上不等价">3.3 两者数学上等价?工程上不等价</h3>
<p><strong>数学</strong>:两种放法本质都是优化同一个目标:</p>
<p>$$J(\pi) = \mathbb{E}_{\pi}[R] - \beta \cdot \text{KL}(\pi \| \pi_\text{ref})$$</p>
<p>只是<strong>梯度 propagate 路径不同</strong></p>
<ul><li>Option AKL 作为 reward 一部分 → 经 GAE → 进入 advantage → 进入 PPO surrogate 梯度。</li><li>Option BKL 作为独立 loss → 直接对 $\theta$ 求梯度。</li></ul>
<p><strong>工程差异</strong></p>
<table><thead><tr><th>维度</th><th>In-reward (Option A)</th><th>In-loss (Option B)</th></tr></thead><tbody><tr><td>KL 估计器</td><td>k1(单 token 可负,作为 reward 接受)</td><td>k3(无偏 + 非负,更稳)</td></tr><tr><td>与 PPO clip 的关系</td><td>KL 被 clip 截断(importance ratio 截断把 KL 一并截了)</td><td>KL 独立,不被 clip 影响</td></tr><tr><td>Advantage 解释</td><td>advantage 内含 KL → "净 advantage"</td><td>advantage 仅 reward-based → "纯 advantage"</td></tr><tr><td>调参敏感度</td><td>β 直接影响 reward scale → 需要和 RM scale 协调</td><td>β 与 reward 独立,但 KL 与 PG 比重要平衡</td></tr><tr><td>监控指标</td><td>看 token-level KL 进了 reward</td><td>看 KL loss 独立曲线</td></tr></tbody></table>
<div class="callout callout-warn"><div class="callout-title">PPO clip 抹掉 KL 信号的细节</div><p>在 Option A 中,当 importance ratio $\rho_t$ 落在 clip 之外($\rho_t > 1+\epsilon$ 且 $\tilde A_t > 0$ 或 $\rho_t < 1-\epsilon$ $\tilde A_t < 0$),PPO surrogate 截断为常数 θ 梯度为 0),此时该 step $\tilde r_t$ 里的 KL 项也一并失效这意味着<strong>当 policy 偏离过大时,PPO clip 反而让 KL anchor 失效</strong>——这是 Option B 把 KL 放 loss 的部分动机(KL 永远生效)。</p></div>
<h3 id="34-实操哪一种用在哪">3.4 实操:哪一种用在哪?</h3>
<table><thead><tr><th>算法</th><th>KL 放置</th><th>估计器</th><th>来源</th></tr></thead><tbody><tr><td>InstructGPT PPO</td><td><strong>In-reward</strong></td><td>k1</td><td>Ouyang 2022 NeurIPS</td></tr><tr><td>Anthropic RLHF</td><td><strong>In-reward</strong></td><td>k1 + adaptive β</td><td>Bai 2022 arXiv 2204.05862</td></tr><tr><td>GRPO / DeepSeekMath</td><td><strong>In-loss</strong></td><td>k3</td><td>Shao 2024 arXiv 2402.03300</td></tr><tr><td>DAPO</td><td><strong>In-loss</strong>(实际配置中 KL 项常被关掉或权重很低)</td><td>k3</td><td>Yu 2025 arXiv 2503.14476</td></tr><tr><td>DPO</td><td><strong>隐式 in-loss</strong>(通过 $\pi_\text{ref}$ 在 log-ratio 分母)</td><td></td><td>Rafailov 2023 NeurIPS</td></tr><tr><td>SimPO</td><td><strong>去掉 reference, 无 KL</strong></td><td></td><td>Meng 2024 NeurIPS</td></tr></tbody></table>
<div class="callout callout-info"><div class="callout-title">DAPO 实战经验</div><p>字节 verl 团队的工程报告里多次提到,KL 项在大规模数学/代码 RL 训练中<strong>经常关掉或设很小</strong> β($10^{-4}$ 量级),原因:reward 已经是 rule-based(接近 ground truth),不存在 RM hackingKL anchor 反而拖训练。这是"Option B + β ≈ 0"的极端版本。</p></div>
<h3 id="36-estimator-placement-的-gradient-bias-分析rethinking-kl-regularization-in-rlhf">3.6 Estimator placement 的 gradient bias 分析(Rethinking KL Regularization in RLHF</h3>
<div class="callout callout-info"><div class="callout-title">关键参考</div><p>Kezhao Liu et al., "Rethinking KL Regularization in RLHF: From Value Estimation to Gradient Optimization", arXiv 2510.01555 (2025-10-02)。这篇文章系统区分 <strong>value estimation</strong>"KL 量本身估得准不准")与 <strong>gradient optimization</strong>("对 θ 求导后是不是真的 reverse-KL gradient"),结论与历史 GRPO 实现不完全一致。</p></div>
<h4 id="设定与三种-estimator-placement">设定与三种 estimator placement</h4>
<p>为简洁起见,令 $\Delta_t = \log\!\frac{\pi_\theta(y_t|s_t)}{\pi_\text{ref}(y_t|s_t)}$per-token log-ratio<strong>带 θ 梯度</strong>),$\hat\Delta_t = \text{stop\_grad}(\Delta_t)$(在 rollout 时记录的 detached 副本)。三种常见 placement</p>
<table><thead><tr><th>方案</th><th>KL 出现的位置</th><th>单 token 形式</th><th>对 θ 的梯度贡献</th></tr></thead><tbody><tr><td><strong>(P1) k1 in reward</strong></td><td>进 reward / advantage</td><td>$\hat r_t \leftarrow r_t - \beta\,\hat\Delta_t$,再走 PPO surrogate</td><td>$-\beta\cdot \mathbb{E}[\nabla_\theta\log\pi_\theta\cdot \hat\Delta_t]$<strong>严格的 reverse-KL score-function gradient</strong>on-policy</td></tr><tr><td><strong>(P2) k2 as loss</strong></td><td>直接 loss 项</td><td>$\mathcal{L}_\text{KL} = \tfrac12 \Delta_t^2$</td><td>$\nabla\mathcal{L}_\text{KL} = \Delta_t\,\nabla_\theta\log\pi_\theta$(用 $\nabla_\theta\Delta_t = \nabla_\theta\log\pi_\theta$)。on-policy 下 $\mathbb{E}_{y\sim\pi_\theta}[\Delta\,\nabla\log\pi_\theta] = \nabla\text{KL}$,与 (P1) <strong>gradient-equivalent</strong>——严格 principled</td></tr><tr><td><strong>(P3) k3 as loss</strong></td><td>直接 loss 项</td><td>$\mathcal{L}_\text{KL} = e^{-\Delta_t} + \Delta_t - 1$</td><td>$\nabla\mathcal{L}_\text{KL} = (1 - e^{-\Delta_t})\nabla_\theta\log\pi_\theta$;这是 reverse-KL gradient 的 <strong>first-order Taylor approximation</strong>$1-e^{-\Delta} = \Delta - \tfrac12\Delta^2 + O(\Delta^3)$,有 $O(\Delta^2)$ bias</td></tr></tbody></table>
<h4 id="为什么-k3-as-loss-是-biased-gradient关键直觉">为什么 k3 as loss 是 biased gradient(关键直觉)</h4>
<p>k3 作为 <strong>value estimator</strong>(计算 KL 的数值)是无偏的:$\mathbb{E}_{\pi_\theta}[\widehat{\text{KL}}_3] = \text{KL}(\pi_\theta\|\pi_\text{ref})$(见 §2.4.2 性质 2)。但当 <strong>对 θ 反传</strong>时,autograd 计算的是 $\nabla_\theta\widehat{\text{KL}}_3$,而<strong>不是</strong> $\nabla_\theta\,\mathbb{E}_{\pi_\theta}[\widehat{\text{KL}}_3]$。后者由 score-function trick 给出:</p>
<p>$$\nabla_\theta\,\text{KL}(\pi_\theta\|\pi_\text{ref}) = \mathbb{E}_{y\sim\pi_\theta}\!\big[\nabla_\theta\log\pi_\theta(y) \cdot \log(\pi_\theta(y)/\pi_\text{ref}(y))\big] \;+\; \mathbb{E}_{\pi_\theta}[\nabla_\theta\log\pi_\theta]\,\quad\text{(=0)}$$</p>
<p>= $\mathbb{E}[\nabla\log\pi_\theta \cdot \Delta]$<strong>这是 (P1) 给的 gradient</strong>,等价于把 $\Delta$ 当 detached reward 走 score function)。</p>
<p>而 (P3) <code>loss.backward()</code> 给的是 $\nabla_\theta(e^{-\Delta} + \Delta - 1) = (1 - e^{-\Delta})\nabla_\theta\Delta = (1 - 1/r)\nabla_\theta\log\pi_\theta$。Taylor 展开:$1 - 1/r = \Delta - \tfrac12\Delta^2 + O(\Delta^3)$。所以 (P3) ≈ (P1) 只在 $\Delta\to 0$ 邻域成立;远离 0 时有 $O(\Delta^2)$ bias。</p>
<h4 id="实践规则结合-rethinking-kl--comedy-of-estimators">实践规则(结合 Rethinking KL + Comedy of Estimators</h4>
<table><thead><tr><th>场景</th><th>推荐 placement</th><th>备注</th></tr></thead><tbody><tr><td><strong>on-policyrollout 当步反传,无 PPO mini-batch 多步 update</strong></td><td><strong>(P1) k1 in reward</strong><strong>(P2) k2 as loss</strong></td><td>两者在 on-policy 下 <strong>gradient-equivalent</strong>,都是严格 reverse-KL gradient</td></tr><tr><td><strong>off-policyPPO mini-batch 多次走 same data</strong></td><td>(P1) k1 in reward + <strong>IS correction</strong>$\rho\cdot\Delta$$\rho = \pi_\theta^\text{new}/\pi_\theta^\text{old}$</td><td>否则 reward 与当前 policy mismatch</td></tr><tr><td><strong>历史 GRPO/DeepSeekMath/DAPO 实现</strong></td><td>(P3) k3 as loss</td><td>有 $O(\Delta^2)$ gradient bias,实际工程里 $\Delta$ 很小(β 锚得紧),所以仍能跑;但<strong>不是理论 principled</strong></td></tr><tr><td><strong>value-side monitoring</strong>(看 KL 数值多大)</td><td>k3 estimator 仍是首选</td><td>无偏、非负、低方差——这就是 §2.4 那三大性质</td></tr></tbody></table>
<div class="callout callout-info"><div class="callout-title">Tip</div><p><strong>总结口径</strong>(面试推荐说法):k3 是<strong>优秀的 KL value estimator</strong>unbiased + non-negative + low variance);但作为 loss 反传的 gradient 是 reverse-KL gradient 的 first-order Taylor approximation,有 bias。Rethinking KL 推荐 on-policy 用 (P1) 或 (P2)DAPO/GRPO 历史用 (P3) 主要是工程惯例 + 在小 β 区间近似成立。</p></div>
<h2 id="4--调度">§4 β 调度</h2>
<h3 id="41-固定---baseline">4.1 固定 β —— baseline</h3>
<p>最常见。$\beta \in [0.01, 0.5]$<strong>InstructGPT 报告中 β = 0.02 是参考值</strong>per-token KL)。优点:简单可重现。缺点:训练中 KL 通常先小后大,固定 β 后期可能"压不住"或"过度压制"。</p>
<h3 id="42-adaptive---schulman-ppo-penalty-原版">4.2 Adaptive β —— Schulman PPO-Penalty 原版</h3>
<p>PPO 论文(Schulman 2017 arXiv 1707.06347)原本提了两个版本:<strong>Clip</strong>(现在主流)和 <strong>Penalty</strong>adaptive KL)。Penalty 形式:</p>
<p>$$\mathcal{L} = \mathbb{E}[r_t A_t] - \beta_k \cdot \text{KL}(\pi_{\theta_\text{old}} \| \pi_\theta)$$</p>
<p><strong>β 自适应规则</strong>(每 epoch 之后看 measured KL $d$):</p>
<ul><li>若 $d < d_\text{target} / 1.5$$\beta \leftarrow \beta / 2$KL 比目标低放松</li><li>若 $d > d_\text{target} \times 1.5$$\beta \leftarrow \beta \times 2$KL 比目标高,加压)</li><li>否则 β 不变</li></ul>
<p>直觉:把 β 当 PID controller 的 P termtarget 是预期 KL(比如 $d_\text{target} = 0.01$)。这条思路在 InstructGPT 和后续 Anthropic 工作里也出现过(Anthropic 论文 1707.06347 之后的 helpfulness/harmlessness 报告里有类似 adaptive β 描述)。</p>
<h3 id="43--annealing-schedule--类似-learning-rate-schedule">4.3 β annealing schedule —— 类似 learning rate schedule</h3>
<p>把 β 看作时间函数 $\beta(t)$</p>
<ul><li><strong>早期紧后期松</strong>$\beta(t) = \beta_0 \cdot \exp(-t / \tau)$。直觉:训练初期 policy 离 ref 近,加强 anchor 防 instability;后期 policy 学到了,放松让它 explore reward。</li><li><strong>早期松后期紧</strong>:相反方向,初期 explore RM 信号,后期 anchor。少见。</li><li><strong>Cosine / linear decay</strong>:参考 lr schedule。</li></ul>
<p>在 RLHF 工程实践中 annealing 用得不多——adaptive β 比 schedule 更鲁棒(不需调 schedule shape)。</p>
<h3 id="44--失败模式">4.4 β 失败模式</h3>
<table><thead><tr><th>β 设置</th><th>现象</th><th>诊断</th></tr></thead><tbody><tr><td><strong>β 太大</strong> ($> 1$)</td><td>KL ≈ 0policy 卡在 ref 附近,RM reward 不涨</td><td>看 reward curve 是平的 / <code>chosen_logp - rejected_logp</code> 不分离</td></tr><tr><td><strong>β 太小</strong> ($< 0.001$)</td><td>KL 爆炸(runaway),policy 越来越长 / 谄媚 / 重复</td><td>看 KL 曲线持续上升、generation length 上升、人工评测下降</td></tr><tr><td><strong>β 突变</strong></td><td>训练 loss 跳跃</td><td>adaptive 频率太高 / target_kl 太严</td></tr></tbody></table>
<div class="callout callout-warn"><div class="callout-title">InstructGPT 论文 β = 0.02 真的合适吗?</div><p>答案因任务而异。<strong>Math/code RL</strong> 通常需要更小 β(DeepSeekMath 报告 β ≈ 0.04DAPO 的 β 经常更小或为 0),因为 reward 接近 ground truth。<strong>Helpfulness/safety RL</strong> 需要更大 β(≥ 0.1)防 reward hacking,因为 neural RM 容易被 hack。这是为什么"β 不是 universal hyperparameter"。</p></div>
<h3 id="45-adaptive--代码示例">4.5 Adaptive β 代码示例</h3>
<pre><code class="language-python">class AdaptiveKLController:
&quot;&quot;&quot;
Schulman 2017 PPO-Penalty style adaptive β controller.
每个 PPO epoch 后调用 update(measured_kl)。
&quot;&quot;&quot;
def __init__(self, beta_init=0.02, target_kl=0.01, horizon=10000):
self.beta = beta_init
self.target_kl = target_kl
self.horizon = horizon # 平滑系数 (越大越缓)
def update(self, measured_kl, n_steps):
# proportional update; clip to prevent extreme jumps
proportional_error = max(-0.2, min(0.2,
measured_kl / self.target_kl - 1.0))
mult = 1.0 + proportional_error * n_steps / self.horizon
self.beta *= mult
# safety clamp
self.beta = max(1e-4, min(1.0, self.beta))
return self.beta</code></pre>
<p>用法:</p>
<pre><code class="language-python">kl_ctrl = AdaptiveKLController(beta_init=0.02, target_kl=0.01)
for epoch in range(num_epochs):
# ... rollout and PPO update ...
measured_kl = compute_mean_kl(policy, ref_policy, batch) # k3 推荐
kl_ctrl.update(measured_kl, n_steps=batch_size)
current_beta = kl_ctrl.beta</code></pre>
<div class="callout callout-info"><div class="callout-title">adaptive β 与 PID controller 的类比</div><p>上面只有 P 项(proportional);HuggingFace TRL 里的实现也只用 P。完全可以加 I(integral:累计误差)和 Dderivative:变化率)做 PID,但实测 P 已经够了,加 D 反而容易在 noisy KL 估计下振荡。</p></div>
<h2 id="5-kl-与-dpo--grpo--simpo--kto--ipo-的关系">§5 KL 与 DPO / GRPO / SimPO / KTO / IPO 的关系</h2>
<h3 id="51-dpoimplicit-reward----sequence-log-density-ratio">5.1 DPOimplicit reward = β × sequence log-density ratio</h3>
<p>DPO 的 implicit reward 是 $\hat{r}_\theta(x, y) = \beta \log(\pi_\theta(y|x) / \pi_\text{ref}(y|x))$,即整段 $y$ 的 sequence-level log-density ratio</p>
<p>$$\hat{r}_\theta(x, y) = \beta \sum_t \log\frac{\pi_\theta(y_t | x, y_{<t})}{\pi_\text{ref}(y_t | x, y_{<t})}$$</p>
<div class="callout callout-warn"><div class="callout-title">注意区分:implicit reward 不是 KL 本身</div><p>$\hat{r}_\theta$ 是<strong>单条 sequence 的 pointwise log-ratio</strong><strong>不是</strong> KL。只有当对 $y\sim\pi_\theta$ 取期望时,$\mathbb{E}_{y\sim\pi_\theta}[\hat{r}_\theta(x,y)] = \beta\cdot\text{KL}(\pi_\theta(\cdot|x)\,\|\,\pi_\text{ref}(\cdot|x))$(这是 k1 KL estimator 的 sequence-level 形式)。但 <strong>DPO 训练时 $y_w, y_l$ 不是从 $\pi_\theta$ 采的,而是来自固定 preference 数据</strong>,所以训练阶段的 $\hat{r}_\theta$ 不能直接读作 KL;它只是 pairwise log-ratio 差异。</p>
<p><strong>正确表述</strong>DPO loss 的对偶 RLHF 解释是把 $\hat{r}_\theta$ 当 rewardBT model 给概率 $\sigma(\hat{r}_w - \hat{r}_l)$;它对应"KL-regularized RL 闭式最优 policy $\pi^* \propto \pi_\text{ref}\exp(r/\beta)$"反解出的 reward 表达式。$\pi_\theta$ 在 implicit RLHF 视角下隐式被 KL 约束(因为 $\hat r_\theta$ 形式里 $\pi_\theta/\pi_\text{ref}$ 出现),但 DPO 优化的是 pairwise margin 而非显式 KL margin。</p></div>
<h4 id="511-dpo-闭式推导回顾">5.1.1 DPO 闭式推导回顾</h4>
<p>KL-regularized 目标:</p>
<p>$$\max_\pi \mathbb{E}_{x,\, y \sim \pi}[r(x, y)] - \beta\, \text{KL}(\pi \| \pi_\text{ref})$$</p>
<p>对单个 $x$ 用 Lagrangian + 求导(详细推导见 §6.1),得:</p>
<p>$$\pi^*(y|x) = \frac{1}{Z(x)} \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y)}{\beta}\right)$$</p>
<p>反解:</p>
<p>$$r(x, y) = \beta \log\frac{\pi^*(y|x)}{\pi_\text{ref}(y|x)} + \beta \log Z(x)$$</p>
<p>代入 Bradley-Terry $P(y_w \succ y_l | x) = \sigma(r(x, y_w) - r(x, y_l))$$\beta \log Z$ 消掉,得 DPO</p>
<p>$$\boxed{\;\mathcal{L}_\text{DPO}(\theta) = -\mathbb{E}_{(x,y_w,y_l)}\log\sigma\!\left(\beta\log\frac{\pi_\theta(y_w|x)}{\pi_\text{ref}(y_w|x)} - \beta\log\frac{\pi_\theta(y_l|x)}{\pi_\text{ref}(y_l|x)}\right)\;}$$</p>
<h4 id="512-dpo-梯度的-kl-解释">5.1.2 DPO 梯度的 KL 解释</h4>
<p>$$\nabla_\theta \mathcal{L}_\text{DPO} = -\beta \mathbb{E}\!\Big[\sigma(\hat{r}_l - \hat{r}_w)\big(\nabla_\theta \log\pi_\theta(y_w|x) - \nabla_\theta \log\pi_\theta(y_l|x)\big)\Big]$$</p>
<p><strong>解释</strong></p>
<ul><li>$\sigma(\hat{r}_l - \hat{r}_w)$ 是"当前模型对偏好顺序错位的置信度"。</li><li>$\nabla \log\pi(y_w) - \nabla \log\pi(y_l)$ 是"提升 $y_w$ 概率 + 降低 $y_l$"。</li><li>$\beta$ 出现两次:一次进 implicit reward $\hat{r}$(决定 sigmoid 内部),一次显式作梯度系数。所以<strong>β 在 DPO 里同时调"KL 强度"和"梯度幅值"</strong>——与 RLHF 中 β 只调一个东西不同。</li></ul>
<div class="callout callout-warn"><div class="callout-title">DPO 的 β 调参隐患</div><p>DPO 调 β 不直接对应 RLHF 调 β 的语义。在 PPO 中 β 只影响 KL penalty 强度,在 DPO 中 β 同时影响:(1) implicit reward scale、(2) 梯度幅值(外层 β)、(3) sigmoid 饱和位置(内层 β)。<strong>经验值 $\beta \in [0.05, 0.5]$ 但每个任务最优 β 不同</strong></p></div>
<h3 id="52-grpok3-kl-in-loss">5.2 GRPOk3 KL in loss</h3>
<p>DeepSeekMath GRPO 用 k3KL 作为独立 loss 项:</p>
<p>$$L^\text{GRPO}(\theta) = \mathbb{E}\!\left[\frac{1}{G}\sum_{i=1}^G \frac{1}{|y_i|}\sum_{t=1}^{|y_i|}\!\Big(\min(\rho_{i,t} \hat{A}_{i,t}, \text{clip}(\rho_{i,t}, 1{-}\epsilon, 1{+}\epsilon)\hat{A}_{i,t}) - \beta\,\widehat{\text{KL}}_3^{i,t}\Big)\right]$$</p>
<p>其中 $\widehat{\text{KL}}_3^{i,t} = e^{-\log r_{i,t}} + \log r_{i,t} - 1$per-token k3),$\log r_{i,t} = \log\pi_\theta(y_{i,t}|\cdot) - \log\pi_\text{ref}(y_{i,t}|\cdot)$。</p>
<p><strong>为什么 GRPO 历史上选 k3</strong>(注意:这些都是 <strong>value-estimator</strong> 性质,不直接保证 loss gradient 正确,见 §3.6):</p>
<ol><li><strong>非负</strong>:作为 loss 数值显示直观(k1 数值可负,调试时容易让 optimizer 监控曲线看起来怪;但 k1 用在 reward 里是无害的)。</li><li><strong>value estimator 无偏</strong>$\mathbb{E}_{\pi_\theta}[\widehat{\text{KL}}_3] = \text{KL}$<strong>仅作为 KL 数值估计无偏;对 θ 反传时 gradient 是 first-order Taylor approximation,有 $O(\Delta^2)$ bias</strong>)。</li><li><strong>value estimator 低方差</strong>:相比 k1 数值,方差更小(log 监控曲线更平滑)。</li><li><strong>不进 advantage</strong>:与 In-reward 方案的耦合相对解开,便于诊断(KL loss 和 PG loss 独立监控)。</li></ol>
<div class="callout callout-warn"><div class="callout-title">GRPO 的 k3-as-loss 不是理论 principled 的最佳选择</div><p>Rethinking KL (arXiv 2510.01555) 系统分析显示 on-policy 下 (P1) k1-in-reward 或 (P2) k2-as-loss 是严格 reverse-KL gradientGRPO/DAPO 实际工程上 $\beta$ 锁得紧、$\Delta$ 很小,所以 first-order approximation 误差有限——但<strong>面试中应能区分 "value-estimator 优势" 与 "loss-gradient 正确性"</strong></p></div>
<h3 id="53-simpo去掉-reference没有-kl-anchor">5.3 SimPO:去掉 reference,没有 KL anchor</h3>
<p>SimPO 把 implicit reward 改成 length-normalized log-prob</p>
<p>$$r_\text{SimPO}(x, y) = \frac{\beta}{|y|} \log \pi_\theta(y|x)$$</p>
<p><strong>关键差异</strong><strong>没有 $\pi_\text{ref}$</strong>,所以<strong>没有 KL 项</strong>。损失:</p>
<p>$$\mathcal{L}_\text{SimPO} = -\mathbb{E}\log\sigma\!\left(\frac{\beta}{|y_w|}\log\pi(y_w) - \frac{\beta}{|y_l|}\log\pi(y_l) - \gamma\right)$$</p>
<p><strong>后果</strong></p>
<ul><li>✅ 训练时省一份 reference policy(显存减半)。</li><li>❌ 没有 KL anchorpolicy 离 SFT 的距离<strong>完全不可控</strong></li><li>实测上 SimPO 在某些 benchmarkAlpacaEval-2 / Arena-Hard)上优于 DPO;但生成质量在 OOD prompt 上<strong>比 DPO 不稳</strong>。SimPO 的设计是"用 length-norm + margin 替代 KL anchor"——它假定了"短 prompt-response 任务下,长度归一 + margin 足以约束 policy"<strong>不是对所有任务都成立</strong></li></ul>
<div class="callout callout-info"><div class="callout-title">SimPO 没有 KL 的工程影响</div><p>工程上发现 SimPO 训完的 model 在重复模式、生成长度、对 prompt 微扰的鲁棒性上<strong>都比 DPO 差</strong>。这是为什么很多生产 RLHF 仍然用 DPO + small β 而不是 SimPO——KL anchor 是有代价但有价值。</p></div>
<h3 id="54-kto--ipo--orpo-的-kl-处理">5.4 KTO / IPO / ORPO 的 KL 处理</h3>
<table><thead><tr><th>算法</th><th>KL 形式</th><th>备注</th></tr></thead><tbody><tr><td><strong>KTO</strong> (Ethayarajh 2024 ICML)</td><td>通过 reference point $z_0 = \mathbb{E}[\beta\cdot\text{KL}]$batch mismatched pair 估,detach</td><td>KL 隐式地"作 anchor"implicit reward 偏离 $z_0$ 多远</td></tr><tr><td><strong>IPO</strong> (Azar 2024 AISTATS)</td><td>与 DPO 同($\log(\pi/\pi_\text{ref})$),但损失从 sigmoid 改 squared</td><td>防止 deterministic preference 下 $\hat{r}$ 无界增长</td></tr><tr><td><strong>ORPO</strong> (Hong 2024 EMNLP)</td><td><strong>无 reference model</strong>(与 SimPO 类似),用 odds-ratio 代替</td><td>一阶段同时做 SFT + preferenceKL anchor 隐含在 SFT loss 里</td></tr></tbody></table>
<h3 id="55-recent-papers-2024-2026">5.5 Recent papers (2024-2026)</h3>
<table><thead><tr><th>论文</th><th>主张</th><th>KL 角度</th></tr></thead><tbody><tr><td><strong>DeepSeekMath GRPO</strong> (Shao et al. 2024 arXiv 2402.03300)</td><td>组内归一化 + k3 KL in loss</td><td>第一个在 LLM RL 中默认 k3 KL</td></tr><tr><td><strong>DPO Implicit Reward Models</strong> (Rafailov 2023 NeurIPS)</td><td>DPO 的 implicit reward 等价于 KL log-ratio</td><td>DPO 本质是 KL-regularized 优化的反解</td></tr><tr><td><strong>Reward Model Overoptimization Scaling Laws</strong> (Gao, Schulman, Hilton 2023 ICML)</td><td>gold reward 在 KL 距离上 inverted-U</td><td>KL 是 overoptimization 的天然 x-axis</td></tr><tr><td><strong>DAPO</strong> (Yu et al. 2025 ByteDance arXiv 2503.14476)</td><td>clip-higher + dynamic sampling + token-level loss</td><td>KL 项常被设小或关掉,加入清理 prompt 的 dynamic sampling</td></tr><tr><td><strong>Cohere DRO / OPO</strong> (各种 2024-2025 工作)</td><td>offline IS-correction RL with KL</td><td>把 IS-correction 与 KL anchor 联合</td></tr><tr><td><strong>"Rethinking KL Regularization in RLHF: From Value Estimation to Gradient Optimization"</strong> (Kezhao Liu et al. 2025-10, arXiv 2510.01555)</td><td>系统区分 KL value estimation 与 gradient optimizationk3-as-loss 是 biased first-order approximation;推荐 (1) k1 in reward(严格 reverse-KL score-function gradient)或 (2) <strong>k2 as loss</strong>value estimator 有偏,但 on-policy loss gradient 严格等价于 k1-in-reward / reverse-KL gradient);off-policy 还需 IS correction</td><td>历史 GRPO 的"k3 as loss"是工程惯例不是理论 principled</td></tr><tr><td><strong>"A Comedy of Estimators: On KL Regularization in RL Training of LLMs"</strong> (Vedant Shah et al. 2025-12, arXiv 2512.21852, v3 2026-03)</td><td>在多种 RL 算法 + estimator placement 组合上系统对比 k1/k2/k3 的 estimator bias 与 gradient bias;分析 placement-effect</td><td>不存在 universally 最好的 estimatorreward-shaping vs loss-term 各有适用场景</td></tr></tbody></table>
<h2 id="6-theoreticalkl-regularized-rl-的最优-policy--reward-overoptimization">§6 TheoreticalKL-Regularized RL 的最优 policy + Reward Overoptimization</h2>
<h3 id="61-kl-regularized-rl-闭式解dpo-的数学基础">6.1 KL-Regularized RL 闭式解(DPO 的数学基础)</h3>
<p><strong>定理</strong>KL-regularized policy optimization 的闭式解):</p>
<p>考虑:</p>
<p>$$\max_\pi J(\pi) = \mathbb{E}_{y \sim \pi(\cdot|x)}[r(x, y)] - \beta\, \text{KL}\!\big(\pi(\cdot|x) \| \pi_\text{ref}(\cdot|x)\big)$$</p>
<p>其中 $\pi$ 是对任意 $x$ 的分布,$\pi_\text{ref}$ 严格正($\pi_\text{ref}(y|x) > 0$ 对所有 $y$)。</p>
<p><strong>唯一最优解</strong></p>
<p>$$\boxed{\;\pi^*(y|x) = \frac{1}{Z(x)}\, \pi_\text{ref}(y|x)\, \exp\!\left(\frac{r(x, y)}{\beta}\right),\quad Z(x) = \sum_{y'} \pi_\text{ref}(y'|x) \exp\!\left(\frac{r(x, y')}{\beta}\right)\;}$$</p>
<p><strong>证明</strong>Lagrangian):</p>
<p>固定 $x$,写目标(连续/离散通用,离散表示):</p>
<p>$$\mathcal{L}_x[\pi] = \sum_y \pi(y|x) r(x, y) - \beta \sum_y \pi(y|x) \log\frac{\pi(y|x)}{\pi_\text{ref}(y|x)} - \mu\!\left(\sum_y \pi(y|x) - 1\right)$$</p>
<p>其中 $\mu$ 是 normalization 约束的 Lagrange multiplier(注意符号:从 max 推 KKT 时把 $\sum_y\pi = 1$ 写成 $-\mu(\sum - 1)$ 是为了内点最优条件简洁)。</p>
<p>对 $\pi(y|x)$ 求偏导:</p>
<p>$$\frac{\partial \mathcal{L}_x}{\partial \pi(y|x)} = r(x, y) - \beta \log\frac{\pi(y|x)}{\pi_\text{ref}(y|x)} - \beta - \mu = 0$$</p>
<p>整理:</p>
<p>$$\log\frac{\pi(y|x)}{\pi_\text{ref}(y|x)} = \frac{r(x, y) - \mu - \beta}{\beta}$$</p>
<p>指数化:</p>
<p>$$\pi(y|x) = \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y) - \mu - \beta}{\beta}\right) = \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y)}{\beta}\right) \cdot e^{-(\mu+\beta)/\beta}$$</p>
<p>代入归一化条件 $\sum_y \pi(y|x) = 1$</p>
<p>$$e^{(\mu+\beta)/\beta} = \sum_y \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y)}{\beta}\right) = Z(x)$$</p>
<p>所以 $e^{-(\mu+\beta)/\beta} = 1/Z(x)$,得:</p>
<p>$$\pi^*(y|x) = \frac{1}{Z(x)} \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y)}{\beta}\right) \quad \blacksquare$$</p>
<p><strong>唯一性</strong>:因为 $J$ 在 $\pi$ 上是<strong>严格凹</strong>的(KL 是凸的,加负号变严格凹,且 reward 是 linear),凹优化有唯一最优。</p>
<h3 id="62-从最优-policy-反解-implicit-reward">6.2 从最优 policy 反解 implicit reward</h3>
<p>把 §6.1 的 $\pi^*$ 取 log</p>
<p>$$\log\pi^*(y|x) = \log\pi_\text{ref}(y|x) + \frac{r(x, y)}{\beta} - \log Z(x)$$</p>
<p>反解 $r$</p>
<p>$$\boxed{\;r(x, y) = \beta\log\frac{\pi^*(y|x)}{\pi_\text{ref}(y|x)} + \beta\log Z(x)\;}$$</p>
<p><strong>这就是 DPO 的 implicit reward</strong>。$\beta \log Z(x)$ 是 partition function<strong>只依赖 $x$,不依赖 $y$</strong>——在 Bradley-Terry 的 $r(x, y_w) - r(x, y_l)$ 差里<strong>消掉</strong></p>
<h3 id="63-bradley-terry-偏好模型下的-rl-等价于-dpo">6.3 Bradley-Terry 偏好模型下的 RL 等价于 DPO</h3>
<p>BT 模型:$P(y_w \succ y_l | x) = \sigma(r(x, y_w) - r(x, y_l))$。</p>
<p>代入 §6.2</p>
<p>$$r(x, y_w) - r(x, y_l) = \beta \log\frac{\pi^*(y_w|x)}{\pi_\text{ref}(y_w|x)} - \beta\log\frac{\pi^*(y_l|x)}{\pi_\text{ref}(y_l|x)}$$</p>
<p>替换 $\pi^*$ 为可学 $\pi_\theta$,对偏好数据 NLL</p>
<p>$$\mathcal{L}_\text{DPO}(\theta) = -\mathbb{E}\log\sigma\!\left(\beta\log\frac{\pi_\theta(y_w|x)}{\pi_\text{ref}(y_w|x)} - \beta\log\frac{\pi_\theta(y_l|x)}{\pi_\text{ref}(y_l|x)}\right)$$</p>
<p><strong>这是 §5.1 的 DPO 公式</strong>。所以<strong>DPO ≡ Bradley-Terry preference + KL-regularized RL 闭式解 + 偏好数据 NLL</strong>,三件套合一。</p>
<h3 id="64-reward-overoptimizationgao-schulman-hilton-2023-icml">6.4 Reward OveroptimizationGao, Schulman, Hilton 2023 ICML</h3>
<h4 id="641-问题表述">6.4.1 问题表述</h4>
<p>记 gold reward $r_g$(人感受的真实质量)、proxy reward $r_p$RM 估的)。RM 用偏好数据学,但偏好数据有限 → $r_p \ne r_g$。</p>
<p>随着 RL 训练 KL 距离 $d = \text{KL}(\pi_\theta \| \pi_\text{ref})$ 增大:</p>
<ul><li>$\mathbb{E}_{\pi_\theta}[r_p]$ 单调上升(policy 学到 RM 的偏好)。</li><li>$\mathbb{E}_{\pi_\theta}[r_g]$ 先升后降(<strong>inverted-U</strong>)—— 这是 reward overoptimization。</li></ul>
<h4 id="642-gao-2023-给的拟合形式">6.4.2 Gao 2023 给的拟合形式</h4>
<p>Gao 2023 用大量 RM size + KL 实验,给出 gold reward 关于 KL 距离 $d$ 的拟合形式(用 $\sqrt{d}$ 当 x-axis):</p>
<p>$$R_g(d) = d \cdot (\alpha_g - \gamma_g \cdot d) \quad \text{(BoN)}$$</p>
<p>$$R_g(d) = d \cdot (\alpha_g - \gamma_g \cdot d) - \delta_g\, d^{3/2}\quad \text{(PPO, 多了高阶项)}$$</p>
<p>其中 $\alpha_g, \gamma_g, \delta_g$ 是与 RM size 相关的系数;RM 越大,"高阶项 / 二次项"权重越小,过优化越慢。</p>
<h4 id="643-kl-是-overoptimization-的天然-axis">6.4.3 KL 是 overoptimization 的"天然 axis"</h4>
<p>无论是 BoN、PPO 还是 DPO(按 implicit reward 累积),都可以把训练曲线画成"<strong>KL 距离 vs gold reward</strong>"图。Gao 2023 发现:</p>
<ul><li><strong>不同算法(BoN / PPO)在同样 KL 下的 over-optimization 行为相似</strong>(同一 RM 给出的 gold 曲线形状一致)。</li><li><strong>更大 RM → 更慢的 over-optimization</strong>gold curve peak 更靠右)。</li><li><strong>KL 是一个一维 progress indicator</strong>,比 step 数 / reward 数更能解释 over-optimization。</li></ul>
<p><strong>面试 takeaway</strong>:在 RLHF 监控里,把 <code>(measured_KL, gold_reward)</code> 画图,看是否进入下降区——这是最直接的 "stop 早一点" 信号。</p>
<h3 id="65-kl-与-chi2-gap-的关系">6.5 KL 与 $\chi^2$ gap 的关系</h3>
<p>KL 与 $\chi^2$ 在 Pinsker 类不等式族里有关系:</p>
<p>$$\text{TV} \le \sqrt{\text{KL}/2}\qquad \text{(Pinsker)}$$</p>
<p>$$\text{KL} \le \log(1 + \chi^2)$$</p>
<p>在 RLHF 里 $\chi^2$ 偶尔被作为 KL 的"敏感"上界使用:<strong>当 $\chi^2$ 大但 KL 小,意味着 $\pi_\theta$ 有重 tail 偏离 $\pi_\text{ref}$</strong>(高方差但低 mean)。某些工作(Yu et al. 2024 / others)在监控 reward hacking 时同时画 KL 和 $\chi^2$,看 tail 行为。</p>
<h3 id="66-sequence-level-vs-token-level-kl">6.6 Sequence-level vs Token-level KL</h3>
<p>由 §1.1 的<strong>链式法则</strong></p>
<p>$$\text{KL}(\pi_\theta(\cdot|x) \| \pi_\text{ref}(\cdot|x)) = \mathbb{E}_{y \sim \pi_\theta}\!\left[\sum_t \log\frac{\pi_\theta(y_t | x, y_{<t})}{\pi_\text{ref}(y_t | x, y_{<t})}\right]$$</p>
<p><strong>sequence-level KL = token-level KL 之和的期望</strong>(自回归 chain rule)。注意:单条 rollout 上把 $\sum_t \log\pi_\theta(y_t)/\pi_\text{ref}(y_t)$ 直接当 KL 是 <strong>k1 estimator</strong>unbiased 但 per-rollout 方差大);若要 true token-level KL $D(\pi_\theta(\cdot|s_t)\|\pi_\text{ref}(\cdot|s_t))$ 还需 full-vocab forward。<strong>两者期望相等</strong>,工程上选 sampled log-ratio 是因为 vocab 求和昂贵。</p>
<p>但有两个<strong>implementation trick</strong> 与 token-level 相关:</p>
<ol><li><strong>Per-token clipping</strong>:单 token KL 偶尔很大(罕见 token、长 tail),可以对每 token KL 做 clip 防止单 token 拖飞 batch 总 KL。</li><li><strong>Mask on assistant tokens only</strong>:在 chat / agent setting 下,prompt token 不应该参与 KL 计算(prompt 是同一的,policy 和 ref 在 prompt 上完全一致,KL = 0;但浮点误差会污染)。所以 KL mask 与 PPO action_mask 重合,<strong>只在 assistant generation token 上算 KL</strong></li></ol>
<pre><code class="language-python"># Per-token KL with action mask (chat / agentic RL setting)
def per_token_kl_with_mask(logp_theta, logp_ref, action_mask, estimator=&quot;k3&quot;):
&quot;&quot;&quot;
logp_theta, logp_ref: [B, T] per-token log-prob
action_mask: [B, T] 1 = assistant token, 0 = prompt/system/pad
estimator: &quot;k1&quot; | &quot;k2&quot; | &quot;k3&quot;
Returns: mean KL over assistant tokens, scalar.
&quot;&quot;&quot;
log_r = logp_theta - logp_ref
if estimator == &quot;k1&quot;:
kl_per_tok = log_r
elif estimator == &quot;k2&quot;:
kl_per_tok = 0.5 * log_r ** 2
elif estimator == &quot;k3&quot;:
delta = -log_r # log(π_ref / π_θ)
kl_per_tok = torch.exp(delta) - delta - 1.0
else:
raise ValueError(f&quot;Unknown estimator: {estimator}&quot;)
masked = (kl_per_tok * action_mask).sum()
n = action_mask.sum().clamp_min(1.0)
return masked / n</code></pre>
<h2 id="7-实践--代码">§7 实践 + 代码</h2>
<h3 id="71-ppo-风格in-reward-shaping-实现">7.1 PPO 风格:In-reward shaping 实现</h3>
<pre><code class="language-python">import torch
import torch.nn.functional as F
def ppo_reward_with_kl(rewards_terminal, rollout_logp_theta, logp_ref,
action_mask, beta=0.02):
&quot;&quot;&quot;
PPO / InstructGPT style: KL penalty in reward (k1 estimator).
rewards_terminal: [B] only the last assistant token gets the RM reward
rollout_logp_theta: [B, T] log π_θ_old(y_t | ...), recorded during rollout, DETACHED
logp_ref: [B, T] log π_ref(y_t | ...), reference policy frozen
action_mask: [B, T] 1 = assistant token
Returns: shaped_reward [B, T] per-token reward with KL penalty baked in.
⚠️ 关键:rollout_logp_theta 和 logp_ref 必须是 detached scalarsrollout 阶段记录或 no_grad
forward)。这里 shaped reward 是 PPO/score-function 反传中的 reward tensor**不能携带梯度**
否则 backward 时 KL 项会和 PG surrogate 双重反传,破坏 score-function 语义。生产代码里通常在
rollout buffer 中把 logp_old 当固定数据保存,update 阶段重新 forward 拿 new_logp。
&quot;&quot;&quot;
B, T = rollout_logp_theta.shape
# k1 KL per token (signed; mean is unbiased). Both inputs assumed detached.
kl_per_tok = (rollout_logp_theta.detach() - logp_ref.detach()) * action_mask # [B, T]
# spread terminal reward to last assistant token
last_token_idx = action_mask.cumsum(dim=-1).argmax(dim=-1) # [B]
R_per_tok = torch.zeros_like(kl_per_tok)
R_per_tok[torch.arange(B), last_token_idx] = rewards_terminal
# combine
shaped = R_per_tok - beta * kl_per_tok
return shaped # 整个 tensor 是 detached / 无梯度,作为 PPO advantage 计算的数据输入</code></pre>
<h3 id="72-grpo-风格in-loss-regularization-实现k3">7.2 GRPO 风格:In-loss regularization 实现(k3</h3>
<pre><code class="language-python">def grpo_loss_with_k3_kl(policy, ref_policy, batch, eps_clip=0.2, beta=0.04):
&quot;&quot;&quot;
GRPO / DeepSeekMath style: KL penalty in loss (k3 estimator).
batch:
input_ids: [N, L] N = sum_b G_b samples
action_mask: [N, L]
old_log_probs: [N, L]
rewards: [N] sequence-level reward
group_id: [N] which prompt
&quot;&quot;&quot;
rewards = batch[&quot;rewards&quot;]
gid = batch[&quot;group_id&quot;].long()
num_groups = int(gid.max().item()) + 1
# Group-relative advantage (z-score within group)
counts = torch.zeros(num_groups, device=rewards.device).scatter_add_(
0, gid, torch.ones_like(rewards))
sums = torch.zeros(num_groups, device=rewards.device).scatter_add_(
0, gid, rewards)
group_mean = sums / counts.clamp_min(1.0)
diff_sq = (rewards - group_mean[gid]) ** 2
sq_sums = torch.zeros(num_groups, device=rewards.device).scatter_add_(
0, gid, diff_sq)
group_std = (sq_sums / counts.clamp_min(1.0)).sqrt()
A = (rewards - group_mean[gid]) / (group_std[gid] + 1e-8)
A = A.unsqueeze(-1) # [N, 1] shared per token
# Forward pass policy + ref
logits = policy(batch[&quot;input_ids&quot;]).logits[:, :-1]
log_probs = F.log_softmax(logits, dim=-1)
tgt = batch[&quot;input_ids&quot;][:, 1:].unsqueeze(-1)
new_log_probs = log_probs.gather(-1, tgt).squeeze(-1)
new_log_probs = F.pad(new_log_probs, (1, 0)) # [N, L]
mask = batch[&quot;action_mask&quot;].float()
with torch.no_grad():
ref_logits = ref_policy(batch[&quot;input_ids&quot;]).logits[:, :-1]
ref_log_probs = F.log_softmax(ref_logits, dim=-1)
ref_token_lp = ref_log_probs.gather(-1, tgt).squeeze(-1)
ref_token_lp = F.pad(ref_token_lp, (1, 0))
# PPO-Clip surrogate (advantage shared per sample)
ratio = torch.exp(new_log_probs - batch[&quot;old_log_probs&quot;])
surr1 = ratio * A
surr2 = torch.clamp(ratio, 1 - eps_clip, 1 + eps_clip) * A
pg_per_tok = torch.min(surr1, surr2) # [N, L]
# k3 KL per token: exp(Δ) - Δ - 1, Δ = log(π_ref / π_θ)
delta = ref_token_lp - new_log_probs # log(π_ref / π_θ)
kl_per_tok_k3 = torch.exp(delta) - delta - 1.0 # ≥ 0
# Combine: maximize PG - β·KL → minimize -PG + β·KL
token_obj = pg_per_tok - beta * kl_per_tok_k3
seq_len = mask.sum(dim=-1).clamp_min(1.0)
per_seq = (token_obj * mask).sum(dim=-1) / seq_len
loss = -per_seq.mean()
with torch.no_grad():
kl_mean = (kl_per_tok_k3 * mask).sum() / mask.sum().clamp_min(1.0)
return loss, {&quot;kl_k3&quot;: kl_mean.item(), &quot;advantage_std&quot;: A.std().item()}</code></pre>
<h3 id="73-dpo-闭式-loss--implicit-reward-监控">7.3 DPO 闭式 loss + implicit reward 监控</h3>
<pre><code class="language-python">def dpo_loss_with_implicit_reward_monitor(policy, ref_policy, batch, beta=0.1):
&quot;&quot;&quot;
DPO loss + implicit reward margin (β × pointwise sequence log-density ratio on
preference data; this is NOT a KL estimator on preference data — only equals
β·KL when expectation is taken under y~π_θ, which doesn&#x27;t hold for fixed preference pairs).
&quot;&quot;&quot;
def log_prob_sum(model, ids, mask):
logits = model(ids).logits[:, :-1]
logp = F.log_softmax(logits, dim=-1)
tgt = ids[:, 1:].unsqueeze(-1)
token_logp = logp.gather(-1, tgt).squeeze(-1)
token_mask = mask[:, 1:]
return (token_logp * token_mask).sum(dim=-1)
pi_w = log_prob_sum(policy, batch[&quot;chosen_ids&quot;], batch[&quot;chosen_mask&quot;])
pi_l = log_prob_sum(policy, batch[&quot;rejected_ids&quot;], batch[&quot;rejected_mask&quot;])
with torch.no_grad():
ref_w = log_prob_sum(ref_policy, batch[&quot;chosen_ids&quot;], batch[&quot;chosen_mask&quot;])
ref_l = log_prob_sum(ref_policy, batch[&quot;rejected_ids&quot;], batch[&quot;rejected_mask&quot;])
# sequence-level log-density ratios on preference data
log_ratio_w = pi_w - ref_w # Σ_t log(π_θ/π_ref) on y_w
log_ratio_l = pi_l - ref_l
diff = beta * (log_ratio_w - log_ratio_l)
loss = -F.logsigmoid(diff).mean()
# implicit rewards (DPO 定义:β × pointwise sequence log-ratiodetached for logging)
chosen_reward = beta * log_ratio_w.detach()
rejected_reward = beta * log_ratio_l.detach()
margin = (chosen_reward - rejected_reward).mean()
# ⚠️ 注意:preference data 上的 log-ratio 平均**不是** KL estimator——KL 需要 y ~ π_θ 采样。
# 这里只能监控&quot;模型在 preference 数据上偏离 ref 的程度&quot;,是 DPO 训练健康度指标,不能当 KL 看。
avg_pref_log_ratio = ((log_ratio_w.detach() + log_ratio_l.detach()) / 2).mean()
return loss, {&quot;margin&quot;: margin.item(),
&quot;avg_pref_log_ratio&quot;: avg_pref_log_ratio.item(),
&quot;chosen_reward&quot;: chosen_reward.mean().item(),
&quot;rejected_reward&quot;: rejected_reward.mean().item()}</code></pre>
<h3 id="74-reward-overoptimization-监控">7.4 Reward overoptimization 监控</h3>
<pre><code class="language-python">def overoptimization_monitor(policy, ref_policy, gold_reward_fn, prompts,
checkpoints_kl, gold_at_kl):
&quot;&quot;&quot;
Track gold reward as a function of measured KL distance during training.
Call periodically; plot (measured_KL, gold_reward) to visualize the inverted-U.
Args:
policy: current π_θ
ref_policy: frozen π_ref
gold_reward_fn: callable (text -&gt; float), uses gold RM or human eval
prompts: list of held-out prompts (small, e.g. 64)
checkpoints_kl: running list of KL values across training
gold_at_kl: running list of gold reward values
&quot;&quot;&quot;
measured_kl_total = 0.0
gold_reward_total = 0.0
for prompt in prompts:
# Generate from policy and ref; compute per-token k3 KL on policy generation
out_policy = policy.generate(prompt, do_sample=True)
# ... (use generate to get logits, mask, compute k3 KL) ...
# For simplicity here, just track the average sequence-level KL
kl_seq = compute_seq_kl_k3(policy, ref_policy, out_policy)
gold = gold_reward_fn(out_policy)
measured_kl_total += kl_seq
gold_reward_total += gold
avg_kl = measured_kl_total / len(prompts)
avg_gold = gold_reward_total / len(prompts)
checkpoints_kl.append(avg_kl)
gold_at_kl.append(avg_gold)
# Detection heuristic: if last 5 gold values are decreasing while KL is rising,
# we are likely in the over-optimization regime.
if len(gold_at_kl) &gt;= 5:
recent_gold = gold_at_kl[-5:]
recent_kl = checkpoints_kl[-5:]
if all(recent_gold[i] &gt;= recent_gold[i+1] for i in range(4)) \
and all(recent_kl[i] &lt;= recent_kl[i+1] for i in range(4)):
print(f&quot;⚠️ Possible reward over-optimization: KL ↑, gold ↓ over 5 checkpoints&quot;)
return avg_kl, avg_gold</code></pre>
<h3 id="75-工程清单debug-checklist">7.5 工程清单(debug checklist</h3>
<div class="callout callout-warn"><div class="callout-title">KL 相关 bug Top 8</div></div>
<ol><li><strong>KL 用错了 mask</strong>:在 prompt token 上算 KL 应该 = 0(同 prompt 输入),但 floating-point 噪声会污染,所以<strong>必须 mask only assistant tokens</strong></li><li><strong>k1 显示为负</strong>log-ratio 单样本可负,但<strong>期望非负</strong>。不是 bug,是 estimator 性质。换 k3 / k2 看监控更直观。</li><li><strong>β 单位错</strong>reward scale = O(1) 时 β = 0.02reward scale = O(100) 时 β 要相应放大。否则 KL anchor 失效。</li><li><strong>adaptive β 振荡</strong>target_kl 太严 / mult 太大。把 mult clip 到 [0.8, 1.2]update 频率降到每 100 steps。</li><li><strong>Reference policy 没冻结</strong>:忘记 <code>ref_policy.eval()</code> + <code>torch.no_grad()</code>ref 跟着训,KL 变成 self-distillation。</li><li><strong>Per-token vs sequence-level KL 混淆</strong>:监控里有时报 per-token,有时报 sequence-level,看错就调错 β。统一一个单位。</li><li><strong>GRPO 中 KL 项缩 reward</strong>:当 reward 是 binary {0, 1}(数学题)且 β = 0.04KL ≈ 0.5 时,KL penalty 已大于 reward 平均值——loss 被 KL 主导。<strong>降 β 到 1e-3 或更小</strong></li><li><strong>Float overflow on $\pi_\text{ref}/\pi_\theta$</strong>:当 policy 大幅偏离 ref$\pi_\text{ref}/\pi_\theta$ 可能极大,$e^\Delta$ 溢出。<strong>用 log-space 写 k3</strong><code>exp(delta) - delta - 1</code> 在 $\Delta$ 大时仍可能溢出,可以加 <code>torch.clamp(delta, max=10)</code> 或换数值稳定 form。</li></ol>
<h2 id="8-失败模式kl-collapse--runaway--reward-hacking">§8 失败模式:KL Collapse / Runaway / Reward Hacking</h2>
<h3 id="81-kl-collapse-过大或-entropy-太低">8.1 KL Collapse(β 过大或 entropy 太低)</h3>
<p><strong>症状</strong></p>
<ul><li>KL 曲线 $\approx 0$policy 等同 reference。</li><li>Reward 不上升。</li><li>Generation 与 SFT 完全相同。</li></ul>
<p><strong>原因</strong></p>
<ul><li>β 过大,KL penalty 主导 lossPG 信号被压住。</li><li>Policy entropy 太低(SFT 后已经很 deterministic)→ 进一步 update 困难。</li></ul>
<p><strong>修复</strong></p>
<ul><li>降低 β(adaptive controller 应能自动处理)。</li><li>加 entropy bonus$+ c_e \cdot H[\pi_\theta]$)。</li><li>检查 PG 与 KL loss 的 magnitude ratio:理想 $|\text{PG}| / (\beta \cdot |\text{KL}|) \in [1, 10]$。</li></ul>
<h3 id="82-kl-runaway-过小或-reward-信号太强">8.2 KL Runaway(β 过小或 reward 信号太强)</h3>
<p><strong>症状</strong></p>
<ul><li>KL 持续上升,policy 与 ref 距离越来越大。</li><li>Generation 变长、出现重复模式、风格漂移。</li><li>Validation 上 gold reward 开始下降(reward overoptimization)。</li></ul>
<p><strong>原因</strong></p>
<ul><li>β 过小,KL anchor 失效。</li><li>Reward 信号过强(neural RM 给出 huge gradient)。</li><li>PPO importance ratio 经常超出 clip 范围,KL 信号被 clip 屏蔽(Option A 特有)。</li></ul>
<p><strong>修复</strong></p>
<ul><li>升 β(adaptive)。</li><li>加 max_kl_budget 提前停(当 measured KL &gt; target 时停训)。</li><li>用 reward model ensemble + conservative aggregationmin / mean - std)。</li><li>若是 Option A,考虑切到 Option BKL 不被 PPO clip 屏蔽)。</li></ul>
<h3 id="83-reward-overoptimizationkl-距离的-inverted-u">8.3 Reward OveroptimizationKL 距离的 inverted-U</h3>
<p><strong>症状</strong></p>
<ul><li>Proxy reward 持续上升。</li><li>Gold reward 先升后降(inverted-U)。</li><li>人类评测:模型在 in-distribution 数据上看起来好,但 OOD prompt 上崩。</li></ul>
<p><strong>原因</strong>:见 §6.4RM 与 gold reward 的本质不同。</p>
<p><strong>修复</strong></p>
<ol><li><strong>KL budget early stop</strong>:把 measured KL 限制在 inverted-U peak 之前(需要 gold reward 监控)。</li><li><strong>RM ensemble</strong>:多个 seed 的 RM,取 min 或 mean - $k\cdot\text{std}$。</li><li><strong>混 RL + DPO</strong>:先 DPO 拿 70%,再 small-β PPO 跑最后一公里。</li><li><strong>Rule-based reward 替代神经 RM</strong>:数学 / 代码任务的根本解法。</li><li><strong>PRM 替代 ORM</strong>dense reward → 单步 over-optimization 受限。</li></ol>
<h3 id="84-length-biasdpo-特有也可视作-kl-anchor-不够强">8.4 Length biasDPO 特有,也可视作 KL anchor 不够强)</h3>
<p><strong>症状</strong></p>
<ul><li>DPO 训完后输出明显变长。</li><li>AlpacaEval 上分数高但用户感受变啰嗦。</li></ul>
<p><strong>原因</strong>DPO loss 是 sequence-level log-ratio 差。$y_w$ 通常更长(人选更详尽答案),longer $y_w$ → 更负的 $\log\pi(y_w)$ → log-ratio 差更大 → loss 减小。但这是 RM scale 而非 reasoning quality。</p>
<p><strong>修复</strong></p>
<ul><li>SimPO 的 length-normalization$r = (\beta/|y|)\log\pi$)。</li><li>Reward shaping 加 length penalty。</li><li>数据 curation:让 $y_w$ 和 $y_l$ 长度分布相似。</li></ul>
<h3 id="85-reference-policy-wrong-checkpoint-failure">8.5 Reference policy "wrong checkpoint" failure</h3>
<p><strong>症状</strong>:训练正常但下游 eval 极差。</p>
<p><strong>原因</strong>:用了错误的 ref checkpoint(比如 pretrain base 而不是 SFT)。KL anchor 锚到了"语言模型"而不是"指令模型"。</p>
<p><strong>修复</strong>reference 必须是 immediate-previous-stage SFT checkpoint,不能跳层级。</p>
<h2 id="9-25-高频面试题">§9 25 高频面试题</h2>
<p>按难度分 3 档:L1 = 任何 LLM 工程岗都会问;L2 = research / alignment 团队会问;L3 = 顶级 lab / DeepSeek 量级团队的硬核题。每题点开看答案要点 + 易踩坑。</p>
<h3 id="l1-必会题10-题">L1 必会题(10 题)</h3>
<details>
<summary>Q1.KL 散度的定义和 3 个核心性质?</summary>
<ul><li>定义:$\text{KL}(p\|q) = \mathbb{E}_{x\sim p}[\log(p(x)/q(x))]$</li><li>非负(Jensen);等号 ⟺ $p = q$ a.e.</li><li>不对称($\text{KL}(p\|q) \ne \text{KL}(q\|p)$),不是 metric</li><li>联合凸,参数化变换下不变(reparam invariant</li></ul>
<p>说 KL 是"距离"——错(不满足三角不等式);或不知道凸性。</p>
</details>
<details>
<summary>Q2.RLHF 里为什么要加 KL penalty</summary>
<ul><li>防 reward hackingpolicy 找 RM 盲点拿高分但人感受变差</li><li>防语言流畅性塌掉:no-KL 时模型可能输出"鬼话但 RM 给高分"</li><li>防 distribution shiftpolicy 离 SFT 太远,RM 自己也不准(OOD)</li><li>提供闭式最优 policy$\pi^* \propto \pi_\text{ref}\exp(r/\beta)$</li></ul>
<p>只说"防过拟合"——不够具体;不知道 reward hacking。</p>
</details>
<details>
<summary>Q3.k1 estimator 是什么?为什么单样本可以为负?</summary>
<ul><li>k1: $\widehat{\text{KL}}_1 = \log(\pi_\theta(y)/\pi_\text{ref}(y))$(直接 log-ratio</li><li><strong>期望</strong> $\mathbb{E}_{y\sim\pi_\theta}[\log r] = \text{KL}$(无偏),但<strong>单样本</strong> $\log r$ 可正可负</li><li>原因:单个样本 $y$ 上 $\pi_\theta$ 可能比 $\pi_\text{ref}$ 大也可能小,log-ratio 没有"非负"约束</li><li>工程影响:用 k1 做监控时看到负值不要慌,是 estimator 本性</li></ul>
<p>把单 estimator 和期望混淆;或不知 expectation 非负 ≠ pointwise 非负。</p>
</details>
<details>
<summary>Q4.k3 estimator (Schulman 2020) 公式是什么?三大性质?</summary>
<ul><li>公式:$\widehat{\text{KL}}_3 = e^\Delta - \Delta - 1$$\Delta = \log(\pi_\text{ref}/\pi_\theta) = -\log r$</li><li>等价形式:$\widehat{\text{KL}}_3 = (\pi_\text{ref}/\pi_\theta) - \log(\pi_\text{ref}/\pi_\theta) - 1$</li><li><strong>无偏</strong>$\mathbb{E}_{\pi_\theta} = \text{KL}$,用 $\sum_y\pi_\text{ref} = 1$</li><li><strong>非负</strong>$f(x) = e^x - x - 1 \ge 0$</li><li><strong>低方差</strong>(带 expectation-0 control variate $\pi_\text{ref}/\pi_\theta - 1$</li></ul>
<p>只背公式不知道 derivation;或不知道它非负。</p>
</details>
<details>
<summary>Q5.KL 在 RLHF 中有哪两种放置?区别?</summary>
<ul><li><strong>In-reward shaping (Option A)</strong>$\tilde{r}_t = r_t - \beta \cdot \text{KL}_t$(用 k1),KL 进 advantage / GAE。InstructGPT 标准。</li><li><strong>In-loss regularization (Option B)</strong>$\mathcal{L} = \mathcal{L}_\text{PG} + \beta \cdot \mathbb{E}[\text{KL}]$。GRPO / DAPO 历史选 k3 estimator。</li><li>目标函数相同,但<strong>梯度路径不同</strong><strong>Principled gradient</strong> 选择:(P1) k1 in reward(P2) k2 as loss—— on-policy 下两者 gradient-equivalent,都是严格 reverse-KL gradient。<strong>GRPO 的 k3-as-loss</strong> 是 reverse-KL gradient 的 first-order Taylor approximation,有 $O(\Delta^2)$ bias(参见 §3.6 / Rethinking KL arXiv 2510.01555)。</li><li>PPO clip 在 Option A 会"屏蔽"超出 clip 的 KLadvantage 内含 KL 一并被 clip);Option B 不会。</li><li>实践:math/code RL 历史上选 B (k3) 因为 β 小、$\Delta$ 小,bias 可忽略;helpfulness / safety 多用 A (k1);如果要严格 principledon-policy 用 P2 (k2-as-loss) 是 simplest principled 选择。</li></ul>
<p>说两者完全等价——目标相同梯度不等价;说 k3-as-loss 是 principled——它是 first-order approximation,理论不严格。</p>
</details>
<details>
<summary>Q6.β 怎么调?太大太小各有什么症状?</summary>
<ul><li>β 太大:KL ≈ 0policy 卡在 refreward 不涨,模型基本等同 SFT</li><li>β 太小:KL runawaypolicy 漂走,generation 变长 / 重复 / 谄媚,reward hacking</li><li>起点:InstructGPT 用 β ≈ 0.02per-token);GRPO 数学任务 β ≈ 0.04 或更小;DAPO 经常 β ≈ 0</li><li>调法:固定 / adaptive(按 measured KL 距 target 拉 β) / annealing schedule</li></ul>
<p>只说"看着调";不知 β 的工程量级。</p>
</details>
<details>
<summary>Q7.Forward KL vs Reverse KL 在 RLHF 里用哪个?为什么?</summary>
<ul><li>RLHF 几乎都用 $\text{KL}(\pi_\theta \| \pi_\text{ref})$;按标准 VI/RLHF 约定(DPO/RLOO/Rethinking KL 等都采用)这是 <strong>reverse KL</strong>$\pi_\theta$ 是变分一侧),mode-seeking</li><li>因为训练时从 $\pi_\theta$ 采样(rollout),$\mathbb{E}_{\pi_\theta}[\log r]$ 直接用样本估</li><li><strong>Forward KL</strong> $\text{KL}(\pi_\text{ref} \| \pi_\theta)$ 需要从 $\pi_\text{ref}$ 采样,工程上无意义(要训 $\pi_\theta$ 不是 $\pi_\text{ref}$),且 mass-covering 行为不符合 RLHF 目标</li><li>Reverse KL 的 mode-seeking 性质正合规则:在 $\pi_\text{ref}$ 高密度区里选 reward 最高的 mode</li></ul>
<p>不知道命名约定(少数早期 RL 教材以采样分布命名,会把 reverse 标成 forward;面试时给公式更稳);或反过来说 forward 更好。</p>
</details>
<details>
<summary>Q8.DPO 的 implicit reward 跟 KL 有什么关系?</summary>
<ul><li>DPO implicit reward $\hat{r}_\theta(x, y) = \beta\log(\pi_\theta(y|x)/\pi_\text{ref}(y|x))$,即 <strong>β × pointwise sequence log-density ratio</strong></li><li>⚠️ <strong>不是 KL 本身</strong>:只有当 $y\sim\pi_\theta$ 取期望时,$\mathbb{E}_{y\sim\pi_\theta}[\hat r_\theta(x,y)] = \beta\cdot\text{KL}(\pi_\theta(\cdot|x)\,\|\,\pi_\text{ref}(\cdot|x))$。<strong>DPO 训练时 $y_w, y_l$ 来自固定 preference 数据</strong>,所以这里的 $\hat r$ 不是 KL estimator,不是 KL margin</li><li>训练时 maximize $\hat{r}(y_w) - \hat{r}(y_l)$ ≡ pairwise log-ratio marginpreference 对的相对置信度),<strong>不是</strong> "KL margin"</li><li>KL anchor 是<strong>隐式</strong>的:通过 $\pi_\text{ref}$ 出现在 $\hat r$ 的分母带来 anchoring 效果——但显式 KL 不在 loss 里</li><li>对偶 RL 视角:DPO 反推自 KL-regularized 闭式最优 policy $\pi^* \propto \pi_\text{ref}\exp(r/\beta)$;隐式优化的目标是同一个 RLHF 目标,但 estimator 路径不同</li></ul>
<p>说 DPO 没有 KL(错,是隐式 anchor);或把 $\hat r$ 直接读作 KL / KL margin(错,需要 y~π_θ 期望条件)。</p>
</details>
<details>
<summary>Q9.Reward overoptimization 是什么?为什么发生?</summary>
<ul><li>Proxy rewardRM)随 KL 单调升,但 gold reward(人评)先升后降(<strong>inverted-U</strong></li><li>Gao, Schulman, Hilton 2023 ICML 给出 KL vs gold-reward 拟合形式</li><li>原因:RM 与 gold reward 不同(RM 是 finite-data 学的近似),policy 学到 RM 偏好但不一定是真实质量</li><li>缓解:KL budget early stop / RM ensemble / PRM / mix DPO + PPO</li></ul>
<p>只说"过拟合"——太笼统;不知道 KL 是 over-optimization 的 axis。</p>
</details>
<details>
<summary>Q10.GRPO 为什么历史上用 k3 不用 k1?</summary>
<ul><li><strong>工程动机</strong>GRPO 把 KL 放 lossk3 的 <strong>value-estimator</strong> 性质(非负 + value-side unbiased + 低方差)让 KL 监控曲线直观</li><li><strong>k1-as-loss 不可行</strong>:直接对 $\log r = \log\pi_\theta - \log\pi_\text{ref}$ 反传时,$\nabla = \nabla\log\pi_\theta$,在 on-policy 期望下为 0<strong>不是</strong> reverse-KL gradient。k1 必须<strong>进 reward / advantage</strong>(作为 detached scalar 走 score-function trick)才能给出严格的 reverse-KL gradient。把 k1 当 loss 项加既数值上可负不好看,gradient 也错</li><li><strong>k3-as-loss 的真实代价</strong>:对 θ 反传的 gradient 是 reverse-KL gradient 的 <strong>first-order Taylor approximation</strong>$1 - e^{-\Delta} = \Delta - \tfrac12\Delta^2 + O(\Delta^3)$,有 $O(\Delta^2)$ bias(见 §3.6 + Rethinking KL arXiv 2510.01555</li><li><strong>Principled 替代</strong>on-policy 下 (P1) k1 in reward 或 (P2) <strong>k2 as loss</strong>$\tfrac12\Delta^2$$\nabla = \Delta\cdot\nabla\log\pi_\theta$gradient-equivalent to P1)都是严格 reverse-KL gradient</li><li><strong>历史 DeepSeekMath / DAPO / verl 默认 k3</strong> 是工程惯例,$\beta$ 锁得紧、$\Delta$ 很小时 bias 可忽略——但这是经验合理化,不是理论 principled</li></ul>
<p>只说 k3 "三优满足"不给 gradient bias caveat;不知道 (P2) k2-as-loss 是 P1 的 gradient-equivalent 替代。</p>
</details>
<h3 id="l2-进阶题10-题">L2 进阶题(10 题)</h3>
<details>
<summary>Q11.推导 k3 的无偏性。</summary>
<p>需要证 $\mathbb{E}_{y\sim\pi_\theta}[(\pi_\text{ref}/\pi_\theta) - \log(\pi_\text{ref}/\pi_\theta) - 1] = \text{KL}(\pi_\theta\|\pi_\text{ref})$。</p>
<ol><li>$\mathbb{E}_{\pi_\theta}[\pi_\text{ref}/\pi_\theta] = \sum_y \pi_\theta(y)\cdot\pi_\text{ref}(y)/\pi_\theta(y) = \sum_y\pi_\text{ref}(y) = 1$</li><li>$\mathbb{E}_{\pi_\theta}[-\log(\pi_\text{ref}/\pi_\theta)] = \mathbb{E}_{\pi_\theta}[\log(\pi_\theta/\pi_\text{ref})] = \text{KL}(\pi_\theta\|\pi_\text{ref})$</li><li>合并:$\mathbb{E}[\widehat{\text{KL}}_3] = 1 + \text{KL} - 1 = \text{KL}$ ✓</li></ol>
<p>关键:用 $\sum_y\pi_\text{ref} = 1$。如果你忘了 $\pi_\text{ref}/\pi_\theta$ 这一项是 expectation 1 的 control variate,证不出无偏。</p>
</details>
<details>
<summary>Q12.从 $f(x) = e^x - x - 1$ 推导 k3 estimator。</summary>
<p>构造性证明:</p>
<ol><li>$f(x) = e^x - x - 1$ 在 $\mathbb{R}$ 非负(凸函数 $e^x$ 在 $x = 0$ 切线 $1 + x$ 之上)。</li><li><p>取 $x = \log(\pi_\text{ref}(y)/\pi_\theta(y)) = -\log r$</p>
<ul><li>$e^{-\log r} = 1/r = \pi_\text{ref}/\pi_\theta$</li><li>$-(-\log r) = \log r = \log(\pi_\theta/\pi_\text{ref})$</li><li>$f(-\log r) = \pi_\text{ref}/\pi_\theta - \log(\pi_\text{ref}/\pi_\theta) - 1 = e^\Delta - \Delta - 1$$\Delta = -\log r$</li></ul></li><li>期望:$\mathbb{E}_{\pi_\theta}[f(-\log r)] = \text{KL}$(已在 Q11 证)。</li></ol>
<p>所以 k3 = $f(\log p/q)$ 的特殊形式,恰好满足"非负 + 无偏 + 含 control variate" 三个性质。</p>
<p>只写公式不解释 $f$ 的构造动机;或不知道凸函数切线 → 非负。</p>
</details>
<details>
<summary>Q13.推 BT preference 下 KL-regularized RL 的闭式最优 policy。</summary>
<p>目标:$\max_\pi \mathbb{E}_{y\sim\pi}[r(x,y)] - \beta\,\text{KL}(\pi\|\pi_\text{ref})$。</p>
<ol><li>写 Lagrangian$\sum_y \pi r - \beta\sum_y\pi\log(\pi/\pi_\text{ref}) - \mu(\sum_y\pi - 1)$</li><li>对 $\pi(y)$ 求偏导 = 0$r - \beta(\log(\pi/\pi_\text{ref}) + 1) - \mu = 0$</li><li>整理:$\log(\pi/\pi_\text{ref}) = (r - \mu - \beta)/\beta$</li><li>指数化:$\pi(y) = \pi_\text{ref}(y)\exp((r - \mu - \beta)/\beta)$</li><li>用 $\sum_y\pi = 1$ 解 $\mu$$e^{(\mu+\beta)/\beta} = \sum_y\pi_\text{ref}\exp(r/\beta) = Z$</li><li>得:$\pi^*(y|x) = \pi_\text{ref}(y|x)\exp(r/\beta)/Z(x)$</li></ol>
<p>注意:$J$ 在 $\pi$ 上严格凹,最优唯一。</p>
<p>漏 normalization 约束;漏 strict concavity argument;或把 sign 搞反。</p>
</details>
<details>
<summary>Q14.推 DPO loss 从 §6.1 的闭式 $\pi^*$ 开始。</summary>
<ol><li>§6.1 给 $\pi^*(y|x) = \pi_\text{ref}\exp(r/\beta)/Z(x)$</li><li>反解 $r(x,y) = \beta\log(\pi^*/\pi_\text{ref}) + \beta\log Z(x)$</li><li>Bradley-Terry: $P(y_w \succ y_l) = \sigma(r_w - r_l)$</li><li>关键观察:$\beta\log Z(x)$ 不依赖 $y$<strong>在 $r_w - r_l$ 差里消掉</strong> $r_w - r_l = \beta\log(\pi^*(y_w)/\pi_\text{ref}(y_w)) - \beta\log(\pi^*(y_l)/\pi_\text{ref}(y_l))$</li><li>把 $\pi^*$ 改为可学 $\pi_\theta$,对偏好数据做 NLL $\mathcal{L}_\text{DPO} = -\mathbb{E}\log\sigma(\beta\log(\pi_\theta(y_w)/\pi_\text{ref}(y_w)) - \beta\log(\pi_\theta(y_l)/\pi_\text{ref}(y_l)))$</li></ol>
<p>关键 trick<strong>$\log Z$ 不依赖 $y$</strong>,所以在 pairwise 差里抵消(这是 DPO 不需要采样的根本原因)。</p>
<p>不解释 $\log Z$ 为什么消掉;或不知道 BT 的 sigmoid。</p>
</details>
<details>
<summary>Q15.推 DPO 梯度。</summary>
<p>记 $h_\theta = \beta\log(\pi_\theta(y_w)/\pi_\text{ref}(y_w)) - \beta\log(\pi_\theta(y_l)/\pi_\text{ref}(y_l))$implicit reward margin)。</p>
<p>$\mathcal{L}_\text{DPO} = -\mathbb{E}\log\sigma(h_\theta)$$\nabla = -\mathbb{E}\sigma'(h_\theta)/\sigma(h_\theta) \cdot \nabla h_\theta$。</p>
<p>用 $\sigma'(x) = \sigma(x)\sigma(-x)$$\sigma'(h)/\sigma(h) = \sigma(-h) = \sigma(\hat{r}_l - \hat{r}_w)$(即"错位置信度")。</p>
<p>$\nabla h_\theta = \beta(\nabla\log\pi_\theta(y_w) - \nabla\log\pi_\theta(y_l))$$\pi_\text{ref}$ 是常数,求 $\theta$ 导为 0)。</p>
<p>合并:</p>
<p>$$\nabla\mathcal{L}_\text{DPO} = -\beta\mathbb{E}[\sigma(\hat{r}_l - \hat{r}_w)(\nabla\log\pi_\theta(y_w) - \nabla\log\pi_\theta(y_l))]$$</p>
<p>解读:</p>
<ul><li>系数 $\sigma(\hat{r}_l - \hat{r}_w)$ 是 "当前 model 多大程度上错把 $y_l$ 排在前面" → hard-example mining</li><li>后面就是提升 $y_w$ 概率 + 降低 $y_l$ 概率</li></ul>
<p>少推一步 sigmoid' 公式;或不知道 $\sigma'(x) = \sigma(x)\sigma(-x)$。</p>
</details>
<details>
<summary>Q16.k2 estimator 为什么有偏?小 KL 极限下偏多少?</summary>
<p>记 $r = \pi_\theta/\pi_\text{ref}$$y \sim \pi_\theta$$\text{KL}(\pi_\theta\|\pi_\text{ref}) = \mathbb{E}_{\pi_\theta}[\log r]$。</p>
<ul><li><strong>k2</strong> 定义 $\mathbb{E}_{\pi_\theta}[\tfrac12(\log r)^2]$,一般 $\ne \mathbb{E}[\log r]$ — 所以<strong>有偏</strong></li><li><strong>正确的 Taylor 展开</strong> 要用 $s = \pi_\text{ref}/\pi_\theta = 1/r$(这是 $\mathbb{E}_{\pi_\theta}[s] = 1$ 的随机变量,可做 mean-1 展开)。$\log r = -\log s$$\log s = (s-1) - \tfrac12 (s-1)^2 + O((s-1)^3)$。</li><li>$\mathbb{E}_{\pi_\theta}[\log r] = -\mathbb{E}[\log s] = -\mathbb{E}[s-1] + \tfrac12\mathbb{E}[(s-1)^2] + O(\cdot) = 0 + \tfrac12\mathrm{Var}(s) + O$. 这与 Fisher 二阶展开一致。</li><li>$\mathbb{E}_{\pi_\theta}[\tfrac12 (\log r)^2] = \tfrac12\mathbb{E}[(\log s)^2] = \tfrac12\mathbb{E}[(s-1)^2] + O((s-1)^3) = \tfrac12\mathrm{Var}(s) + O$.</li><li>所以<strong>小 KL(即 $r\approx 1$)极限下</strong>$\mathbb{E}[k_2] \approx \mathbb{E}[\log r] = \text{KL}$,二阶等价。</li><li>大 KL 下 k2 系统性偏离 KL(高阶项不可忽略,方向取决于分布的高阶矩)。</li></ul>
<p><strong>关键修正</strong>:旧版本写 "$\mathbb{E}[r-1] = 0$" 是错的——在 $y\sim\pi_\theta$ 下 $\mathbb{E}[r] = \mathbb{E}_{\pi_\theta}[\pi_\theta/\pi_\text{ref}]$ 一般 $\ne 1$。$\mathbb{E}[s] = 1$ 才是正确的恒等式(这是 importance sampling 的标准结果)。</p>
<p>只说"二阶近似";不展开 Taylor,或者错用 $r$ 而非 $s$ 做 mean-1 展开。</p>
</details>
<details>
<summary>Q17.Adaptive β 与 PID controller 的类比?</summary>
<ul><li>Adaptive β(PPO Schulman 2017)只用 P 项:若 KL &gt; target → β ↑;若 KL &lt; target → β ↓</li><li>对比 PID controller$u(t) = K_p e + K_i\int e + K_d \dot{e}$</li><li>P 项 = 当前误差比例响应</li><li>I 项 = 累积误差(防 steady-state error),但 KL 是 stochastic,加 I 容易振荡</li><li>D 项 = 误差变化率(damping),但 KL 估计本身高方差,D 容易放大噪声</li><li>工程实践:<strong>只用 P 项</strong>最 robustTRL 默认);某些 framework 加 small I 项做长期收敛</li></ul>
<p>只说 "类似 P controller" 不展开;或加上 D 项不知会出问题。</p>
</details>
<details>
<summary>Q18.GRPO 的 k3 KL 在 reward 是 binary (0/1) 时怎么调 β?</summary>
<ul><li>Reward = {0, 1}advantage scale ≈ O(1)</li><li>KL_k3 per-token 初始 ≈ 0policy 与 ref 相同),训练中可达 0.1 ~ 0.5</li><li>若 β = 0.04KL penalty per-token ≈ 0.04 × 0.3 ≈ 0.012,与 advantage 比合理</li><li>若 β = 1KL penalty per-token ≈ 0.3<strong>远大于</strong> advantageloss 被 KL 主导</li><li>经验:数学任务起始 β = 0.01 ~ 0.04,看 KL 曲线调;DAPO 经常 β = 1e-3 或 0</li><li>对比 RLHF helpfulness 任务:reward scale 大(连续 [-5, 5])→ β 可以大些(0.1 ~ 0.5)</li></ul>
<p>不知 β 与 reward scale 的耦合;或机械套 β = 0.04。</p>
</details>
<details>
<summary>Q19.SimPO 没有 reference model,为什么还能 work?没了 KL anchor 不是会 reward hack 吗?</summary>
<ul><li>SimPO 用 <strong>length-normalization</strong> $r = (\beta/|y|)\log\pi(y)$ + <strong>target reward margin</strong> $\gamma$</li><li>没有 KL anchor,但 length-norm 阻止 "$y_w$ 越长越优" 的退化</li><li>Margin $\gamma$ 让 loss 在 $r_w - r_l > \gamma$ 时 saturate,避免 implicit reward 无界</li><li>实测某些 benchmarkAlpacaEval-2 / Arena-HardSimPO 优于 DPO</li><li><strong>没有 KL anchor 的代价</strong>OOD 鲁棒性差、对 $\beta, \gamma$ 调参敏感、生成长度可能仍然偏大</li><li>实际生产中 DPO + small β 仍然主流,SimPO 是 "在某些 benchmark 上更强但 trade off 不同" 的选择</li></ul>
<p>说 SimPO 一定更好;或不知道 length-norm + margin 是 KL 的替代。</p>
</details>
<details>
<summary>Q20.Per-token KL 和 sequence-level KL 是什么关系?</summary>
<ul><li>由 KL 的<strong>链式法则</strong>(条件分解): $\text{KL}(\pi_\theta(\cdot|x) \| \pi_\text{ref}(\cdot|x)) = \mathbb{E}_{y\sim\pi_\theta}[\sum_t \log(\pi_\theta(y_t|x,y_{<t})/\pi_\text{ref}(y_t|x,y_{<t}))]$</li><li><strong>sequence-level KL = token-level KL 之和的期望</strong></li><li>工程上只能 token-level 算(vocab 维度求和 OKsequence 维度组合爆炸)</li><li>实际写 RLHF lossper-token KL → mask assistant tokens → sum → average per sequence</li><li>注意:prompt token 上 policy 和 ref 输入相同,KL 应 = 0,但 floating-point 噪声会污染 → 必须 mask</li></ul>
<p>混淆两者;或不知道 mask only assistant tokens 的必要性。</p>
</details>
<h3 id="l3-顶级-lab-题5-题">L3 顶级 lab 题(5 题)</h3>
<details>
<summary>Q21.证明 $f(x) = e^x - x - 1 \ge 0$ 对所有 $x \in \mathbb{R}$。从该不等式出发,推导 k3 的非负性、无偏性。哪个性质对 "KL 作为 loss 加项" 更关键,为什么?</summary>
<p><strong>非负证明</strong></p>
<p>$f(x) = e^x - x - 1$。$f'(x) = e^x - 1$$f'(x) = 0$ ⟺ $x = 0$。$f''(x) = e^x > 0$$f$ 严格凸,$x = 0$ 是全局最小,$f(0) = 0$。所以 $f(x) \ge 0$ 对所有 $x$。✓</p>
<p><strong>k3 非负性</strong>:取 $x = \log(\pi_\text{ref}/\pi_\theta) = -\log r$,则 $\widehat{\text{KL}}_3 = f(-\log r) \ge 0$ 总成立。✓</p>
<p><strong>k3 无偏性</strong></p>
<p>$\mathbb{E}_{\pi_\theta}[\widehat{\text{KL}}_3] = \mathbb{E}_{\pi_\theta}[e^{-\log r}] + \mathbb{E}_{\pi_\theta}[\log r] - 1 = 1 + \text{KL} - 1 = \text{KL}$ ✓</p>
<p><strong>哪个性质对 loss 加项更关键?</strong></p>
<ul><li><strong>非负 + value-side 无偏</strong>:这些是好的<strong>监控/数值显示</strong>性质——KL loss 曲线不会出现负值或大幅噪声。但 <strong>k3-as-loss 的关键问题不在数值层</strong>,而在 gradient 层。</li><li>⚠️ <strong>k3 作为 loss 反传时的 gradient 是 reverse-KL gradient 的 first-order Taylor approximation</strong>$\nabla(e^{-\Delta} + \Delta - 1) = (1-e^{-\Delta})\nabla\Delta = (\Delta - \tfrac12\Delta^2 + O(\Delta^3))\,\nabla\log\pi_\theta$,有 $O(\Delta^2)$ bias(见 §3.6 + Rethinking KL arXiv 2510.01555)。</li><li><strong>真正 principled 的 loss 选择是 (P2) k2-as-loss</strong>$\nabla(\tfrac12\Delta^2) = \Delta\,\nabla\log\pi_\theta$ 在 on-policy 期望下等于严格 reverse-KL gradient。k2 数值未 calibrated 但 gradient 正确,与 k1-in-reward gradient-equivalent。</li><li><strong>如果坚持要"非负 + 无偏 + 易监控"</strong> ⇒ k3 仍是最佳 <strong>value estimator</strong>;但要分清"value-side k3 monitor + loss-side k2/k1-in-reward gradient"这一组合,比 "k3-as-loss" 更 principled。</li></ul>
<p>所以 k3 在 <strong>value-monitoring 层面</strong>最方便(非负 + value-unbiased + 低方差)。但<strong>对于 "as loss addend" 的 principled 性,关键不是非负,而是 loss-gradient 是否匹配真实 reverse-KL gradient</strong>——k3-as-loss 的 gradient $(1 - e^{-\Delta})\nabla\log\pi_\theta$ 只是 first-order Taylor approximation,有 $O(\Delta^2)$ biason-policy 下严格 principled 的 loss 是 (P2) k2-as-loss 或 (P1) k1-in-reward。GRPO/DAPO 历史用 k3 主要是工程惯例 + 小 β 时 bias 可忽略。</p>
<p><strong>易错</strong>:把非负当作 "loss addend 的 key" —— 那只是数值显示层面的优势;真正决定 principled 性的是 gradient correctness。理想组合是 "value-side k3 monitor + loss-side k2/k1-in-reward gradient"。</p>
</details>
<details>
<summary>Q22.推导 DPO 的 implicit reward 与 KL-regularized RL 的 policy gradient 之间的"对偶等价性"。</summary>
<p>设定:$\max_\pi \mathbb{E}_\pi[r] - \beta\,\text{KL}(\pi\|\pi_\text{ref})$,闭式解 $\pi^*(y|x) = \pi_\text{ref}\exp(r/\beta)/Z$。</p>
<p><strong>RL 视角</strong>:当 reward $r$ 给定时,最优 policy 通过 importance-weighted update 朝 $\pi^*$ 走。Score function policy gradient</p>
<p>$\nabla_\theta J = \mathbb{E}_{\pi_\theta}[\nabla\log\pi_\theta \cdot (r - \beta\log(\pi_\theta/\pi_\text{ref}))]$</p>
<p><strong>DPO 视角</strong>:把 $\pi$ 直接看作待学 $\pi_\theta$,用 BT 反解 implicit reward $\hat{r} = \beta\log(\pi_\theta/\pi_\text{ref}) + \beta\log Z$,对偏好对做 NLL。</p>
<p><strong>等价性</strong></p>
<ol><li>闭式解给出 $r = \beta\log(\pi^*/\pi_\text{ref}) + \beta\log Z$。</li><li>若 $\pi_\theta = \pi^*$(即 RL 已收敛),则 implicit reward 恢复真实 $r$up to additive $\beta\log Z$,但 $\log Z$ 在 BT pairwise 中抵消)。</li><li>RL 梯度 $\propto r - \beta\log(\pi_\theta/\pi_\text{ref})$,在收敛时 $= \beta\log Z(x)$(常数 in $y$)→ 梯度为零(PG 在 $\pi^*$ 处停)。</li><li>DPO 梯度 $\propto \sigma(\hat{r}_l - \hat{r}_w)(\nabla\log\pi(y_w) - \nabla\log\pi(y_l))$,在 $\pi_\theta = \pi^*$ 处对应"BT 模型 perfectly fits" → 梯度同步消失。</li><li>两个视角的固定点(fixed point)都是 $\pi^*$,所以<strong>RL 和 DPO 都在 optimize 同一目标,只是从两个角度切入</strong>RL 是 forward optimization(直接 max $J$),DPO 是 inverse optimization(用偏好数据 fit BT 模型)。</li></ol>
<p><strong>关键</strong>DPO 不是 RL 的替代,是<strong>对同一目标的不同 reduction</strong>——RL 通过 sampling-based PGDPO 通过 closed-form + supervised learning。"DPO 没有 RL" 是误读。</p>
<p>只说"DPO 推 RL 闭式解"不展开 gradient 等价性;或不知道两者 fixed point 相同。</p>
</details>
<details>
<summary>Q23.从 $\sqrt{\text{KL}}$ 和 inverted-U gold curve 推 reward overoptimization 的"安全 KL budget"。</summary>
<p>Gao 2023 的 BoN gold reward 拟合:$R_g(d) = d(\alpha_g - \gamma_g d)$$d = \sqrt{\text{KL}}$。</p>
<p>求 peak$dR_g/dd = \alpha_g - 2\gamma_g d = 0$ → $d_\text{peak} = \alpha_g / (2\gamma_g)$。</p>
<p>对应 KL distance$\text{KL}_\text{peak} = d_\text{peak}^2 = \alpha_g^2 / (4\gamma_g^2)$。</p>
<p><strong>安全 budget</strong>:要在 peak 之前停下来。一般选 $\text{KL}_\text{stop} = 0.5 \cdot \text{KL}_\text{peak}$(留 50% safety margin)。</p>
<p><strong>怎么估 $\alpha_g, \gamma_g$</strong> 需要 gold reward 信号(人工 / 强 RM ensemble)。在小规模 pilot run 跑几个 KL 点,拟合 $R_g(d)$。</p>
<p><strong>RM 越大,越靠右</strong>Gao 2023 给的 scaling law 表明 $\alpha_g, \gamma_g$ 随 RM size 改变(拟合系数本身依赖于 RM 规模和数据),更大 RM 的 $\text{KL}_\text{peak}$ 更靠右,但 $R_g(\text{peak})$ 也更高。这是为什么大 RM 既"对得起 budget" 又能拿更高 gold。</p>
<p><strong>PPO 比 BoN 复杂一点</strong>$R_g(d) = d(\alpha_g - \gamma_g d) - \delta_g d^{3/2}$,三阶项使 peak 稍微靠左。</p>
<p>应用:实际工程里把 measured KL 限制在 $\text{KL}_\text{peak} \cdot 0.5$ 作 early stop,即 "$\sqrt{\text{KL}}$ &lt; $d_\text{peak}/2$"。</p>
<p>不展开 derivative;或不知 RM size 与 peak 的 scaling。</p>
</details>
<details>
<summary>Q24.如果让你设计一个 RLHF 算法,把 reverse + forward KL 联合用,会怎么用?</summary>
<p><strong>动机</strong>(按标准约定:reverse = $\text{KL}(q\|p)$ mode-seekingforward = $\text{KL}(p\|q)$ mass-covering):</p>
<ul><li><strong>Reverse KL</strong> $\text{KL}(\pi_\theta\|\pi_\text{ref})$ = mode-seeking on $\pi_\theta$ → 选 ref 高密度区里 reward 高的 mode(合规则)。<strong>RLHF 默认就用这条</strong></li><li><strong>Forward KL</strong> $\text{KL}(\pi_\text{ref}\|\pi_\theta)$ = mass-covering on $\pi_\theta$ → 让 $\pi_\theta$ 覆盖 ref 的所有可能输出(防 mode collapse)。</li></ul>
<p><strong>问题</strong>forward KL 需要从 $\pi_\text{ref}$ 采样,工程上没意义(要训的是 $\pi_\theta$ 不是 $\pi_\text{ref}$)。</p>
<p><strong>绕路方案 (theoretical)</strong></p>
<ol><li><strong>JSD-style combo</strong>:用 $\text{JS}(\pi_\theta\|\pi_\text{ref}) = \tfrac{1}{2}\text{KL}(\pi_\theta\|m) + \tfrac{1}{2}\text{KL}(\pi_\text{ref}\|m)$$m = (\pi_\theta + \pi_\text{ref})/2$。对称、有界,可同时拿 mode-seeking 和 mass-covering。问题:$m$ 不是闭式(mixture distribution),梯度计算复杂。</li><li><strong>Importance sampling</strong>:从 $\pi_\theta$ 采样,但 reweight 成 $\pi_\text{ref}$ 期望:$\mathbb{E}_{\pi_\theta}[(\pi_\text{ref}/\pi_\theta)\log(\pi_\text{ref}/\pi_\theta)] = \text{KL}(\pi_\text{ref}\|\pi_\theta)$。问题:tail 上 $\pi_\text{ref}/\pi_\theta$ 极大,方差炸。</li><li><strong>Symmetric KL</strong>$\text{KL}_\text{sym} = \tfrac{1}{2}(\text{KL}(\pi_\theta\|\pi_\text{ref}) + \text{KL}(\pi_\text{ref}\|\pi_\theta))$,对称但同样需要 forward 一侧的估计。</li><li><strong>Hybrid penalty</strong>:训练前期主要 reverse KL(让 policy 朝 mode 收)+ 后期加 small forward KL term 用 importance sampling 估,限制 mode collapse。</li></ol>
<p><strong>实际工业方案(更简单)</strong></p>
<ul><li>用 entropy bonus 替代 forward KL 的 "mass coverage" 目标——entropy 不需要 ref 采样。</li><li>用 ensemble policy 训练,多个 policy 各自 mode-seek 不同 mode,整体保持多样性。</li><li>用 BoN inference + DPO/PPO training 组合:训练时 mode-seek,推理时多样性来源于 BoN 采样。</li></ul>
<p><strong>总结</strong>forward KL 在 RLHF 里"理论吸引但工程难",主流做法是用 entropy / multiple policies 替代。</p>
<p>只说"两个都加上"——太天真,要给出工程方案;不知道 forward KL 的 sampling 障碍。</p>
</details>
<details>
<summary>Q25.下一代 RLHF 算法可能怎么改进 KL regularization?给 3 个方向 + trade-off。</summary>
<p><strong>方向 1Adaptive KL estimator per token</strong></p>
<ul><li>对每 token 单独决定用 k1 还是 k3:小 KL token 用 k1(无偏 + 简单),大 KL token 用 k3(防方差爆炸)。</li><li>Trade-off:实现复杂度 + per-token 阈值难定。</li></ul>
<p><strong>方向 2Per-task β controller</strong></p>
<ul><li>不同 sub-task(数学 / 代码 / 对话 / safety)用不同 β,由 task classifier 在线分发。</li><li>Trade-off:要求 task labels 准确;β 之间的 cross-task 干扰需要研究。</li></ul>
<p><strong>方向 3Adversarial KL</strong></p>
<ul><li>不固定 $\pi_\text{ref}$,让 $\pi_\text{ref}$ 也在线学(如 self-rewarding LM、iterative DPO),但每轮固定一个时间窗内的 $\pi_\text{ref}$。</li><li>Trade-off:可能 unstableGAN-like);需要 fresh human label 防 drift。</li></ul>
<p><strong>方向 4Distributional reward + W2 KL</strong></p>
<ul><li>把 reward 也建模成分布 $p(r|x,y)$KL 用 Wasserstein-2 metricgeometric)替代。</li><li>Trade-offW2 计算复杂、需 sliced approximation;理论收敛性不清。</li></ul>
<p><strong>方向 5Hierarchical KL</strong></p>
<ul><li>句子级 KL + token 级 KL 联合:句子级控总 KL 预算,token 级做细粒度 anchoring。</li><li>类比:PRM (process reward) 之于 ORM (outcome reward)。</li><li>Trade-offsentence boundary 在生成时不显式,需要额外标注或 heuristics。</li></ul>
<p><strong>方向 6KL-free 但 trust-region 替代</strong></p>
<ul><li>完全去 KL,用 PPO clip 的 trust region 来约束("clip is enough")。</li><li>已有 IRL / SimPO 等尝试。</li><li>Trade-off:失去闭式 RL 数学基础(无 $\pi^* \propto \pi_\text{ref}\exp(r/\beta)$)。</li></ul>
<p>只罗列没 trade-off;或不知道 SimPO / IPO 已部分探索 KL-free 路线。</p>
</details>
<h2 id="a-附录参考文献清单">§A 附录:参考文献清单</h2>
<p>按章节分组。本节为草稿初版,<strong>arXiv ID 与精确发表场所未经在线核实</strong>——校验时应通过 <code>/arxiv</code> 或 codex web_search 重新查证。</p>
<p><strong>KL 基础与 estimators</strong></p>
<ul><li>Schulman 2020 blog <em>Approximating KL Divergence</em> <code>http://joschu.net/blog/kl-approx.html</code>k1 / k2 / k3 estimator 的标准来源)</li><li>Endres &amp; Schindelin 2003 IEEE TIT 49(7) <em>A New Metric for Probability Distributions</em>$\sqrt{\text{JS}}$ 是 metric 的证明)</li><li>Pinsker 1964(原始 Pinsker 不等式 $\text{TV} \le \sqrt{\text{KL}/2}$</li></ul>
<p><strong>RLHF / PPO</strong></p>
<ul><li>Schulman et al. 2017 arXiv 1707.06347 <em>Proximal Policy Optimization Algorithms</em>PPO-Clip + PPO-Penalty adaptive β)</li><li>Ouyang et al. 2022 NeurIPS <em>Training Language Models to Follow Instructions with Human Feedback</em>InstructGPTper-token KL in reward</li><li>Bai et al. 2022 Anthropic arXiv 2204.05862 <em>Training a Helpful and Harmless Assistant with RLHF</em>adaptive β controller</li></ul>
<p><strong>DPO 系</strong></p>
<ul><li>Rafailov et al. 2023 NeurIPS <em>Direct Preference Optimization: Your Language Model is Secretly a Reward Model</em>(闭式 + 反解 + BT</li><li>Azar et al. 2024 AISTATS <em>A General Theoretical Paradigm to Understand Learning from Human Preferences</em>IPO,防 deterministic preference 下 reward 无界)</li><li>Ethayarajh et al. 2024 ICML <em>KTO: Model Alignment as Prospect Theoretic Optimization</em>reference point 替代 KL</li><li>Meng et al. 2024 NeurIPS <em>SimPO: Simple Preference Optimization with a Reference-Free Reward</em>(去 reflength-norm + margin</li><li>Hong et al. 2024 EMNLP <em>ORPO: Monolithic Preference Optimization without Reference Model</em>odds-ratio 一阶段)</li></ul>
<p><strong>GRPO 系 / RL with k3 KL</strong></p>
<ul><li>Shao et al. 2024 arXiv 2402.03300 <em>DeepSeekMath: Pushing the Limits of Mathematical Reasoning</em>GRPO 首次系统使用 k3 + group-relative advantage</li><li>DeepSeek-AI 2025 arXiv 2501.12948 <em>DeepSeek-R1</em>GRPO + rule-based reward + emergent CoT</li><li>Yu et al. 2025 ByteDance arXiv 2503.14476 <em>DAPO: An Open-Source LLM Reinforcement Learning System at Scale</em>clip-higher + dynamic sampling + token-level loss + 小 β)</li></ul>
<p><strong>Reward Overoptimization</strong></p>
<ul><li>Gao, Schulman, Hilton 2023 ICML <em>Scaling Laws for Reward Model Overoptimization</em>KL distance vs gold reward 的 inverted-U + 拟合 form</li><li>Coste et al. 2024 ICLR <em>Reward Model Ensembles Help Mitigate Overoptimization</em></li><li>Eisenstein et al. 2024 COLM (arXiv 2312.09244, 2023) <em>Helping or Herding? Reward Model Ensembles Mitigate but do not Eliminate Reward Hacking</em></li></ul>
<p><strong>Critic-free RL(与 KL 放置相关)</strong></p>
<ul><li>Ahmadian et al. 2024 ACL <em>Back to Basics: Revisiting REINFORCE Style Optimization</em>RLOOleave-one-out baselineKL in reward</li><li>Li et al. 2024 ICML <em>ReMax: A Simple, Effective, and Efficient Reinforcement Learning Method</em></li></ul>
<p><strong>两篇 2024-2026 KL-in-RLHF 系统分析论文(已核验 arXiv 元数据)</strong></p>
<ul><li>Kezhao Liu et al., <em>Rethinking KL Regularization in RLHF: From Value Estimation to Gradient Optimization</em>, arXiv 2510.01555 (2025-10-02). 系统区分 KL value estimation vs gradient optimization;指出 k3-as-loss 是 biased first-order approximation;推荐 (P1) k1 in reward 或 (P2) k2 as lossoff-policy 需 IS correction。本教程 §3.6 内容基于该论文。</li><li>Vedant Shah et al., <em>A Comedy of Estimators: On KL Regularization in RL Training of LLMs</em>, arXiv 2512.21852 (2025-12-26, v3 2026-03-18). 实证对比 k1/k2/k3 在多种 RL 算法 + placement 组合上的 estimator bias / gradient bias / placement-effect;结论:不存在 universally 最好的 estimator。</li></ul>
<p><strong>Zhihu 中文资料</strong></p>
<ul><li><code>https://zhuanlan.zhihu.com/p/1979720260128118305</code><em>KL 进阶:Forward KL、Reverse KL、KL 估计与应用</em>(已核验,主题与 RLHF KL estimator 一致)</li><li><code>https://zhuanlan.zhihu.com/p/1892008158626546312</code> — [needs-verify URL accessibility] 题目疑似涉及 k2-loss vs k3-loss / GRPO off-policy / clip_std;用户校验时若链接失效可替换。</li></ul>
<p><strong>与本文紧密相关的内部教程</strong></p>
<ul><li><code>docs/tutorials/rlhf_dpo_grpo_ppo_tutorial.md</code> — RLHF / DPO / GRPO / PPO 总览(包含 BT + 闭式 + DPO 推导)</li><li><code>docs/tutorials/reasoning_models_tutorial.md</code> — Reasoning models 的 RL 训练细节</li><li><code>docs/tutorials/agentic_rl_tutorial.md</code> — Agentic setting 下的 token mask + KL 讨论</li></ul>
<footer class="aris-footer">
Generated by <a href="https://github.com/wanshuiyin/Auto-claude-code-research-in-sleep/blob/main/skills/render-html/SKILL.md">ARIS <code>/render-html</code></a> ·
source path <code>docs/tutorials/kl_divergence_rlhf_tutorial.md</code> ·
SHA256 <code>f0b8b5e62023</code> ·
generated at 2026-05-19 19:13 UTC.
This is a generated view — edit the source Markdown, then re-render.
</footer>
</main>
</div>
</body>
</html>