3.2 软硬损失怎么配比:目标函数设计 本节摘要:蒸馏的总损失是硬标签交叉熵与教师软化 KL 的加权和,权重 alpha 是全册出场率第二高的旋钮。本节给出配比公式的完整形态、各分量的作用边界,按四类典型场景给默认值,并处理两个常见复杂情况:师生任务不一致、多教材分量并存时的归一化。 3.1 讲了教材的显影(温度),本节讲这份教材在总课程表里占多少课时(配比)。两者合起来构成蒸馏目标函数的全部主干,第四章的所有变体教法,最终都落回这条公式上做加减法。 公式的完整形态 标准目标函数长这样:总损失等于 alpha 乘软损失(高温 KL,已乘温度平方补偿),加 (1 - alpha) 乘硬损失(常温交叉熵)。
本节摘要:蒸馏的总损失是硬标签交叉熵与教师软化 KL 的加权和,权重 alpha 是全册出场率第二高的旋钮。本节给出配比公式的完整形态、各分量的作用边界,按四类典型场景给默认值,并处理两个常见复杂情况:师生任务不一致、多教材分量并存时的归一化。
3.1 讲了教材的显影(温度),本节讲这份教材在总课程表里占多少课时(配比)。两者合起来构成蒸馏目标函数的全部主干,第四章的所有变体教法,最终都落回这条公式上做加减法。
标准目标函数长这样:总损失等于 alpha 乘软损失(高温 KL,已乘温度平方补偿),加 (1 - alpha) 乘硬损失(常温交叉熵)。写全了是:
L = alpha * T^2 * KL(学生高温分布 || 教师高温分布) + (1 - alpha) * CE(学生常温分布, 真实标签)
两个分量教的是不同的东西,边界要分清。硬损失的职责是"纠错":真实标签是唯一的外部事实来源,教师在训练集上犯错时,只有硬损失能把学生拉回正轨;它是学生成绩的下限保障。软损失的职责是"传艺":提供类间关系、样本难度、决策边界形状这些标签里没有的信息;它是学生超过"同规模直接训练"的部分的来源。alpha 的本质,是在"事实"与"见识"之间分配学生的注意力。
import torch import torch.nn.functional as F def total_kd_loss(s_logits, t_logits, y, T=4.0, alpha=0.9): """完整配比损失:注意软损失已含 T 平方补偿。""" hard = F.cross_entropy(s_logits, y) soft = F.kl_div( F.log_softmax(s_logits / T, dim=-1), F.softmax(t_logits / T, dim=-1), reduction="batchmean", ) * T * T return alpha * soft + (1 - alpha) * hard # 观察两个分量的数值量级,是定 alpha 的第一手依据 s = torch.randn(64, 10, requires_grad=True) t = torch.randn(64, 10) + 3.0 # 模拟一个"有明确偏好"的教师 y = torch.randint(0, 10, (64,)) L_hard = F.cross_entropy(s, y).item() L_soft = total_kd_loss(s, t, y, alpha=0.0).item() print(f"硬损失量级: {L_hard:.3f}, 软损失量级: {L_soft:.3f}") # 输出示例: # 硬损失量级: 2.37, 软损失量级: 2.91 # 量级接近时 alpha 才有"权重"的意义;若两者差一个数量级, # 先归一化分量再谈配比,否则 alpha 形同虚设。
场景一:师生同族、任务一致、教师强。 这是标准场景,软损失为主。alpha 从 0.9 起步(软 9 硬 1),因为标签信息量小、教师分布信息量大。Hinton 原始实验也是软损失主导。
场景二:标签噪声大。 硬损失靠不住时,把 alpha 提到 0.95 甚至 1.0,让教师的判断替代脏标签当主要纠错源。教师自身在这批噪声上的输出也更可靠——它是在干净数据上练的。
场景三:学生容量很小。 小学生消化不了太抽象的教材,软损失可以适当让位,alpha 取 0.5 到 0.7,给硬损失多点权重帮学生先站稳。容量鸿沟的进一步处理见 6.1。
场景四:教师任务与学生任务部分重合。 比如教师是 1000 类分类器、学生只做其中 20 类。此时硬损失权重应过半(alpha 取 0.3 到 0.5),因为教师的分布里有 980 个"无关课"在稀释注意力,软损失要做类目裁剪后(见下文)才值得高配比。
# 场景四的类目裁剪:教师 1000 类,学生只认 20 类 import torch import torch.nn.functional as F def cropped_kd(s_logits, t_logits, student_classes, y, T=4.0, alpha=0.5): """把教师分布裁剪到学生类目子集后再归一化。 student_classes 是长度 20 的索引张量,指出学生 20 类 对应教师 1000 类里的哪些位置。""" t_full = F.softmax(t_logits / T, dim=-1) t_sub = t_full[:, student_classes] # 取出 20 类的概率 t_sub = t_sub / t_sub.sum(dim=-1, keepdim=True) # 重新归一化 hard = F.cross_entropy(s_logits, y) soft = F.kl_div( F.log_softmax(s_logits / T, dim=-1), t_sub, reduction="batchmean", ) * T * T return alpha * soft + (1 - alpha) * hard t_logits = torch.randn(32, 1000) + 4.0 s_logits = torch.randn(32, 20, requires_grad=True) student_classes = torch.tensor([3, 17, 44, 102, 305, 388, 401, 512, 530, 615, 640, 688, 702, 777, 808, 815, 890, 913, 970, 999]) y = torch.randint(0, 20, (32,)) loss = cropped_kd(s_logits, t_logits, student_classes, y) print("裁剪后蒸馏损失:", loss.item()) # 输出示例: # 裁剪后蒸馏损失: 2.87 # 不裁剪直接蒸,教师 98% 的概率质量在子集之外,软损失近乎噪声。
背景。 某舆情团队的任务是五分类情感识别,人工标注来自外包团队,抽检发现约 8% 的样本标注可疑。基线学生直接训练 86.2%;教师是该领域强模型,在干净数据上训练,测试 93.5%。
操作。 分四组配比实验:alpha 0.5、0.8、0.9、0.95,温度固定 4,其余超参全同。额外记录一个观察指标:训练损失里软硬两分量的比值曲线,用来确认配比在实际量级上生效。
结果。 alpha 0.5 时学生 88.0;0.8 时 89.6;0.9 时 90.3;0.95 时 90.1。最优配比落在 0.9,比基线高 4.1 个点,是本团队做过的单笔收益最大的训练改动。
解读。 脏标签场景下软损失份额越高越好,与场景二的预判一致;0.95 反而略降,说明教师输出并非全知——保留的 5% 硬损失仍在纠正教师也拿不准的边缘样本。另一个值得注意的现象:alpha 0.9 组的硬损失分量在整个训练期始终比 0.5 组低,说明软目标本身在帮学生把硬分类做得更对——配比不是零和游戏,好的软损失会反哺硬任务。
变式。 三分量以上时(软 + 硬 + 特征,如 2.2 的方案),先各自归一化再分配权重,比例按"响应 0.5、特征 0.3、硬 0.2"起步;训练早期可以把 alpha 动态调低、后期调高——先让学生学会做事,再教它分寸,这个课程表式技巧在容量鸿沟大的组合上尤其有效。
⚠️ 常见坑:alpha 调到 1.0 前先确认教师校准。教师输出若是病态的过度自信,全软训练会把学生的错误模式焊死在教师身上;此时先修温度(3.1)或换教师,再谈满配比。
💡 关键直觉:把 alpha 理解为"课时分配"。标签是必修课,教师分布是选修的师傅私课;学生越强、任务越难、标签越脏,私课的课时占比就越高。