☰
面向CTR预估的多教师知识蒸馏工程落地
2026/11/3 23:52:01 网站建设 项目流程

线上 serving 的延迟预算卡在 30ms 以内,模型加一层就超时,可离线实验里那个又大又慢的模型,AUC 明显比线上这套高——这个死结,做过推荐系统点击率预估的人基本都撞过。多教师网络知识蒸馏就是在这个缝隙里长出来的一套解法:把几个“离线很强、线上放不下”的教师模型里学到的知识,通过软标签、中间层对齐、样本加权等手段,迁移到一个结构不变、延迟不变的学生模型上。标题里提到的这套来自业界的方案,核心不在于蒸馏本身有多新,而在于把“多教师”这件事在 CTR 场景下做扎实了:多个教师怎么来、软标签怎么聚合、温度怎么调、蒸馏损失和真实标签怎么配比。这篇内容适合已经能跑通一个 DeepFM 或 DIN 级别模型、想进一步压榨效果的中高级算法同学,也适合刚接触知识蒸馏、想知道它在推荐场景里到底怎么落地的同学。

1. 这个方案到底在解决什么问题

1.1 线上延迟预算与离线效果的死结

推荐系统里的点击率预估,本质上是在一个极严的延迟约束下做高维稀疏特征的二分类。线上的 QPS 摆在那,模型复杂度就有一个硬天花板:embedding 维度不能太大、特征交叉层数不能太深、用户行为序列长度不能太长。你在离线把序列长度从 50 拉到 500,AUC 可能涨零点几个千分点,但线上单请求的推理耗时直接翻倍,工程侧不会批。

所以真正的矛盾不是“模型不够强”,而是“强模型上不了线”。知识蒸馏的价值就在这里体现:它把计算压力从推理侧挪到了训练侧。教师模型可以在离线用几倍的算力、几倍的特征、几倍的序列长度跑,跑完之后它的知识以软标签的形式被固化下来,学生模型的推理路径一个字节都没变,但训练信号变丰富了。

我自己的理解是,蒸馏在 CTR 场景里扮演的是“训练期增强”的角色,而不是“模型压缩”的角色。工业界做 CTR 蒸馏,绝大多数时候学生模型的结构和上线时的结构是完全一致的,参数量也一致,你并没有把模型变小,你只是把一个更强的信号源接进了 loss 里。

1.2 单教师蒸馏为什么不够用

单教师蒸馏在图像分类上很成熟,搬到 CTR 上就会碰到几个具体问题。

第一个是教师本身有偏。任何一个 CTR 模型都是在特定特征子集上训练的,它学到的知识有明确的边界。比如一个以长序列为主的教师,它对用户即时兴趣的刻画很准,但对物品侧静态特征的交互建模就弱;反过来一个以特征交叉为主的教师,短期兴趣迁移能力就不行。你只蒸馏一个教师,等于把它的偏好和偏见一起传给学生。

第二个是单教师的软标签噪声大。CTR 是极度不平衡的二分类,正样本可能只占百分之几,教师的输出分布本身就集中在低概率区间。单教师给出的软标签在大量样本上是“几乎为 0 但又不是精确 0”的一团模糊信号,学生从里面能学到的信息有限。

第三个是单教师的容量瓶颈。想要更好的软标签,就得把教师做得更大,但教师越大,训练成本越高、过拟合风险越高、单点故障的影响越大。多教师用“横向扩展”代替“纵向加深”,几个中等规模的教师取长补短,通常比一个巨无霸教师更划算。

1.3 多教师蒸馏在 CTR 场景下的三种教师来源

在推荐场景里,“多教师”不是随便训几个模型凑数,实践中有效的教师大概来自三类:

教师类型与学生的差异点传递的知识典型增益来源
长序列教师用户行为序列长度是学生的数倍更完整的长周期兴趣表征序列建模能力迁移
异构结构教师完全不同的网络结构(如不同的交叉方式)不同的特征交互假设结构互补、降噪
跨域教师用其他场景/其他目标训练的模型更泛化的表征冷启动、稀疏特征

