这篇论文的标题里藏着一句很值得玩味的话:它在追问On-Policy 蒸馏到底是不是真的在“蒸馏”。如果按字面去读,问题可以转写成更直白的版本——学生模型在策略内采样的数据上训练,教师模型只是给这些数据提供了一个“看起来更聪明的标签”,那学生最终提升到底是来自教师教出来的知识,还是仅仅因为“在自己擅长或者更倾向的数据分布上多走了几步”?
OPSA 方法被放到这个问题的对立面来验证,核心卖点是无需监督。从论文标题的表述看,作者试图在没有真实参考答案、没有人工偏好标注的情况下,仍然得到一个可用的蒸馏目标。这篇博客不做论文翻译,而是把这篇论文最值得关注的问题拆开:On-Policy 蒸馏为什么会产生“虚假收益”;怎么设计一组实验把教师的知识迁移和学生的自我提升解耦;以及 OPSA 这类无需监督方法应该从哪个角度验证有效。如果你正在做小模型蒸馏、RL 调优、偏好对齐,或者看到训练 loss 在下降但说不清模型到底学到了什么,这篇内容可以直接收藏。
先说结论性判断:别急着把任何“学生 loss 降得很好”的报告当成蒸馏有效的证据。更稳妥的工作习惯是建立三个控制变量——数据分布、教师参与方式、外部监督信号。本文会带你完成一套最小验证流程,并给出一套可以复用的 OPSA 实验框架。正文里的所有代码均为通用模板,不是论文官方开源代码,使用前需要替换成你自己的模型、数据集和 loss 实现。
1. 主题速览:On-Policy 蒸馏与 OPSA 要回答什么问题
| 维度 | 内容 |
|---|---|
| 研究对象 | On-Policy 蒸馏方法是否真的发生了“知识迁移” |
| 提出方法 | OPSA,从关键词看是一种无需外部监督的蒸馏/自蒸馏方案 |
| 核心矛盾 | 教师标签带来的提升,可能被学生自身分布变化掩盖 |
| 关键词 | On-Policy、知识蒸馏、OPSA、无需监督、模型蒸馏 |
| 目标读者 | 训练小模型、做蒸馏、做 RL 调优、研究模型能力迁移的工程师和研究者 |
| 复现重点 | 解耦教师信号、采样分布、监督信号三个变量 |
| 本文属性 | 论文思路拆解 + 通用实验框架,不是论文原文翻译 |
这里先做一个概念提醒:最近经常会看到“蒸馏一本书”“怎么蒸馏 skill”“模型蒸馏”这几种说法,它们并不完全一样。把一本开源书“蒸馏”成知识密度更高的小册子,指的是文本压缩或者语料整理;普通人所说的“蒸馏 skill”,更像是让模型从长上下文或示例里提炼技能。而本文讨论的知识蒸馏,定义要严格得多:把一个大模型(教师)的知识迁移到一个小模型(学生),让学生在小参数量下逼近教师的能力表达。On-Policy 蒸馏和 OPSA 都建立在这个定义之上。
表格里没有写“OPSA 全称”和“论文作者/机构”,因为当前材料没有给出这些信息。读者在精读原文时应先定位两个东西:Algorithm 1 的伪代码,和损失函数那一节的公式。它们能确认 OPSA 到底从哪获得训练信号,这是全文最关键的一步。
2. 知识蒸馏到底“蒸馏”什么:先厘清 On-Policy 的位置
传统知识蒸馏的全流程一般是离线模式:准备一个大规模静态数据集,让教师模型对每条样本输出软标签,也就是各类别的概率分布,然后让学生模型在这组固定软标签上学习。这种做法的优点是稳定、开销低、容易复现;缺点也很明显——如果学生模型的生成分布与静态数据分布不一致,学生学到的东西可能和自己的解码策略对不上。
On-Policy 蒸馏把强化学习里的“在线采样”概念引入知识蒸馏。每一步训练不是从固定数据集里读样本,而是先让学生模型在当前策略下采样一批输出,再让教师模型对这批学生生成的结果打标签。这样做的好处是数据的分布永远贴近学生当前状态,学生学到的目标更“当下”;坏处是训练过程变成在线采样,数据分布每一轮都在变,实验结果的可解释性明显下降。
这时候就有了标题里的致命问题:学生提升,是教师给的知识在起作用,还是当前策略采样带来的分布变化在起作用?
用因果关系拆开看,On-Policy 蒸馏的收益至少可以来自三个地方:
第一,教师软标签提供了比 one-hot 标签更丰富的类别关系。例如在分类任务里,教师会说“猫”和“虎”的相似度高于“猫”和“汽车”,这种结构化信息确实算知识迁移。
第二,学生从当前策略采样,实际上是一种自举。模型在训练中会越来越多地采样到自己已经偏好的区域,哪怕没有教师,只用学生自己的 softmax 做平滑处理,也可能获得稳定训练、降低方差的收益。
第三,教师如果给的不是 softmax 概率,而是偏好评分或者是否被接受的标签,学生学到的东西更接近奖励信号下的策略优化,而不是“蒸馏”出的知识。很多论文把第三种也叫做蒸馏,但在机制分析里必须区分开:前者是被教出来的能力,后者是被迫压缩或调优出来的结果。
所以 On-Policy 蒸馏“是不是真在蒸馏”,本质上是在问:把第一部分的贡献从第二、第三部分里分离出来后,教师独有知识贡献还有多少?很多实验设计没有做这种分离,自然就出现了“教师有没有都一样涨点”的结论。
正是因为这个原因,OPSA 才值得研究。它想表达的路径可能是:如果我能证明一个完全不需要外部监督信号、甚至不需要教师参与打分的过程也能达到类似效果,那基本可以反推——原来的 On-Policy 蒸馏,很大概率只是在利用“在线采样 + 自适应分布”的增益,而不是真正发生了知识迁移。
3. 为什么 On-Policy 蒸馏可能“没在蒸馏”:三个机制解释
3.1 同源师生带来的“自我兜底”
On-Policy 蒸馏里最常见的设计是教师和学生共用底模,或者教师本身就是学生的一个更大版本。这种同源结构天然存在一个风险:教师和学生错误模式高度相似。学生在某个位置出现过错误倾向,教师在大模型的参数空间里也会表现出相似倾向,教师给的标签没有提供足够多的“反事实”知识。此时学生学到的东西更像是“顺着自己已经会走的路径再走了一遍”,只是这条路径被写得更光滑了。
如果把教师换成词表不同、架构不同、训练数据来源差异很大的另一个模型,再用同样流程做蒸馏,你能明显看到结果发生变化。同源教师很容易让学生获得平滑收益,却很难带来真正的跨架构知识迁移。设计复现实验时,第一组对照组就应该是“不同源教师 + On-Policy”,否则无法定位差异来源。
3.2 教师信号与学生自身分布的耦合
在线采样让教师和学生面对的数据每一轮都不同,每次参数更新都会影响下一轮采样数据,数据和参数之间形成闭环。这会带来一个统计陷阱:即便教师不参与优化,学生只对自己的输出做 low-confidence 惩罚,也可能会出现指标提升。原因是学生通过在线采样不断接触自己能力边界附近的样本,然后在优化时规避这些边界,这个行为被误读成“从教师那里学到了知识”。
要解决这个问题,不能只看最终分数,要看模型在教师知识边界之外的行为变化。例如准备一组难度明显超出学生当前能力、但教师可以稳定解决的 prompt,看蒸馏后学生是否真的在这组数据上提升。如果只在自己本来就能回答的问题上变好,那不叫蒸馏,叫“爬山”。
3.3 KL 散度掩盖下的信息量问题
很多蒸馏实现把损失写成KL(student_logits || teacher_logits),KL 值降下去就觉得对齐了。问题在于,教师分布本身包含的信息量可能很小。如果教师对很多输入都给出高置信度、接近 one-hot 的输出,学生拟合这个分布即使 KL 很低,也学不到什么结构信息,只是学会了“更相信自己”。这会让 loss 曲线特别好看,但换一组分布外测试立刻露馅。
更合理的评估方式是把教师分布分成“学生能预测的部分”和“学生不能预测但教师能提供的部分”。前者对应自我兜底,后者才对应真正的知识迁移。OPSA 这类少监督方法出现后,KL 散度这种指标会进一步失效,因为它们不再直接模仿某个概率分布,需要单独给评估设计度量方式。
3.4 当“监督”变成“奖励”,蒸馏就跑偏了
最后一个机制是监督信号的性质。经典知识蒸馏的监督信号是教师概率分布,属于“模仿式”目标;RLHF/DPO 类训练的监督信号是反映人类偏好的 reward,属于“选择式”目标。两者在数学形式上可以相互转化,但在机制上差异巨大。如果 On-Policy 蒸馏实验使用“教师判断回答是否可接受”作为过滤条件,学生涨点可能完全来自过滤掉低质量数据,而不是教师展示了更多知识。这类混淆在论文中并不少见,读原论文时一定要看清教师输出到底被用来做了什么。
从标题给出的信息推断,OPSA 应该是试图完全绕开上述三类问题:不依赖真实答案、不依赖教师软标签、不依赖人工偏好,让蒸馏信号更“纯粹”。因此它的价值可能不只是提升指标,更是用“负空间”的方式证明原有流程里的教师参与并非不可替代。
4. OPSA 方法机制:无需监督的信号从哪里来
这一节需要先做一个声明:目前输入材料只给出 “OPSA” 和 “无需监督” 两个关键词,没有给出公式和算法伪代码。下面写的是阅读这类论文时应当关注的机制推断,不能当作 OPSA 原文机制直接引用。要拿到确定机制,建议下载论文后重点看损失函数与 Algorithm 1。
OPSA 如果走“无需监督蒸馏”路线,通常有三种可能的信号来源:
第一种是自一致性。让同一个学生模型在相同 prompt 下用不同解码温度或不同随机种子采样多条输出,把彼此一致的部分作为训练信号。这种方式不需要任何外部模型参与,学生只需要在生成过程中找到自己不稳定的地方并强化稳定输出。优点是成本低;缺点是只能压缩模型自身的不确定性,不能引入超出学生已有能力的知识。
第二种是分布匹配或熵最小化。模型可以在不依赖教师 softmax 的情况下,通过正则项约束当前输出分布的熵,把低置信度区域压平,把高置信度区域收紧。这更像一种“自我蒸馏 + 正则化”的混合体。如果 OPSA 使用这类信号,它能证明的是“无需外部监督也能稳定提升”,但不能证明教师知识可被完全替代。
第三种是基于排序或对比信号的无监督偏好。比如让学生自己回答多个候选,再用文本内部一致性、可验证性、或者与 prompt 的语义相似度给候选打分,然后对高分样本做梯度上升。这个方法不需要人类偏好,但需要额外的奖励代理或规则判断,严格意义上不算“完全无监督”,需要看论文如何定义。
顺着这个推断,OPSA 训练管线的大致轮廓是:给定一组 prompt,学生先采样多条候选回答;然后通过某种无需外部标签的评分函数选出更优解;最后让对方模型优化自己选出的结果。循环往复完成多轮提升。
如果按这套理解,OPSA 的有效性验证就变得很清楚:它不是要证明“无监督也能涨点”,而是要证明“在没有教师和真实标签的情况下,模型通过自身输出构建学习信号,可以逼近甚至超过传统 On-Policy 蒸馏的水平”。如果实验做到这一点,那么原始 On-Policy 蒸馏的“教师贡献”就会被极大质疑。反之,如果 OPSA 效果明显不如带教师版本,反而说明教师仍然提供了学生自身采样给不了的信息,也就是说 On-Policy 蒸馏确实有部分“真蒸馏”成分。
这个对照关系,比任何单独的方法指标都重要。
5. 实验设计:如何验证 On-Policy 蒸馏是否真的在蒸馏
复现这类论文,不能只跑一个方法和一个 baseline。要回答标题里的问题,至少需要四组实验,并且四组实验之间的差异必须非常小,否则任何结果都无法归因。
| 实验组 | 教师模型参与 | 外部真实标签 | 采样方式 | 主要考察点 |
|---|---|---|---|---|
| A | 参与并输出软标签 | 不提供 | 学生 On-Policy 采样 | 标准 On-Policy 蒸馏效果 |
| B | 不参与,学生自己输出作为标签 | 不提供 | 学生 On-Policy 采样 | 去掉教师后还剩多少收益 |
| C | 参与并输出软标签 | 提供 | 静态数据集采样 | 常规离线蒸馏效果 |
| D | 按 OPSA 方法训练 | 不提供 | 学生自采样 + 自评分 | 无需监督时能否达到 A 的效果 |
A 和 B 的对比是最核心的。如果 A 和 B 最终指标接近,说明 On-Policy 蒸馏里教师提供的信息可以被学生的自举替代,论文标题的质疑成立。A 和 C 的对比也很重要,它判断的是“在线采样是否比离线数据更有价值”。如果 A 在训练步数更少的情况下接近 C,说明在线数据分布帮助很大,但这仍然不能证明教师贡献。
实验指标不能只看 benchmark 分数。应当同时记录:
- 学生模型训练前后在同一组 OOD prompt 上的回答质量,判断是否真的扩展了能力边界。
- 学生新分布和教师分布的 KL 散度,以及和学生旧分布的 KL 散度。如果后者变化远大于前者,说明模型主要在做自我调整。
- 学生在“教师会做、学生原本不会”的样本子集上的正确率。只有这个数字明显上升,才能谈得上知识迁移。
- 训练曲线的方差。去除教师后,方差可能变大或变小,这能反映教师信号是否起到了稳定器的作用。
所有组必须固定随机种子、固定采样温度、固定训练步数、固定 batch size。很多蒸馏论文最大的问题就是不加控制地调参,导致对比组之间差异不是来自蒸馏方法,而是来自超参。建议每组至少跑三个随机种子取均值和标准差,否则结论可能只是噪声。
6. 环境准备与复现框架搭建
如果你要落地复现,下面是一个项目目录,适用于基于 PyTorch 的自蒸馏对比实验。
. ├── configs │ └── opsa_experiment.json ├── data │ └── prompts.jsonl ├── models │ ├── teacher │ └── student ├── outputs │ ├── method_onpolicy │ ├── method_no_teacher │ ├── method_offline │ └── method_opsa ├── scripts │ ├── train.py │ └── evaluate.py └── requirements.txt环境检查建议按这个顺序确认:操作系统支持 CUDA;显卡驱动版本正常;Python 环境里已经安装 PyTorch;磁盘空间足够存放教师、学生模型和中间 checkpoint;如果学生模型需要自己的 tokenizer,需要确认它与教师词表是否一致。词表不一致时,教师 softmax 不能直接对齐到学生 logits,需要先做投影层,这种情况下一旦出现 KL loss 不下降,问题很可能就在这里。
教师和学生的落盘路径需要在配置文件中写清楚。如果你使用的模型来自 Hugging Face,可以用transformers的AutoModelForCausalLM加载;如果你在境内网络环境,需要提前把权重文件同步到本地目录。受限于每个具体模型许可不同,训练前自行确认权重和数据的适用范围,不要把开源许可之外的数据塞进蒸馏流程。
推荐使用 bf16 混合精度,教师模型在推理阶段用torch.inference_mode()冻结。学生模型开gradient_checkpointing可以显著降低显存占用,代价是训练速度变慢。对大多数实验场景,先跑通一个 1000 条 prompt 的小样本流程,再放大到完整数据。
7. 训练脚本、配置与评估示例
下面给出一份通用配置文件。它把前文的四组实验参数集中管理,实际实验时可以只修改method字段,避免手写多条重复训练命令导致配置遗漏。
{ "project": "onpolicy_distill_repro", "method": "method_opsa", "seed": 42, "model": { "teacher_path": "/models/teacher", "student_path": "/models/student", "max_length": 1024, "use_bf16": true }, "data": { "prompt_path": "/data/prompts.jsonl", "max_train_samples": 1000, "eval_path": "/data/eval_prompts.jsonl" }, "train": { "batch_size": 4, "gradient_accumulation_steps": 8, "learning_rate": 2e-5, "num_train_steps": 200, "sampling_temperature": 0.8, "save_steps": 50 }, "loss": { "distill_weight": 0.5, "ce_weight": 0.5, "use_teacher": false, "use_ground_truth": false } }这里use_teacher: false对应 D 组 OPSA 实验。use_ground_truth: false表示训练时不依赖真实参考文本。配置文件只描述通用结构,字段命名不一定和论文官方一致,落实验证时需要对照实际代码调整。
训练脚本核心循环可以参考下面这个模板。它不是一个可开箱即用的完整训练脚本,而是一个便于理解变量关系的伪代码框架。
import json import torch from torch.nn import functional as F # 加载配置 with open("configs/opsa_experiment.json", "r") as fp: config = json.load(fp) def compute_supervised_kl_loss(teacher_logits, student_logits): """On-Policy 蒸馏组使用的标准 KL 对齐损失。""" return F.kl_div( F.log_softmax(student_logits, dim=-1), F.softmax(teacher_logits, dim=-1), reduction="batchmean", ) def compute_self_consistency_signal(student_samples, student_model): """OPSA 风格的无需监督信号。 这里仅给出逻辑占位:具体无监督打分函数需要按论文实现替换。 常见思路:比较多次采样输出之间的一致性,选择置信度更高的结果作为优化目标。 """ return torch.tensor(0.0, device=student_samples.device) def train(): trainer = load_trainer(config) teacher_model = load_teacher(config) student_model = trainer.student_model optimizer = trainer.optimizer for step in range(config["train"]["num_train_steps"]): prompts = load_prompt_batch(step, config) # On-Policy 采样:学生当前策略生成候选 with torch.no_grad(): student_samples, student_logits = student_model.generate_with_logits( prompts, temperature=config["train"]["sampling_temperature"], ) total_loss = torch.tensor(0.0, device="cuda") if config["loss"]["use_teacher"]: with torch.inference_mode(): teacher_logits = teacher_model.forward(student_samples) distill_loss = compute_supervised_kl_loss(teacher_logits, student_logits) total_loss = total_loss + distill_loss if config["method"] == "method_opsa": # 无监督信号分支:具体 loss 需要按论文替换 self_signal = compute_self_consistency_signal(student_samples, student_model) total_loss = total_loss + self_signal if config["loss"]["ce_weight"] > 0 and config["loss"]["use_ground_truth"]: ref_texts = load_reference_text(step, config) ce_loss = compute_cross_entropy(student_logits, ref_texts) total_loss = total_loss + config["loss"]["ce_weight"] * ce_loss total_loss.backward() optimizer.step() if step % config["train"]["save_steps"] == 0: torch.save(student_model.state_dict(), f"checkpoints/model_{step}.pt") if __name__ == "__main__": train()代码里的compute_self_consistency_signal只是逻辑占位。如果 OPSA 的真实信号来自一致性、分布熵或内部排序,需要把损失函数替换成论文实现。这也是复现论文时最容易出现偏差的地方——不同无监督损失收敛行为差异极大,一个简单的占位函数无法代表最终论文效果。
评估脚本可以这样设计,重点输出三个数字:学生在评测集上的标准准确率、学生新旧分布 KL 变化、学生分布与教师分布 KL 变化。即便没有教师参与训练,评测时仍然可以通过加载教师模型计算两者分布差异。
import torch from torch.nn import functional as F def evaluate(model, eval_prompts, teacher_model=None, old_logits_path=None): """评估蒸馏后模型的质量与分布变化。""" model.eval() total_accuracy = 0.0 total_kl_with_teacher = 0.0 total_kl_with_old = 0.0 batch_count = 0 for batch in eval_prompts: with torch.inference_mode(): logits = model.forward(batch["input_ids"]) # 准确率指标需要按任务自行设计 acc = get_accuracy(logits, batch["expected_answer"]) total_accuracy += acc if teacher_model is not None: teacher_logits = teacher_model.forward(batch["input_ids"]) kl_teacher = F.kl_div( F.log_softmax(logits, dim=-1), F.softmax(teacher_logits, dim=-1), reduction="batchmean", ) total_kl_with_teacher += kl_teacher.item() if old_logits_path is not None: old_logits = load_old_logits(old_logits_path, batch) kl_old = F.kl_div( F.log_softmax(logits, dim=-1), F.softmax(old_logits, dim=-1), reduction="batchmean", ) total_kl_with_old += kl_old.item() batch_count += 1 return { "accuracy": total_accuracy / batch_count, "kl_with_teacher": total_kl_with_teacher / batch_count, "kl_with_old": total_kl_with_old / batch_count, }这里刻意不写死get_accuracy实现,因为它依赖具体任务。如果做生成任务,可以用规则判断关键词;如果做分类,可以直接用 argmax。核心是三个量同时报告,不要把 accuracy 单独拿出来当蒸馏成功的唯一证明。
8. 资源占用与训练过程观察
On-Policy 蒸馏的资源占用比离线蒸馏高,因为每一步需要学生采样、教师前向、学生梯度回传三个大计算阶段。显存会同时包含学生优化器和教师推理状态。OPSA 如果完全去掉教师,理论上可以省掉教师前向那部分显存和算力,但学生多路采样和自评分函数会带来额外 CPU/GPU 消耗。
显存估算可以参考这个公式:总显存约等于学生模型参数量乘以 12 到 16 字节(单卡混合精度训练场景),再加上教师模型推理约等于参数量乘以 2 字节到 6 字节。具体占用与 batch size、序列长度、是否开启梯度检查点强相关,不建议拿别人的经验值硬套。更准确的做法是先用一个 batch 跑起来,用nvidia-smi观察峰值占用,再逐步调大 batch。
训练步骤长度对开销的影响大于数据量。学生在 On-Policy 蒸馏中参与采样会非常耗显存,如果序列长度达到 2048,即使 batch size 为 1 也可能把常见消费级显卡占满。复现这类实验,优先准备单张 24G 以上显存的 GPU,如果条件有限可以缩小max_length和batch_size,同时在学生端开启gradient_checkpointing。
训练过程要重点观察四条曲线:
第一条是 total loss。它降得再平滑,也不能说明知识迁移发生。
第二条是学生分布与教师分布的 KL 散度。该值下降说明学生确实往教师方向靠。但要注意,如果学生和教师同源,此曲线会从很小的地方开始下降,最终结果可能变化不大。
第三条是学生分布与训练前旧模型分布的 KL 散度。如果这个值显著上升,模型行为发生了真实改变。如果该值几乎为零,模型基本没有变化,loss 信号可能是被采样平滑效果掩盖了。
第四条是 OOD 测试集准确率。它最可靠,也最容易观察到“loss 下降但能力没提升”的矛盾情况。
建议每隔固定步数保存一次 checkpoint,并在单独评测脚本里加载 checkpoint 做指标计算。不要只在训练结束后评一次,那样无法还原哪个阶段发生了真正的知识变化。
9. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| KL loss 在训练初期就开始下降,但最终任务分不涨 | 教师与学生同源导致信号冗余 | 查看学生旧分布 KL 变化 | 增加不同源教师对照组 |
| 去掉教师后,学生指标仍然保持上涨 | 在线采样自带正则化收益 | 用 no teacher 对照组复盘 | 说明原方案里有很大一部分并非蒸馏 |
| OPSA 无监督信号波动大,loss 不稳定 | 自评分函数方差过高 | 打印每一步无监督 loss 分布 | 减小学习率、提高采样候选数 |
| 教师和学生的 tokenizer 不一致 | 词表无法对齐 | 检查 logits 最后一维尺寸 | 添加投影层或统一 tokenizer |
| 显存不足 | batch size 或序列长度过大 | nvidia-smi 查看峰值占用 | 开梯度检查点、缩小 batch、使用 bf16 |
| 采样数据分布不断漂移,指标难以对比 | On-Policy 在线采样造成分布偏移 | 固定几个验证 prompt 定期评测 | 设置多个固定 eval prompt 集合,避免只看训练分布 |
| 训练完成但模型直接退化 | 无监督信号方向错误 | 检查生成样本质量变化 | 修正评分函数,增加过滤阈值 |
如果在跑论文自带仓库时遇到问题,第一条应该查 README 里指定的 Python、PyTorch 和 Transformers 版本,而不是直接升级到最新版本。很多蒸馏实现会在特定版本下保持稳定,升级依赖反而导致 API 变化。
另一个高频问题是采样温度设置。OPSA 这种依赖自生成的训练方法对解码温度更敏感。温度过低,采样多样性不足,无监督信号无法区分好坏;温度过高,生成大量噪声,训练信号失效。建议采样温度先从 0.8 到 1.0 之间试起,对比三档后再确定正式配置。
10. 最佳实践与使用建议
第一,无论采用哪种蒸馏方法,都必须在论文实验之外增加一个“去掉教师”的对照组。这个组不一定是新方案,但它能快速告诉你性能提升中有多少比例来自教师。如果 no teacher 组的得分已经达到完整方案的 80% 以上,建议先检查蒸馏数据构造和采样策略,而不是继续堆算力微调教师超参。
第二,OPSA 这类无需监督的蒸馏方法,用途不等于“替代一切教师”。当学生能力明显弱于教师、OOD 数据量又很大时,外部教师仍然能提供学生自采样无法获得的信息。OPSA 更适合的场景是:教师许可受限、标注成本过高、或者你需要快速检验学生是否有自我提升潜力。把它当作一种低成本诊断工具,反而比单纯当作无监督训练器更有价值。
第三,检查无监督方法是否真正学到泛化知识,要使用独立评测集。训练时不看标签,不代表评测时可以短路。建议从原有训练 prompt 中切开 10% 到 20% 作为评测集,并在训练前先测一次 student 的 baseline 指标。所有报告里都要写明 baseline 和最终数值的差值,而不是只写“提升到多少分”。
第四,发布或部署由蒸馏得到的小模型前,需要确认教师模型、训练数据、蒸馏产物的许可证是否允许后续用途。教师模型本身就带有数据采集和授权边界,蒸馏不能自动让数据变成“干净数据”。如果你的数据里包含真实用户生成内容、人脸、声音或受版权保护的材料,不要把它复制到自蒸馏训练集里。
第五,OPSA 这类方法的实验稳定性需要妥善管理。每组实验至少跑三个随机种子取均值,否则基于小模型低方差数据很容易得出完全相反的结论。实际操作中随机种子对结果的影响可能比蒸馏方法差异还大,这是复现论文时最常见的“隐藏变量”。
11. 总结:最值得先验证的是什么
这篇论文最值得尝试的点,不是“无监督蒸馏涨了多少分”,而是它提供了一次机会去检查你手里所有蒸馏流程是否出现了虚假归因。只要你正在做模型蒸馏,值得先跑一个最小化的两两对比:On-Policy 标准蒸馏,对比去掉教师后的自训练。如果两者差距不大,你现有的训练管线可能并不依赖教师知识。
OPSA 方法则要重点验证两个位置:无监督学习信号是从哪来的,这个信号在连续多轮训练后是否稳定。只要这两个点能说清楚,OPSA 的设计逻辑就站得住;说不清,就说明它可能仍然依赖隐性监督。
最容易踩的坑是看论文时只盯着最终 benchmark,不看实验组设计和 loss 公式。对于这篇论文而言,实验设计的价值远大于几个百分点的提升数字。建议收藏备用,之后看到任何“蒸馏涨点”的报告,先按这套思路检查它的对照组是否干净,再决定要不要跟随。最实用的下一步,是用小规模数据快速复现一次 On-Policy、No Teacher、OPSA 三组对比,观察这三条训练曲线的真实差异。