2.4 师傅不在场:数据无关蒸馏 本节摘要:数据无关蒸馏解决一个极端约束:教师权重在手,但原始训练数据一件也拿不到——数据涉密、已删除、或属于别人。办法是自己造教材:从随机噪声出发,反复修改噪声让教师的输出最"像对训练数据的那份自信",再拿这些伪样本教学生。本节讲造教材的闭环、两种流派与翻车点。 前面三节的教材都来自真实数据。本节是第二章的收官,也是资源约束的极端现场:连数据都没有,课还怎么上。这一节同时呼应第一章 1.3 的隐私价值——当数据本身就是不能碰的东西,软目标与伪样本成了传艺仅剩的通道。 自己造教材的闭环 核心想法是个逆向问题:教师的参数是固定的,什么样的输入会让教师表现出"见过训练数据"的行为?把这个问题交给梯度下降。
本节摘要:数据无关蒸馏解决一个极端约束:教师权重在手,但原始训练数据一件也拿不到——数据涉密、已删除、或属于别人。办法是自己造教材:从随机噪声出发,反复修改噪声让教师的输出最"像对训练数据的那份自信",再拿这些伪样本教学生。本节讲造教材的闭环、两种流派与翻车点。
前面三节的教材都来自真实数据。本节是第二章的收官,也是资源约束的极端现场:连数据都没有,课还怎么上。这一节同时呼应第一章 1.3 的隐私价值——当数据本身就是不能碰的东西,软目标与伪样本成了传艺仅剩的通道。
核心想法是个逆向问题:教师的参数是固定的,什么样的输入会让教师表现出"见过训练数据"的行为?把这个问题交给梯度下降。从一批纯噪声出发,反复调整噪声本身,让教师对它的输出越来越符合预期——预期通常由两部分构成:输出分布要尖锐自信(真实的训练数据让教师自信),且与已有伪样本互不重复(教材要多样)。噪声越改越像数据,这个过程叫模型反演或深度图像先验式生成。
教材造出来后,训练闭环就成立了:生成器产伪样本 → 教师打软目标 → 学生照常蒸馏 → 学生下轮再参与约束生成(防止教师与新学生联手跑偏)。整个流程不碰任何真实样本。
import torch import torch.nn.functional as F def generate_pseudo_batch(teacher, batch_size, iters=200, lr=0.05, eps=0.08, seen=None): """从噪声出发,优化输入让教师输出既自信又多样。 seen 是此前已生成批次的输出中心,用于推开重复教材。""" teacher.eval() x = torch.randn(batch_size, 3, 32, 32, requires_grad=True) opt = torch.optim.Adam([x], lr=lr) for _ in range(iters): logits = teacher(x) logp = F.log_softmax(logits, dim=-1) # 目标一:自信。交叉熵的最小值出现在硬预测处, # 等价于把最大对数概率推高、其余压低。 conf = -(logp.max(dim=-1).values.mean()) # 目标二:多样。与历史批次的输出均值拉开距离。 diversity = 0.0 if seen is not None and len(seen): centers = torch.stack(seen).mean(dim=0) diversity = -F.kl_div(logp.mean(0), centers, reduction="batchmean") loss = conf + 0.5 * diversity opt.zero_grad(); loss.backward(); opt.step() with torch.no_grad(): # 把噪声约束在合法像素范围内 x.clamp_(-eps, eps) with torch.no_grad(): seen.append(F.softmax(teacher(x), dim=-1).mean(0)) return x.detach() seen = [] pseudo = generate_pseudo_batch(teacher, 64, seen=seen) print("伪样本形状:", pseudo.shape) # 输出示例: # 伪样本形状: torch.Size([64, 3, 32, 32]) # pseudo 不带梯度,可直接喂给常规蒸馏训练循环当教材。
反演派:如上例,直接对输入做梯度优化,用教师自身行为定义"像数据"。优点是不需要额外网络、实现百行以内;缺点是生成慢(每批伪样本要几百次前向反传),且容易生成对抗式的"怪图"——教师自信但人眼完全看不懂的纹理。缓解办法是在损失里加图像先验:总变差正则让图像平滑、背景类别分布正则让类目多样。
生成对抗派:另训一个生成网络专门产伪样本,一个判别器判断"这批样本像不像真实数据分布"。生成器与判别器对抗,产出的样本分布比反演法更接近真实数据,训练学生的效果上限更高。代价是多两套要训练的组件,稳定性工作量大增。
反演法伪样本的"逼真度"怎么量?肉眼看不靠谱,工程上用教师输出分布的类目覆盖来当代理指标——教材堆在少数几类,学生注定偏科:
# 伪教材的质量巡检:类目覆盖与自信度两个仪表 import torch import torch.nn.functional as F @torch.no_grad() def pseudo_textbook_checkup(teacher, pseudo_batches): """pseudo_batches: 已生成伪样本批次的列表。""" softs = [] for x in pseudo_batches: softs.append(F.softmax(teacher(x), dim=-1)) p = torch.cat(softs) # N x C cat_share = p.mean(0) # 每类平均占比 coverage = (cat_share > 0.5 / p.size(1)).float().mean().item() conf = p.max(-1).values.mean().item() print(f"类目覆盖率: {coverage:.2f}(低于 0.8 说明教材偏科)") print(f"教师平均自信: {conf:.2f}(虚高过 0.98 要查对抗化)") print(f"类目占比前3: {cat_share.topk(3).values.round(decimals=3).tolist()}") return coverage, conf # 输出示例(已加类目均衡正则的生成器): # 类目覆盖率: 0.91(低于 0.8 说明教材偏科) # 教师平均自信: 0.87(虚高过 0.98 要查对抗化) # 类目占比前3: [0.163, 0.148, 0.121] # 若前三类合计超过四成,优先调大均衡正则权重再继续生成。
这份巡检建议每生成若干批跑一次——它比最终精度早很多暴露生成器的偏斜,省下的是后面整轮学生训练的算力。

