PyTorch模型蒸馏核心是:学生学教师logits而非真实标签;用温度T软化分布(T=3~7);总损失=α·KL+ (1−α)·CE(α≤0.7)。需teacher.eval() + torch.no_grad(),logits/T后分别log_softmax与softmax,类别维度须语义对齐。

怎么用 PyTorch 实现最简模型蒸馏流程
核心就三件事:让学生模型学教师模型的 logits,而不是只盯住真实标签;加一个温度参数软化分布;损失函数得混合交叉熵和 KL 散度。不这么干,蒸馏基本没效果。
常见错误现象:loss 降得快但学生准确率卡在比教师低一大截、验证集上 student 的输出分布过于尖锐(temperature 太小)、训练时直接用 teacher.eval() 但忘了 torch.no_grad(),显存爆掉。
- 教师模型必须提前固定权重:调用
teacher.eval()+with torch.no_grad(): - logits 要除以
temperature(通常设为 3~7),再进torch.nn.functional.log_softmax和F.kl_div - 总损失 =
alpha * kl_loss+(1 - alpha) * ce_loss,alpha别设太高(0.7 是常见上限) - 学生模型输入必须和教师完全一致(包括预处理、尺寸、归一化),否则
teacher输出的 logits 没法对齐
KL 散度计算时为什么必须用 log_softmax 和 softmax 分开写
因为 F.kl_div(input, target, reduction='batchmean') 要求 input 是 log-probabilities(即 log_softmax 输出),target 是 probabilities(即 softmax 输出)。直接喂两个 softmax 或两个 log_softmax 都会算错。
典型错误:F.kl_div(student_logits, teacher_logits) —— 这俩都是 raw logits,完全没做分布转换,KL 值毫无意义。
立即学习“Python免费学习笔记(深入)”;
- 正确写法:
F.kl_div(F.log_softmax(student_logits / T, dim=1), F.softmax(teacher_logits / T, dim=1), reduction='batchmean') -
T必须相同,不能学生用 4、教师用 2;否则分布尺度不一致,KL 会虚高 - 如果用
nn.KLDivLoss,注意它默认reduction='batchmean',但要求 input 已是 log-space,别漏掉log_softmax
蒸馏时要不要冻结教师模型的 BatchNorm 统计?
要,而且必须关掉 teacher 的所有 training flag,包括 BN 层的 running_mean 和 running_var 更新。否则学生在学一个“边推理边变”的目标,根本学不稳。
容易被忽略的坑:只调了 teacher.eval(),但教师模型里嵌了自定义模块,里面手动写了 if self.training: 分支,结果那个分支还在跑——导致 BN 统计意外更新。
- 检查方式:打印
teacher.modules(),逐个确认.training == False - 更稳妥做法:训练前加
for m in teacher.modules(): m.training = False(强置) - 若教师用了 SyncBatchNorm,还要注意多卡下
eval()是否真正同步生效(PyTorch ≥1.9 一般没问题)
学生模型比教师小很多时,怎么避免 logits 维度不匹配
不是所有任务都能直接蒸馏 logits。比如教师是 1000 类 ImageNet 分类头,学生只训 10 类子集,student_logits 和 teacher_logits shape 对不上,F.kl_div 直接报错。
这时候不能硬 pad 或 slice,得按语义对齐:只取教师在学生类别索引上的 logits,再做 softening。
- 假设学生只学猫狗两类,对应教师的 class_id = [281, 282],则先取
teacher_logits[:, [281, 282]],再softmax - 类别映射表必须提前构建好,且在数据加载器里保持一致,否则蒸馏目标漂移
- 如果学生结构完全不同(如 CNN ←→ ViT),logits 维度无法对齐,就得换策略:用中间层特征蒸馏(
attention map或feature map的 L2 loss),而非 logits
事情说清了就结束。真正难的不是写那几行 KL 计算,而是确保教师输出稳定、学生输入对齐、类别语义一致——这三个点一松动,蒸馏就退化成普通训练。


















