一个语言模型其实就是一个序列上的分布。Post-training 在做的事,是把这个分布往某个目标推。 SFT、RL、OPD 的差别,不在「学不学得到」,而在目标分布是什么,以及梯度被允许从哪儿出发。 nrehiew 这篇 blog 的核心论点是:真正承重的不是显式 KL 惩罚,而是「on-policy 数据」。
SFT 把模型拉向外部数据集,RL 沿当前策略上奖励最高的方向更新,OPD 用学生自己的样本但跟着教师的分布走。 前者会按整个分布均匀施力,因此容易把无关能力一起冲掉;后两者只在「模型自己访问过的区域」上动,自带一种隐式 KL 约束。
在最小代码编辑实验里,OPD 的两个学生(一个从 SFT 教师、一个从 RL 教师蒸馏)表现几乎一模一样, 甚至都略超过 RL 教师本身。说明真正在起作用的是"数据从学生分布采样"这一性质,而不是教师的好坏。 把 SFT / RL / OPD 并排看,on-policy 数据才是 post-training 真正的承重梁。
nrehiew 提出一个统一的视角:先别看损失函数长什么样,而是问「目标分布是什么?它有多直接?」 这一节先把这个模板立起来,后面的所有差异都可以套进它。
作者明确说这不是一个严谨的数学定义,更像一个有用的思考模板。在这个视角下: SFT 把当前分布拉向「数据集定义的那个分布」;RL 没有一个事先指定的外部分布, 但每一步都试图朝「期望奖励更高的方向」挪一点;OPD 介于两者之间 —— 样本由学生自己生成,但梯度让学生去匹配教师的分布。
模板里最关键的一个问题是 —— gradient 是从哪儿出发的? SFT 的梯度均匀地铺在外部数据集的 token 上,不管这些 token 是不是任务核心; RL 和 OPD 的梯度则只在模型当前访问的区域上动。这就是后面所有「为什么 RL 少遗忘」讨论的几何源头。
想象当前模型分布 π 是一条曲线,覆盖了它已经学到的所有能力(数学、代码、写作……不同的「山头」)。 训练 = 拿一只手去推这条曲线,让它的某个山头变高。
SFT 的手是直的,从外部按住目标 token,不管模型现在长什么样; RL 的手在曲线自己的高地里推,只动模型采得到的区域; OPD 的手也在曲线自己的高地里,但推力来自教师 logits 的形状,不是来自外部奖励。
读到这里要 get 到:算法的差别不在「学不学得到任务」,而在从哪推、推多远、付出什么代价。
把三种方法并排放在同一张图上对比。每张卡片同时回答三个问题: 「目标分布是谁定义的?数据是哪儿来的?梯度怎么被约束?」 切换 Tab 就可以一个一个看。
数据集在训练开始前就已经存在 —— 人写的、强模型生成的,都行。 然后用交叉熵让模型尽量贴近数据集的 token 分布。 起点是哪个分布完全不影响最终目标方向,因为 NLL 损失对起点不敏感。
这也是 SFT「灾难性遗忘」最自然的源头:数据集分布如果离原模型很远, 模型没有理由优先选「附近的解」,它只会被往示范 token 上拽。 梯度在整个分布上均匀施力,不区分 token 是任务关键的运算符,还是「therefore」「we can see that」这类风格 token。
没有一个外部的目标分布。模型自己生成轨迹,奖励函数打分,然后用 Policy Gradient 增加期望奖励。 梯度只能从「当前策略采得到的样本」上发出,所以更新天然集中在模型已经访问的高概率区域。
这种局部性正是 RL「不太遗忘」的物理来源。前提是奖励有意义 —— RLVR 有可验证奖励,奖励方向≈质量方向;RLHF 用奖励模型,方向更有偏,因此需要 KL 惩罚和 trust region 兜底。
OPD 是 SFT 和 RL 中间的那一档:像 SFT 那样有一个明确的「老师信号」,但像 RL 那样数据来自学生本身。 每一步先 on-policy 采样,再用 reverse KL 把学生的 logits 朝老师的 logits 拉。 粗略类比:RL 用 advantage 加权 completion,OPD 用「学生/老师 log ratio」加权。
一种新变体是 On-Policy Self Distillation (OPSD):教师 = 学生,但教师在算 log 概率时可以看到参考答案作为前缀。
因为两者本质同一个模型,大部分 token 上 KL 都很小;
真正张开的是 style / pivot token(如 wait / alright),这反而和任务核心不同步。
OPSD 用同一个模型当学生和老师,老师比学生多看到一个「参考答案前缀」。 作者做了 per-token KL 分析后发现:在所有 thinking 配置下,风格 token 的 KL 显著高于数学 token。 如果不加 clip,模型会被这些与任务无关的 token 过度拉扯,最终崩掉。
下面这两组是作者图示中的典型 token 类别。bar 长度按相对 KL 强度对照(论文里是相对量级)。 Style 这一侧远高于 Math 这一侧 —— 意味着如果朴素地走梯度,每一步更新都会被 style token 主导。
作者沿用前作的「最小代码编辑」任务:给模型一段被人为损坏的函数, 只允许修改 bug 相关的几行。SFT 教师泛化差、伤害通用代码能力;RL 教师泛化好、不掉 LCB。 作者本来以为 OPD 学生会跟教师一致 —— 结果完全不是。
| Model | Pass@1 ↑ | Norm. Levenshtein ↓ | Added CC ↓ | LiveCodeBench v6 ↑ |
|---|---|---|---|---|
| 教师 · Teachers | ||||
| SFT teacher | 0.775 | 0.450 | 0.450 | 0.286 |
| RL teacher | 0.792 | 0.063 | 0.206 | 0.320 |
| 学生 · On-Policy Distillation | ||||
| OPD · 从 SFT 教师蒸馏 | 0.800 | 0.059 | 0.206 | 0.297 |
| OPD · 从 RL 教师蒸馏 | 0.787 | 0.055 | 0.228 | 0.314 |
OPD-SFT(0.800 / 0.059 / 0.206)和 OPD-RL(0.787 / 0.055 / 0.228)的差距, 比两种教师之间的差距小一个量级。教师的好坏几乎被「on-policy 采样」这个步骤抹平了。
OPD-SFT 在 Pass@1 上 0.800 > 0.792,OPD-RL 的 Levenshtein 0.055 < 0.063。 这跟 Agarwal 等人在 GSM8K 上观察到的「学生超过老师」一致 —— OPD 的监督本身就比单纯模仿教师轨迹更针对学生的状态。
SFT 教师在 LCB 上 0.286(明显掉了),但从它蒸馏出来的 OPD 学生反而是 0.297, 甚至比教师还高。即使教师本身已经退化,学生也没有继承这份退化。结论:教师提供信号,状态分布属于学生。
关于「为什么 RL 比 SFT 少遗忘」,社区里至少有三种说法。 作者认为前两种都有一部分对,但都解释不清 OPD 的现象。 他真正相信的是第三种:on-policy 数据本身就是隐式 KL 约束。
SFT 的交叉熵在固定数据集上等价于最小化 forward KL;Chen et al. (2025) 证明 RL 可被看作 reverse KL 最小化。 forward KL 是 mode-covering,会牺牲已有的 mode 去覆盖新数据。
作者的批评:这论证依赖于显式 KL 惩罚。但实证上即便 KL 惩罚被弱化或去掉,RL 也仍然不太遗忘 —— 所以「KL 方向」不是真正的发动机。
每个示范 token 都被无差别推高概率 —— 不管是数学符号还是「therefore」。 Diao et al. 发现 SFT 上大量 token 都是低概率 + 低熵:模型本来很自信,却被迫去拟合一个发散的 ground-truth, 代价是冲掉现有的表示。
RL 有数据相关的隐式正则(Lai et al. 2025):方差大的样本组得到更小的 advantage; Mukherjee 等人观察到 RL 只更新了一个稀疏的子网络。
想象一个最朴素的 RL:REINFORCE + 0/1 奖励。这时奖励就是个 filter, 得到 reward = 1 的样本本质上和拒绝采样产生的样本一样。
把 RL 的目标定义为「所有 completion reward 都是 1 的最优策略」。 因为我们只从当前策略采样,所有可达的最优策略里,离我们最近的那一个就成了实际的训练目标。 每一步策略梯度,都把我们朝"最近的、可解的最优解"挪一点。
所有让任务做对的策略形成一个集合 P*。一般的 SFT 目标可以选 P* 里的任意一个 —— 哪怕它离当前 π 很远。 而 on-policy 训练,因为每一步只能从 π 自己里采样,能挪到的位置自然被局限在 π 的邻域。
所以训练过程倾向于走向「π 在 P* 中的最近投影 π*」。这就是 RL 不太遗忘的几何源头 —— 它不需要 KL 惩罚,采样过程本身已经把"可达范围"卡住了。
这也解释了为什么 OPD 从 SFT 教师蒸馏也能少遗忘:教师 logits 提供方向信号,但状态分布始终是学生的, 所以更新仍然被约束在学生附近的可达区域里。
实验里 OPD 学生在 Pass@1 上反超了 RL 教师本身。蒸馏一般不会超过老师,这事反直觉。 作者没给严格证明,但给了两条解释,并补一张曲线说明这件好事的代价是什么。
传统离线蒸馏只在教师自己生成的轨迹上学。问题是:学生真实犯的错,教师轨迹里可能根本没出现过 —— 等于没被监督到。
OPD 反过来:让学生先自己生成一段 prefix,教师在这段 prefix 上给意见。 监督直接发生在学生"真正会去的状态"上,所以错在哪、就被纠在哪。
先打个底:模型每生成一个 token,softmax 出来其实是覆盖整个词表的一张概率分布。我们平时看到的"老师输出 X"只是这张分布的最高峰(argmax)。下面三张图直接对比看:
普通 token 蒸馏只学最高那一根;OPD 用 reverse KL,让学生把整张分布对齐到老师 —— 老师在第二、第三峰各有多少概率、哪些位置老师其实自己就拿不准(多 bar 都不矮),学生统统学下来。
学生因此继承的是老师的判断力,不只是"答案"。所以哪怕老师采样出来的某个具体样本不算最佳(采样有运气成分),学生自己采样反而能更稳地落到分布里好的那部分 —— 这就是 Pass@1 反超老师的来源。
原文实测了 OPD 和 RL 训练全程的 reward / entropy 曲线,这是结论: RL 的 reward 平稳爬升、熵缓慢温和下降;OPD 的 reward 近乎阶跃地拉升,同一步上熵直接断崖崩塌到非常低的水平 —— 远低于 RL。
为什么 OPD 的熵反而比 RL 更低?因为 reverse KL 是 mode-seeking 的(Gu et al. 2023)—— 它要求学生的整张分布对齐老师,会主动把概率压到老师的少数几个峰值上,其它合理备选 token 的概率被压到接近 0。RL 哪怕弱化了 KL 约束,因为 on-policy 采样的"近优解"性质,分布形状本身没被那么剧烈地改写。
对应到指标:Pass@1 提升,但 Pass@k(k>1)和多样性会被 mode collapse 拖累。Pass@1 强 ≠ 全面更强,评估时要单独看多样性指标。
近一年开源 / 半开源模型逐渐收敛到一个范式:用 SFT 立基础格式,用 RL 在可验证领域里冲分, 最后用 OPD 把不同领域的「专家教师」融合到同一个学生里 —— 学生最后不再走 RL。 GLM 5、DeepSeek V4、MiMo-V2 Flash 都走这套。
| 领域 | 最佳教师训练方法 | 理由 |
|---|---|---|
| Math · Code | RL · RLVR | 有可验证奖励,方向无偏,正合 RL 长项 |
| Creative Writing | Self-Distillation | 奖励信号噪声大,用 LLM judge 反而是有偏代理 |
| Knowledge-heavy benchmarks | Distillation 系 | 同上 —— 知识题用 RL 反而容易跑偏 |
| BrowseComp 等开放任务 | SFT 等 | 这是少数几个最终合并模型反而弱于教师的领域 |
有趣的观察:在 RL 这一列上,最终合并模型几乎总是优于专家教师; 只有 self-distilled 专家所在的领域,合并模型可能反而退步。原因尚不明确,但本身就是 OPD 作为"承重梁"的一个反证。
Brown (2026) 提出 RL 之所以 Pareto-optimal,是因为在「capability ↑ vs KL 移动 ↑」这条曲线上很高效。 nrehiew 用 OPD 把这个框架补完:真正决定 KL 预算的是 on-policy 数据,而不是显式 KL 惩罚。 所以未来的最优算法,需要同时满足三个性质 —— 而目前任何已知方法都只占两个。
作者承认他不知道具体算法长什么样。但问题的形状是清楚的:每一根轴都解决一个已知的缺陷, 目前还没有任何一种已知方法把三根轴同时占满。
RLVR 的 outcome reward 一回合只给 O(1) bit 信息(Schulman et al. 2025)。 Logits 蒸馏密度高,但引入偏差。 未来算法需要密度,但代价不能是偏差。
RLVR 因为奖励可验证,偏差几乎为零。 OPD 教师 logits 是高偏代理,需要靠 clipping 兜底。 最佳算法应该在保持密度的同时把偏差压下去。
on-policy 数据是隐式 KL 约束的源头,避免了模型为了拟合遥远目标而摧毁原有能力。 RL 和 OPD 都有这一性质,它是承重梁。