第三类需要特别注意合规和数据隔离问题,跨域蒸馏必须在数据使用规范允许的范围内做,不能想当然地把别的业务数据拿来当教师信号。我见过有人为了涨点,把其他业务线训练的模型直接搬过来做教师,结果特征定义都对不齐,蒸馏出来的软标签全是噪声,训了三天还不如不加。这个坑后面会细讲。

2. 整体架构设计与关键选型

2.1 训练流程的分阶段设计

多教师蒸馏不是一次训练就能搞定的,它天然是一个三阶段流程,硬把它压成一个阶段会出问题。

阶段一,各自训练教师。每个教师独立训练,验收标准是:单模效果必须显著优于学生基线。这一点是硬门槛,教师比学生弱,蒸馏就是负迁移,别抱侥幸心理。

阶段二,冻结教师,联合训练学生。教师前向不反传,参数锁死。学生的总损失是 CTR 主损失和蒸馏损失的加权和。这一步是整个方案的主体。

阶段三,可选的学生微调。联合训练结束后,把蒸馏损失权重逐步衰减到 0,再用纯 CTR 损失跑几个 epoch。这一步的作用是让学生“回归本职工作”,避免被软标签带偏。很多团队省略这一步,结果离线 AUC 涨了,线上校准度变差,就是这个原因。

为什么教师必须冻结?因为如果教师和学生一起训,教师会被学生的损失函数带偏,逐渐向学生靠拢,蒸馏信号就退化成自我模仿,多教师的互补性直接消失。这跟 GAN 的判别器不能太好是两回事,但道理相通:信号源必须稳定。

2.2 蒸馏信号的四种载体与选择依据

蒸馏到底传什么,这是设计里最容易含糊的地方。可选载体有四种,成本和收益差别很大。

输出层软标签。最常用,成本最低,只需要存教师对每条样本的输出概率。优点是实现简单、通用性强;缺点是对二分类 CTR 来说信息量有限,一个标量里塞不下多少东西。

logit 层的温度缩放分布。严格说这是软标签的变体,但多了一个温度参数,可以把分布“摊平”,暴露更多相对信息。二分类场景下它的收益不如多分类明显,但仍然有效。

中间层特征。传递隐层表示,信息量大很多。难点是维度对齐:教师隐层维度往往和学生不一致,需要加一个投影矩阵把学生特征映射到教师维度上再做 MSE 或余弦对齐。这个投影层只在训练时存在,推理时丢掉。

Embedding 层。对 CTR 模型来说这一层最有价值,因为模型能力差异很大程度体现在 embedding 的表达质量上。做法是对每个特征域的 embedding 做对齐,要求教师和学生用同一套特征词表。

实操建议:从“输出层软标签”起步,跑通链路之后再逐层加。中间层蒸馏的调参难度比输出层高一个量级,新手上来就做中间层,很容易训崩。

2.3 多教师聚合的四种方式对比

多个教师的软标签怎么合成一个信号,这是“多教师”三个字的核心。四种方式各有场景:

聚合方式实现优点缺点
简单平均各教师概率取均值零参数、稳定忽略样本差异,弱教师拖累
加权平均预先设定固定权重可控权重靠人工调,无法逐样本自适应
门控注意力小网络按样本输出权重逐样本自适应增加参数,有过拟合风险
置信度加权按教师输出熵/方差加权无需训练教师自信不代表正确

我倾向于“门控注意力 + 温度平滑”这个组合。门控网络的输入是学生模型的特征表征,输出是 K 个教师权重,过 softmax 归一化。它的物理含义是:这条样本,哪个教师的知识更可信。比如一个行为序列很长的老用户样本,长序列教师权重自然会被抬高;一个几乎没行为的冷启动样本,序列教师的权重就下去了。

关键细节是门控网络不能太强。我一般把门控做成两层 MLP、隐层 64 维,并且给它单独一个更小的学习率,或者在训练前期用固定均匀权重预热,等学生稳定了再放开。见过有人把门控做成跟主模型一样大的网络,结果门控直接把整个 loss 吸过去了,学生啥也没学到。

