Veto 论文精读:让学生参与构造蒸馏目标,为什么有效、又有什么代价?
Veto 的核心操作很小:把教师概率乘以学生概率的 β 次幂,再归一化,用这个新分布监督学生。 学生当前几乎不相信的 token,会在新目标里受到抑制。它改变的是“这一步应该学成什么样”,不需要更改 Transformer 结构。
本文解读 Ijun Jang 等人的 Stable On-Policy Distillation through Adaptive Target Reformulation,依据 arXiv v3(2026 年 7 月 11 日),并对照官方实现。下面的三词示例、交互图和梯度核查是本文自行构造的教学分析,不是论文实验。
阅读时抓住三个问题:目标究竟如何变化?哪些梯度会被抑制?这种抑制会不会让学生更难学会自己原本不会的东西?
1. 背景:学生应该在自己的轨迹上接受指导
语言模型每生成一个 token,下一步的输入就变了。训练时始终读取标准答案前缀,推理时却要读取自己的输出,便可能遇到训练中少见的状态。
假设标准解法是“先算总价,再减折扣”,学生却先写了一个错误的中间数值。只训练标准解法,不一定能教会学生处理这个实际会出现的前缀。On-policy distillation(在策略蒸馏)让学生先生成,然后让教师在学生真正走到的前缀上提供下一词分布。
这里有两条独立的选择轴:
| 问题 | 可选方案 | Veto 主要改变什么? |
|---|---|---|
| 在哪些前缀上学习? | 固定数据、教师生成、学生生成、混合轨迹 | 主实验使用学生轨迹 |
| 在这些前缀上学习什么? | 教师分布、重构后的目标分布 | 把教师目标改成教师与学生的乘积 |
因此,Veto 可以放进已有 on-policy 训练循环。它不要求教师重写整条答案,也不自动纠正错误前缀;教师只是评估给定前缀下的下一词。论文方法与背景
2. 方法:把目标分布拆成四个可检查的步骤
固定一个学生生成的前缀,词表中第 \(i\) 个 token 的教师概率和学生概率分别记为:
\[ t_i=P_T(i\mid x,y_{<k}),\qquad p_i=P_\theta(i\mid x,y_{<k}). \]
Veto 构造:
\[ w_i=t_i p_i^\beta,\qquad Z=\sum_j t_jp_j^\beta,\qquad q_i=\frac{w_i}{Z}. \]
它等价于:
\[ q=\operatorname{softmax}(\log t+\beta\log p). \]
这是 Product of Experts(专家乘积):先在每个 token 上相乘,再让整个词表的概率和恢复为 1。论文 §4.2
教师参数冻结。训练时需要教师打分,部署时只需要学生。
2.1 β 的含义:学生有多少“否决权”?
- \(\beta=0\):\(q=t\),退化成直接学习教师。
- \(\beta>0\):学生概率越小,相乘时受到的压低越强;随后还要归一化。
- \(\beta=1\):\(q\propto tp\),并不等于学生分布。
还要避免把它写成 \(q=(1-\beta)t+\beta p\),或 \(q\propto t^{1-\beta}p^\beta\)。这些是不同的方法。Veto 的教师指数始终是 1,logits 相加后也没有额外除以 \(1+\beta\)。
因此,“教师与学生之间的桥梁”只能作直观比喻,不能理解为新概率一定落在二者之间。例如,当教师和学生已经一致,均为 \((0.7,0.2,0.1)\),设置 \(\beta=1\) 得到:
\[ q=\frac{(0.49,0.04,0.01)}{0.54}\approx(0.9074,0.0741,0.0185). \]
新目标比二者都更尖锐。它强调共同支持的 token,而不是做普通平均。
2.2 最容易漏掉的一行:detach
新目标需要使用当前学生概率,但在本次反向传播时,必须把目标看成常量。官方训练代码明确使用
shift_student_logps.detach() 构造目标。官方实现:目标构造
可把一个位置的 forward KL 写成以下教学代码:
1 | |
这是解释目标的最小片段,不是完整训练脚本;实际训练还需处理 token
对齐、prompt/padding mask
和损失归约。停止梯度只针对构造目标的那条学生分支,损失中的
log_p 仍然需要梯度。
如果让梯度穿过 \(q(p)\),优化的就是另一个复合函数,后面的梯度公式和 RL 解释不能原样照搬。
3. 完整数值推演:从概率到一次更新
设当前只有 A、B、C 三个候选 token。它们只是三个词表项,不代表完整答案,也没有预设“正确/错误”标签。
\[ t=(0.70,0.20,0.10),\qquad p=(0.01,0.49,0.50),\qquad\beta=0.5. \]
教师最看好 A,学生几乎不考虑 A。逐步计算:
| 计算步骤 | A | B | C |
|---|---|---|---|
| 教师 \(t\) | 0.7000 | 0.2000 | 0.1000 |
| 学生 \(p\) | 0.0100 | 0.4900 | 0.5000 |
| \(p^{0.5}\) | 0.1000 | 0.7000 | 0.7071 |
| 未归一化 \(w=t p^{0.5}\) | 0.0700 | 0.1400 | 0.07071 |
| \(q=w/0.280710678\) | 0.24937 | 0.49873 | 0.25190 |
现在以停止梯度的 \(q\) 为目标:
\[ L=\mathrm{KL}(q\Vert p)=\sum_iq_i\log\frac{q_i}{p_i}\approx0.63816. \]
令学生 logits 为 \(z\),\(p=\operatorname{softmax}(z)\),则:
\[ \frac{\partial L}{\partial z_i}=p_i-q_i. \]
| 目标 | A 的 logit 梯度 | B 的 logit 梯度 | C 的 logit 梯度 |
|---|---|---|---|
| 直接学习教师,\(\beta=0\) | −0.69000 | +0.29000 | +0.40000 |
| Veto,\(\beta=0.5\) | −0.23937 | −0.00873 | +0.24810 |
梯度下降减去梯度,因此负号表示该 logit 上升。Veto 仍提高 A,但力度明显减弱;B 的更新方向甚至发生了变化,因为归一化后的目标对 B 分配了更多质量。
为了把流程走完,暂时把三个 logits 当成直接可训练参数,取学习率 \(\eta=0.1\):
\[ z'=\log p-0.1(p-q),\qquad p'=\operatorname{softmax}(z')\approx(0.01036,0.49617,0.49346). \]
一次更新后,学生并不会立刻变成 \(q\)。真实模型还会通过共享网络参数影响其他前缀,因此这只是单位置的教学更新。本文用中心有限差分核对了上述停止梯度目标的 logit 梯度,最大绝对误差小于 \(2\times10^{-11}\)。
动手观察:拖动 β,谁受到抑制?
启用 JavaScript 后可拖动 β,观察目标和梯度。完整静态计算见上表。
横条范围均为 0–100%。显示的是固定前缀、完整三词词表的合成数据;拖动只重算目标,不会训练模型。梯度均对学生 logits 求导,并固定当前 q。
建议先把 β 拉到 0,再拉到 1,最后切换“学生已匹配教师”。后一个场景揭示了一个容易忽略的代价:即便学生已经学到教师,正 β 仍会推动它进一步变尖锐。
4. 为什么要衰减 β?固定点给出的直觉
如果教师保持不变、β 固定,且学生可以精确匹配每次目标,在理想固定点有:
\[ p_i^*=q_i(p^*)\quad\Longrightarrow\quad p_i^*\propto t_i^{\frac{1}{1-\beta}},\qquad 0\leq\beta<1. \]
例如 β 为 0.5 时,固定点正比于教师概率的平方。β 越接近 1,理想分布越偏向教师最高概率的 token。这是满足自洽条件的分布,不是深度网络必然收敛的证明。 参数共享、有限优化步、不断变化的前缀分布,都会偏离这个理想模型;β=1 也不能直接代入分母。论文附录 A.2
一种自然的训练策略是:早期使用学生信心过滤目标,随后逐步减弱过滤,最终接近原教师。官方代码的线性调度为:
\[ \beta_k=\beta_{\mathrm{start}}+ (\beta_{\mathrm{end}}-\beta_{\mathrm{start}})\frac{k}{N}, \qquad \beta_{\mathrm{end}}=0. \]
这里起始值始终固定。论文 Algorithm 1 把 β 写成循环内的原地乘法;若逐字实现,会变成逐轮累乘,而不是线性衰减。复现应对照官方调度函数。
从学习角度看,这是一种折中:过滤太弱,学生要承受完整教师目标;过滤太强或持续太久,学生原本不擅长的 token 可能一直得不到足够监督。β 并不是越大越好。
5. 与 RL 的联系:改变的是局部熵权重
换成 reverse KL:
\[ L_{\mathrm{rev}}=\mathrm{KL}(p\Vert q). \]
本次更新固定目标 \(q\)。在生成目标所用的当前学生参数处,其梯度可整理为:
\[ \nabla_\theta L_{\mathrm{rev}} =\mathbb E_{i\sim p}\left[ \nabla_\theta\log p_i \left((1-\beta)\log p_i-\log t_i\right) \right]. \]
常量项消失的原因是 \(\mathbb E_{i\sim p}[\nabla\log p_i]=0\)。这个局部下降方向,等价于上升以下代理目标的梯度:
\[ J=\mathbb E_{i\sim p}[\log t_i]+(1-\beta)H(p). \]
这里的“奖励”是 \(+\log t_i\),即教师越看好的 token 奖励越高;\(-\log t_i\) 是最小化形式中的代价。原文主定理中的 reward 标注容易混淆符号,阅读时应结合附录最后的优化方向。论文附录 A.3
| β | 熵系数 \(1-\beta\) | 局部直觉 |
|---|---|---|
| 0 | 1 | 标准 reverse KL 的教师偏好与熵平衡 |
| 0.5 | 0.5 | 降低熵权重,更偏向教师高概率项 |
| 1 | 0 | 去掉该代理目标中的显式熵奖励 |
这意味着:提高 β 本身并不意味着增加多样性,反而降低了上述熵项的权重。论文的“decisiveness”应理解为更集中、更果断。
也不要把这个公式等同于完整 agentic RL 系统:这里没有环境交互回报、工具执行结果或答案验证器奖励。这是固定前缀上的词表分布分析;它不包含对整条离散采样轨迹分布求导带来的所有项。公式形似策略梯度,不代表训练框架、信用分配和 rollout 管理就变成了同一件事。
6. 论文实验支持了什么?
主实验使用经过任务 SFT 的 Qwen2-7B-IT 教师与 Qwen2-0.5B-IT 学生,Veto 主表采用 forward KL。论文报告使用两张 80GB H100、训练三个 epoch;学生训练各任务约使用 1K 条样本。下面为论文 Table 2 的结果,数值单位均为百分比。实验设置与结果
| 方法 | GSM8K 准确率 | HumanEval Pass@1 | HumanEval Pass@10 | DialogSum 胜率 |
|---|---|---|---|---|
| Teacher SFT | 74.7 | 64.7 | 72.2 | 65.0 |
| Student SFT | 30.7 | 26.9 | 34.6 | 54.0 |
| Supervised KD | 33.4 | 26.8 | 34.5 | 54.3 |
| SKD | 33.6 | 24.8 | 34.8 | 53.6 |
| On-policy KD | 35.1 | 22.9 | 35.3 | 54.3 |
| Veto | 39.9 | 29.0 | 37.7 | 56.5 |
| 相对 On-policy KD 的绝对增益 | +4.8 | +6.1 | +2.4 | +2.2 |
最后一行是百分点,不是相对百分比。这些结果表明,目标重构在所测设置中改善了学生成绩;但不能读成小模型已经追平教师。例如 GSM8K 仍相差 34.8 个百分点。
另一个值得注意的现象是:普通 On-policy KD 的 HumanEval Pass@1 低于 Student SFT。这提醒我们,训练轨迹更贴近推理,并不自动保证效果更好。
DialogSum 使用 GPT-4o-mini 进行成对评判,不是人工正确率。官方评估脚本默认用 Qwen2-7B-Instruct 作为比较对象,并将平局记作半胜;实际复现需要核对对手模型及评判参数,不能把 56.5 理解成“击败其他所有基线的比例”。摘要评估代码
消融实验提供了两个补充:GSM8K 的 reverse KL 从 37.9 提升到 40.2;Gemma-2 9B→2B 的 on-policy 基线从 49.8 提升到 51.2,后者使用固定 β=0.3。它说明收益不局限于一组模型,但覆盖范围仍有限。不能将 reverse KL 的 40.2 与主表 forward KL 的设置混为一谈。论文 §5.5
7. 一个必须讲清的数学边界:哪种梯度“爆炸”?
以下是本文的独立核查,不是论文结论的照录。
论文把 forward KL 的不稳定性联系到 \(t_i/p_i\):学生概率趋近零时,这个比值确实可能很大。但判断梯度是否发散,必须说明对什么变量求导。
对概率坐标,固定教师目标的交叉熵部分满足:
\[ \frac{\partial L}{\partial p_i}=-\frac{t_i}{p_i}. \]
对实际 softmax logits,链式法则给出:
\[ \frac{\partial L}{\partial z_i}=p_i-t_i. \]
后者每个分量都在 \([-1,1]\) 内。因此,不能只凭概率分母趋近零,就断言标准 forward KL 的 logit 梯度必然爆炸。 参数梯度还包含网络的 Jacobian、序列聚合和数值实现等因素;这也不等于说整个训练必然稳定。
Veto 的停止梯度实现则有 \(\partial L/\partial z_i=p_i-q_i\)。它改变监督方向与强度,这在三词例子中可以直接看到;不需要依赖“普通 KL 的 logit 梯度发散”才能解释这个变化。
另一个细节是“损失项趋零”不等于“导数趋零”。对教学函数:
\[ f(p)=-p^\beta\log p, \qquad f'(p)=-p^{\beta-1}(\beta\log p+1). \]
即使 \(f(p)\to0\),当 \(0<\beta<1\) 时,\(f'(p)\) 仍可无界。这说明仅证明某个 token 的损失贡献趋零,不足以证明所有相关梯度稳定;上式也不能替代对完整、归一化、停止梯度训练目标的分析。
论文 Figure 2 展示 ignorant tokens 上的梯度量级差异,但图注没有明确它对概率、logits 还是模型参数求导。若要把这张图用作整体优化稳定性的依据,需要先补齐测量定义。官方训练同时使用梯度裁剪,归因实验也应控制这一因素。论文 §4.1 与附录 A.1
8. 从实现到复现:真正要检查的细节
先对齐目标,再比较效果。 复现 Veto 时,一行公式之外最重要的是下面几项。
| 检查点 | 为什么会影响结果 |
|---|---|
| 教师是否先做任务 SFT | 直接拿基础教师,监督信号就不同 |
| 相同前缀、相同 token 位置和词表 | 错位一格或词表不兼容,会让 KL 比较失去意义 |
| 目标分支是否停止梯度 | 决定实际优化的函数 |
| β 初始值、结束值与调度 | 决定过滤强度及持续时间 |
| prompt、padding mask 与归约 | 影响学习对象和不同长度样本的权重 |
| log-space 计算 | 避免直接计算小概率乘积造成下溢 |
| rollout 与教师打分的成本 | Veto 只简化目标修改,没有消除生成和教师前向 |
官方 README 推荐主实验从 β=0.8(数学)、1.0(代码)、0.3(摘要)线性衰减到 0。但仓库提交的 YAML 是特定运行配置:例如数学配置包含 β 起始值 1.2 和 reverse KL,摘要配置包含 β=0。照抄默认文件不等于复现主表。 应按 README 的任务推荐显式调整,并保存实际生效配置。官方复现说明
从 infra 角度,目标构造通常只是全词表张量上的逐元素操作和一次归一化。真正的大头仍是学生 rollout、教师前向以及学生反向。论文没有给出足够的吞吐、显存与端到端成本对照,因此不能仅凭公式简单,就宣布训练总成本显著下降。
9. 哪些后续实验最值得做?
首先,区分“优化更稳定”和“最终更准确”。在相同初始化、学习率、裁剪阈值与样本预算下,同时记录 loss、logit 梯度、裁剪前参数梯度、非有限数值次数和验证分数。这个测量成本主要是日志与重复运行,不需要更大模型。
其次,检查学生低概率项究竟是噪声还是能力缺口。按教师与学生分歧大小分桶,观察被抑制 token 后续是否学会,并比较恒定 β、线性衰减和 β=0。若低概率但关键的知识始终没学会,说明“否决权”也在妨碍迁移。这是本文建议的诊断,论文并未报告这一完整实验。
最后,把收益放进成本预算里衡量:固定生成 token 数或 GPU 小时,跨随机种子比较准确率、多样性与学习曲线,再逐步扩展到更长推理和工具使用任务。现有结果支持把 Veto 作为一种值得验证的蒸馏目标设计;它们尚不能证明它适用于所有规模、所有任务,也不能替代对失败样例的分析。
对学习者而言,最值得带走的是一个可复用的思考方法:训练目标也可以随学生能力变化,但必须同时检查目标的偏差、梯度流向和最终学习到的分布。 Veto 把这三件事集中在一个 β 参数上,因而是理解现代后训练的一个很好的具体例子。
参考资料
- Jang et al. Stable On-Policy Distillation through Adaptive Target Reformulation,arXiv v3。方法、实验、附录及理论陈述。
- 论文 PDF v3。用于核对图表与公式布局。
- 官方 Veto 实现,固定代码版本。本文核查了目标 detach、β 调度、配置与摘要评估口径,未重新运行大模型训练;数值教学例子与有限差分检查在本地完成。
点赞与评论
喜欢这篇文章?点个赞,或留下你的想法。登录 GitHub 后即可参与。
如果评论无法加载,请检查网络连接后刷新页面。