背景。 某公司收购了一个视觉模型资产:权重文件与评测脚本齐全,训练数据因原公司合规要求彻底销毁,无法重新获取。业务需要把这个模型的精度迁移到一个可在端侧部署的学生上。
操作。 采用反演式数据无关蒸馏。每轮先用教师生成 64 张伪样本(迭代 200 次优化,带总变差正则与类目均衡正则),随后用这批伪样本对学生做常规响应蒸馏,温度 4、alpha 0.9。生成与训练交替,共跑 400 轮;同时用教师公开报告的各类别先验约束生成器的类目分布,防止教材全堆在易类上。
结果。 学生在原任务测试集上达到教师成绩的 91%,而直接用"随机噪声当数据"的对照组只有 72%,用增强版反演(加图像先验正则)为 88%,生成对抗式参考实现 93%。全程未接触任何真实训练样本。
解读。 效果阶梯说明两件事:其一,伪样本的质量直接决定天花板——"教师自信"这一个条件就能撑起七成成绩,先验正则再补两成,完整生成器逼近上限;其二,数据无关蒸馏的上限系统性低于有数据蒸馏,差距正是真实数据分布里教师行为解释不了的部分。若未来能拿到哪怕小规模真实样本,混合"真实小样本 + 伪样本"通常比纯伪样本再上一个台阶。
变式。 拿不到原始数据但能拿到部分统计量(类别均值特征、协方差)时,把统计量注入反演目标能显著提升伪样本质量;文本任务可把连续优化换成在嵌入空间扰动,避开离散 token 的梯度难题。
⚠️ 常见坑:伪样本"对抗化"。不加图像先验时,反演容易找到教师敏感、人眼无意义的纹理——教师对这些样本自信,但学生学它们学不出泛化。总变差正则、颜色抖动、中途截断都是常用的"逼真"手段。
💡 关键直觉:数据无关蒸馏的本质是"审讯教师"。教师记不住原始数据,但它对"什么样的输入该有什么反应"的记忆犹在——梯度下降就是审讯的刑具,逼它把记忆吐成教材。