2.4 为什么不直接用软标签替换硬标签

这是一个常见误解。有人想,既然软标签信息更丰富,那我干脆只用软标签训练学生不就行了?

不行,有两个原因。第一,教师会犯错,硬标签是真实发生的用户行为,是唯一的“地面真值”,完全丢掉了学生就没有纠偏锚点。第二,CTR 场景下的正样本极度稀疏,教师的软标签在负样本上普遍是一个很小的值,如果只用软标签,学生学到的决策边界会被压平,线上打分整体偏低,虽然排序能力可能不差,但校准度崩了。

校准度在推荐系统里不是学术指标,它直接影响出价、混排、多目标融合这些下游环节。AUC 涨了但校准偏了,工程上可能直接判为不可用。

3. 核心细节:温度、权重与损失配比

3.1 温度参数的数学作用与 CTR 场景下的取值

温度 T 是蒸馏里最需要解释清楚的超参。对二分类模型,教师输出的 logit 记作 $z_t$,学生记作 $z_s$,经过温度缩放后的概率是:

$$p_t^T = \sigma(z_t / T), \quad p_s^T = \sigma(z_s / T)$$

蒸馏损失写作交叉熵形式:

$$L_{kd} = -T^2 \left[ p_t^T \log p_s^T + (1 - p_t^T)\log(1 - p_s^T) \right]$$

对 $z_s$ 求导得到:

$$\frac{\partial L_{kd}}{\partial z_s} = T \cdot \left( \sigma(z_s/T) - \sigma(z_t/T) \right)$$

看这个梯度你能明白两件事。第一,当 T=1 时它就是普通 BCE 的梯度,没什么特别。第二,T 变大时,$\sigma(z/T)$ 的差值会被压缩,梯度变小,所以前面的 $T^2$ 是必要补偿项,不然温度一调大,蒸馏项就形同虚设。

在 CTR 场景下,我的经验取值区间是 T ∈ [1.0, 2.5],最常见的是 1.5。取值逻辑是看教师输出分布的“锐度”:如果教师在验证集上的预测分布高度集中在 0 到 0.05 之间,说明分布已经很扁,这时候 T 再大就彻底没有区分度了,反而要用小于 1 的温度去锐化;如果教师的预测分布比较分散,可以用稍大的 T 把中间地带的相对关系暴露出来。这个判断不需要理论推导,画个直方图就能看出来,比拍脑袋靠谱。

3.2 软标签与真实标签的配比 alpha

总损失是:

$$L = L_{ctr} + \alpha \cdot L_{kd}$$

$\alpha$ 的作用是控制“向教师学习”和“向真实数据学习”的平衡。CTR 场景下 α 的取值普遍比图像分类小,我常用的范围是 0.1 到 0.5,起步建议 0.3。

原因在于 CTR 的软标签噪声比图像大得多。用户点不点一个物品,里面混杂了大量偶然因素:误触、随手点、推荐位遮挡、时间点不同心情不同。教师给出的概率是这些噪声期望的一个估计,它比硬标签“平滑”,但也可能把噪声放大。α 太大,学生就变成在拟合教师的噪声。

还有一个实操细节:α 应该随训练进程衰减。前期学生离教师很远,需要强蒸馏信号拉一把;后期学生已经接近甚至超过单教师水平,继续强拉就是束缚。我一般用余弦衰减,从初始值线性降到初始值的 10% 左右。

3.3 门控加权网络的实现细节与过拟合防范

门控网络的形式:

$$w_k = \frac{\exp(g_k(x)/\tau)}{\sum_{j}\exp(g_j(x)/\tau)}$$

其中 $g(x)$ 是门控网络输出,$\tau$ 是门控温度,控制权重的锐度。τ 太小,权重会退化成 one-hot,等于每次只用一个教师,多教师的意义就没了;τ 太大,权重接近均匀,退化成简单平均。经验上 τ 取 1.0 到 2.0。

过拟合防范有三招,我一般同时用:

  • 门控输入只用学生模型的低维表征(比如最后一层隐层,64 到 128 维),不要喂原始特征,防止它学出对特定特征组合的记忆。
  • 对权重加熵正则,鼓励权重不要过度集中。$\lambda \sum_k w_k \log w_k$,λ 取 0.01 量级即可。
  • 训练前期用固定均匀权重预热 1 到 2 个 epoch,等主模型收敛到一定程度再解冻门控。

这里有个容易忽略的点:门控网络本身也会被蒸馏损失和主损失共同影响。如果门控输出权重后又反传,就变成了“学生选择教师、教师适应学生”的耦合,容易震荡。我的做法是对门控网络单独设置梯度裁剪,阈值设得比主网络更严。

3.4 中间层与 embedding 对齐的实操约束

中间层蒸馏的实现要点在维度对齐。假设教师隐层维度是 512,学生是 256,需要加一个线性投影 $W_p \in \mathbb{R}^{256 \times 512}$,损失是:

$$L_{mid} = \frac{1}{B}\sum_{i=1}^{B}\left| W_p h_s^{(i)} - h_t^{(i)} \right|_2^2$$

投影矩阵只在训练时存在,推理时直接丢掉,不影响线上延迟。这一点在很多介绍里没写清楚,导致有人以为中间层蒸馏会增加推理成本,其实不会。

Embedding 对齐更麻烦,因为教师和学生可能用不同的词表。可行的做法是只对齐“共享词表”的那部分特征域,并且要求两边用的是同一份特征配置。对齐时我建议用余弦相似度而非 MSE,原因是 embedding 的绝对尺度意义不大,只关心方向,MSE 会把两边的范数差异也当成误差去优化,容易把学生 embedding 的整体尺度拉偏。

另一个坑是,中间层蒸馏的权重不能和输出层蒸馏一样大。我现在用的比例大约是输出层 α=0.3、中间层 β=0.05,中间层只是起到一个“表征引导”的作用,主导信号还是输出层软标签。

4. 完整实操过程与代码实现

4.1 教师模型的训练与验收

教师训练的流程和普通 CTR 模型没有区别,但有两条额外的验收标准要写进实验记录里。

第一,每个教师单独评测,AUC 必须显著高于学生基线,我一般要求相对提升不低于 0.3%,否则这个教师不进池子。注意是相对提升,不是绝对,CTR 场景 AUC 的绝对提升 0.3% 已经很夸张了。

第二,教师之间要有足够的差异性。两个相关系数 0.99 的教师放进去,收益基本为零。可以用预测结果的皮尔逊相关系数衡量,我一般要求两两相关低于 0.95。如果相关性太高,说明这两个教师学的是同一个东西,换掉一个。

教师训练的日志里记得记录每个教师在验证集上的预测分布分位数,后面调温度要用。

4.2 离线软标签落盘方案

这里分享一个很实用的工程技巧:把教师的软标签预先算好落盘,训练时直接读,而不是每个 batch 都跑一遍教师前向。

这么做的好处很直接。假设你有 3 个教师,每个教师参数量是学生的一半,那训练时同时驻留 4 个模型,显存直接顶到上限,batch size 会被压到很小,训练效率严重下降。落盘之后,训练时只加载学生模型,显存占用回到基线水平,batch size 可以拉满。

存储成本的估算很简单:假设训练集有 1 亿条样本,每个教师存一个 float16 的软标签,那么单个教师占用约 200MB,3 个教师 600MB。这个量级在训练集群上完全可以接受。但如果存中间层特征,维度 256 的 float16,单个教师就是 1 亿 × 256 × 2 字节 = 51GB,这就必须走流式读取或者采样对齐,不能全量存。

落盘方案的代价是软标签是静态的,训练过程中不会更新。但教师本来就是冻结的,所以这个“代价”其实不存在。唯一的限制是门控网络无法在训练时实时调用教师,不过门控只需要软标签的加权,落盘后一样能做。

4.3 学生网络的联合训练代码

下面是核心 loss 的实现,用 PyTorch 写,可以直接套到你现有的训练脚本里。

import torch import torch.nn as nn import torch.nn.functional as F class MultiTeacherDistillLoss(nn.Module): """多教师蒸馏损失:输出层软标签 + 门控加权""" def __init__(self, num_teachers, hidden_dim=128, T=1.5, alpha=0.3, gate_tau=1.0, entropy_lambda=0.01): super().__init__() self.num_teachers = num_teachers self.T = T self.alpha = alpha self.gate_tau = gate_tau self.entropy_lambda = entropy_lambda # 门控网络:输入学生的隐层表征,输出每个教师的权重 logit self.gate = nn.Sequential( nn.Linear(hidden_dim, 64), nn.ReLU(), nn.Linear(64, num_teachers), ) def forward(self, student_logit, teacher_probs, student_repr, labels): """ student_logit: [B] 学生输出 logit teacher_probs: [B, K] 每个教师的预测概率(已落盘读出) student_repr: [B, D] 学生最后一层隐层表征 labels: [B] 真实标签 """ # 主损失 loss_ctr = F.binary_cross_entropy_with_logits(student_logit, labels) # 门控权重 gate_logit = self.gate(student_repr) / self.gate_tau weights = F.softmax(gate_logit, dim=-1) # [B, K] # 加权融合教师软标签 soft_target = (weights * teacher_probs).sum(dim=-1).clamp(1e-6, 1 - 1e-6) # 温度缩放蒸馏损失 student_temp_logit = student_logit / self.T loss_kd = F.binary_cross_entropy_with_logits( student_temp_logit, soft_target ) * (self.T ** 2) # 门控熵正则,防止权重塌缩成 one-hot entropy = -(weights * torch.log(weights + 1e-8)).sum(dim=-1).mean() total = loss_ctr + self.alpha * loss_kd + self.entropy_lambda * entropy return total, loss_ctr.detach(), loss_kd.detach(), weights.detach()

有几个容易写错的地方要强调。

binary_cross_entropy_with_logits的第二个参数是目标概率,不是 logit。所以传进去的soft_target必须是 sigmoid 之后的概率值,如果你直接把教师的原始 logit 传进去,损失会算出奇怪的值但不报错,排查起来很痛苦。

温度补偿项 $T^2$ 必须乘上。漏了这一步,你把 T 调大之后会发现蒸馏项几乎不起作用,然后花半天怀疑是教师有问题。

门控熵正则的符号是负号。熵越小权重越集中,我们要鼓励熵大(不要塌缩),所以正则项应该是正熵加到 loss 里,或者负熵减去,具体看你想要的方向。上面代码里是“鼓励熵大”的写法。

4.4 关键参数与资源开销估算

给一组我实际用过的配置,供参考:

参数取值说明
教师数量 K3超过 5 个边际收益基本为零
温度 T1.5按教师预测分布锐度调整
蒸馏权重 α0.3,余弦衰减至 0.03前期强拉、后期放手
门控温度 τ1.0越大越接近均匀平均
门控学习率主网络的 1/10防止门控抢梯度
batch size与学生基线一致落盘方案下无额外显存压力

显存估算:落盘方案下,训练时只驻留学生模型(参数量 P),显存约等于基线。如果不落盘,需要驻留 K 个教师加学生,显存约为 (K × P_teacher + P_student) 对应的激活和参数占用,实际可能是基线的 3 到 4 倍。这是很多人第一次做多教师蒸馏时最直观的痛感来源。

存储估算再强调一次:1 亿样本 × 3 教师 × float16 = 约 600MB,可以忽略;换成中间层 embedding 就变成几十 GB,必须重新设计。

4.5 上线前的一致性检查清单

蒸馏只在训练侧生效,理论上不影响推理,但实际落地时这几项一定要核一遍:

  1. 学生模型的导出结构和蒸馏前完全一致,参数量、层名、输入输出签名逐项比对。
  2. 特征配置没有因为对齐教师而改动。有些人为了做 embedding 对齐,顺手改了特征处理逻辑,这是事故高发区。
  3. 蒸馏后的模型权重没有引入额外的 buffer 或 non-trainable 参数。
  4. 用同一批离线样本,分别对新旧模型的输出做逐条比对,差异应该完全来自权重更新,而不是结构差异。
  5. 打分分布的分位数变化在可接受范围内,特别是高分段。

第 5 条我特别看重。蒸馏容易让模型整体输出偏移,虽然排序不变,但下游融合出价会跟着变。

5. 效果验证与消融实验设计

5.1 教师数量的边际收益曲线

多教师的收益不是线性的。我记录过一组实验,学生基线 AUC 为 0.7820:

配置AUC相对基线提升
学生基线0.7820—
+1 个教师(长序列)0.7848+0.36%
+2 个教师0.7861+0.52%
+3 个教师0.7866+0.59%
+5 个教师0.7868+0.61%

这组数字在 CTR 场景里是典型的:第一个教师贡献最大,第二个次之,三个之后基本饱和。所以我的建议是教师数量控制在 3 个,把精力花在“怎么选教师”和“怎么调温度”上,而不是堆数量。

注意这些数字是模拟实验的结果,实际提升幅度跟你的基线强度、数据量、教师差异度强相关,不要直接拿去当预期。

5.2 分层评估:蒸馏到底帮了谁

只看总体 AUC 是不够的,蒸馏的效果在不同人群上差异很大。我一般会按这几个维度做分层:

用户活跃度分层。把用户按历史行为数分成冷、温、热三档,分别看 AUC。我的观察是,蒸馏的收益主要落在冷启动和低频用户上,因为教师的知识(尤其是长序列教师)在这些样本上提供了学生自己学不出来的信息。高频用户学生自己就学得不错,蒸馏的增量有限。

物品曝光分层。新上架物品的收益也明显,逻辑同上。

特征稀疏度分层。有些特征域在训练集里出现次数很少,学生的 embedding 基本靠初始化,教师的 embedding 可能是用了更多数据训出来的,这部分迁移价值很大。

分层评估的另一个作用是排查问题。如果蒸馏后总体 AUC 涨了,但冷启动分层反而掉了,说明蒸馏信号在稀疏样本上引入了偏差,要去看是不是 α 太大或者门控在稀疏样本上权重分配不合理。

5.3 线上线下一致性的排查方法

离线涨点、线上不涨,是蒸馏最常见的翻车场景。排查方向按概率从高到低排:

第一,训练集与线上数据的时间分布漂移。教师是在旧数据上训的,如果软标签落盘之后隔了很久才训学生,软标签的分布可能已经和当前数据不匹配。应对办法是软标签和训练数据用同一批,落盘后尽快训练,别拖。

第二,评估数据泄漏。有些团队在做序列教师时,把未来行为加进了特征里,导致教师的离线指标虚高,软标签里带有未来信息,学生学到的是泄漏。上线后未来信息没了,效果自然回落。检查方法很直接:把教师的最后一个输入特征掐掉,看指标掉多少,掉得离谱就说明有泄漏。

第三,蒸馏后校准偏移导致下游链路受损。这个前面提过,AUC 涨了但整体打分偏低,融合层出价下降,最终收入反而跌。这种情况要在学生训练末期降 α 做微调。

第四,线上特征和训练特征不一致导致的“隐藏分差”。蒸馏本身不改变结构,但它会改变模型对某些特征的依赖强度。如果某个特征线上和训练时的取值口径不一致,蒸馏后模型对它的依赖变强,问题就会被放大。

6. 常见问题与排查实录

6.1 蒸馏后效果反而变差

这是最高频的问题,原因通常有三种。

教师不够强。前面说过,教师必须显著优于学生,相对提升 0.3% 是底线。如果教师只比学生强 0.1%,蒸馏基本是给噪声。

温度取错了。教师在验证集上的预测分布高度集中(比如 95% 的样本预测值小于 0.02),这时候 T=2 会把本来就挤在一起的分布彻底压平,软标签失去区分度。解决办法是画分布直方图,用小于 1 的温度去锐化,T 取 0.5 到 1.0 试试。

α 太大。学生被软标签带偏,学到了一堆教师噪声。降 α 重跑,从 0.1 开始往上加。

6.2 训练不稳定与 loss 震荡

蒸馏 loss 参与训练后,loss 曲线出现周期性震荡,通常是门控网络和主网络互相拉扯。解决办法是门控预热加单独学习率,或者干脆先用固定均匀权重跑通,确认链路没问题再加门控。

另一种情况是 soft_target 被 clamp 到边界。教师输出恰好是 0 或 1 时,交叉熵会出现极大值。代码里clamp(1e-6, 1-1e-6)就是防这个,别省。

6.3 教师与学生特征域不一致

多教师最容易踩的坑就是这个。很多同学拿一个用了 200 个特征域的教师,去蒸馏一个只有 120 个特征域的学生,然后指望 embedding 对齐。实际上两边的特征配置不同,词表不同,embedding 对不齐,中间层蒸馏的梯度全是噪声。

我的原则是:教师和学生必须共享同一套基础特征配置,差异只能来自“每个特征的建模方式”和“序列长度”,不能来自“有没有这个特征”。这个约束能不能满足,直接决定你能不能做中间层蒸馏。如果满足不了,就老老实实只做输出层软标签蒸馏。

6.4 常见问题速查表

现象最可能原因排查动作处理办法
蒸馏后 AUC 下降教师弱或温度错单教师 AUC、预测分布直方图换教师,调 T 到 0.5-1.0
训练 loss 震荡门控与主网络耦合关闭门控用均匀权重门控预热、降学习率
离线涨线上不涨时间漂移或数据泄漏检查教师特征时序、落盘时间重打软标签,掐掉可疑特征
打分整体偏移α 过大或未做末期微调对比打分的分位数分布末期衰减 α 到接近 0
冷启动分层下降稀疏样本蒸馏偏差分层 AUC降低稀疏样本的蒸馏权重
中间层蒸馏 loss 不降维度对齐或词表不一致投影矩阵初始化、特征域交集只对齐共享特征域,用余弦损失

6.5 几条不太写在文档里的经验

第一,别指望蒸馏带来大幅度提升。CTR 场景下多教师蒸馏的典型收益在相对 0.3% 到 0.8% 之间,能到 1% 已经很罕见。如果你的目标是翻倍,方向就错了,该去做特征工程或者样本体系。

第二,蒸馏的最大隐性成本不是算力,是实验管理复杂度。K 个教师加一个学生,消融实验的数量是组合爆炸的。我的建议是把教师池固定下来,只用一套教师做所有对比实验,绝对不要中途换教师,否则前后实验不可比。

第三,落盘的软标签一定要带版本号和训练数据的 hash。这一点吃过亏:软标签和训练数据版本对不齐,样本顺序错位,模型训出来效果莫名其妙地差,排查了两天才发现是文件读取顺序的问题。加个 hash 校验,一行代码的事。

第四,门控权重的分布要定期看。如果发现某个教师的权重长期接近 0,说明这个教师基本没贡献,可以考虑从池子里拿掉。反过来,如果某个教师权重长期接近 1,说明多教师退化成了单教师,要么是这个教师太强,要么是门控崩了,两种都需要处理。

第五,学生在训练末期一定要能“脱开”教师。我现在的做法是最后 20% 的 step 把 α 降到初始值的十分之一以下,让模型用纯 CTR 损失收尾。这一步对线上校准度的改善相当明显,尤其在多目标融合的场景下,校准不准会直接体现在收入指标上。

我个人在实际项目里的体会是,多教师蒸馏这套东西,技术难度并不在公式上,公式很简单,难在工程细节:软标签怎么存、门控怎么稳、教师怎么选、上线怎么核。把这几件事做扎实,它能稳定地给你贡献那零点几个千分点;任何一环糊弄,它也能稳定地让你白干两周。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询