第三章 教师模型选型:BERT、RoBERTa、GPT系列的选择标准与预训练权重加载

做知识蒸馏,第一步就是选老师。老师选不好,后面全白干。

我见过不少团队,一上来就无脑上 BERT-large,结果蒸馏出来的学生模型还不如直接训练一个小模型。为什么?因为老师教的东西本身就有问题,或者老师太强了,学生根本学不会。

这一章,我们就来聊聊怎么选老师,以及选好之后怎么把预训练权重加载进来。

3.1 三大主流教师模型家族

目前 NLP 蒸馏领域,教师模型基本就三个流派:BERT、RoBERTa、GPT。它们各有各的脾气。

模型家族 核心特点 适合蒸馏的场景 我个人习惯
BERT 双向编码器,MLM + NSP 预训练 分类、NER、QA 等理解型任务 中小规模任务首选,稳定
RoBERTa 去掉 NSP,动态 Mask,更大 batch 需要更强语义理解的任务 效果比 BERT 好 1-2 个点
GPT 系列 单向自回归,生成式预训练 文本生成、对话、摘要 生成任务首选,但蒸馏难度大

核心原则:教师模型的任务类型必须与学生模型的目标任务一致。你拿 GPT 去蒸馏一个分类模型,效果大概率不如 BERT。

3.2 选型标准:五个维度

选老师不是拍脑袋。我总结了五个关键维度,你照着这个清单去选,基本不会踩坑。

  1. 任务匹配度——理解任务选 BERT/RoBERTa,生成任务选 GPT。这是铁律。
  2. 模型容量——教师参数量一般是学生的 3-10 倍。太小了学不到东西,太大了学生跟不上。
  3. 预训练数据域——教师用的预训练数据跟你的下游任务越接近越好。比如做医疗 NLP,用 BioBERT 比用原始 BERT 强很多。
  4. 推理速度——蒸馏过程中需要教师反复推理。如果教师太慢,整个训练周期会拉得很长。
  5. 社区生态——HuggingFace 上有没有现成权重?有没有成熟的蒸馏工具?这直接决定你的开发效率。

我的经验:如果你刚开始做蒸馏,先用 BERT-base 当老师。它够用、够快、社区支持最好。等流程跑通了,再换更大的模型。

3.3 预训练权重加载实战

选好模型之后,下一步就是加载权重。这一步看似简单,但坑不少。

3.3.1 从 HuggingFace 加载

现在最主流的方式就是通过 transformers 库加载。代码很简单:

from transformers import AutoModel, AutoTokenizer

# 加载 BERT-base 教师模型
teacher_model = AutoModel.from_pretrained("bert-base-uncased")
teacher_tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

# 加载 RoBERTa-large
teacher_model = AutoModel.from_pretrained("roberta-large")
teacher_tokenizer = AutoTokenizer.from_pretrained("roberta-large")

# 加载 GPT-2
teacher_model = AutoModel.from_pretrained("gpt2")
teacher_tokenizer = AutoTokenizer.from_pretrained("gpt2")

注意:GPT 系列加载时,记得设置 pad_token = eos_token,否则 batch 推理时会报错。我曾经在这个坑里卡了半天。

3.3.2 加载自定义权重

有时候你需要加载自己微调过的模型。比如你在医疗数据上微调了一个 BERT,现在想用它当老师。

# 加载本地微调后的教师模型
teacher_model = AutoModel.from_pretrained("./my_finetuned_bert")
teacher_tokenizer = AutoTokenizer.from_pretrained("./my_finetuned_bert")

这里有个关键点:微调后的模型可能修改了分类头。蒸馏时我们通常只需要取 teacher_model.base_model 或者指定输出 hidden states。

3.3.3 冻结教师模型

蒸馏过程中,教师模型是 不参与梯度更新 的。一定要记得冻结:

for param in teacher_model.parameters():
    param.requires_grad = False

teacher_model.eval()  # 切换到评估模式

为什么?因为教师的作用是提供软标签和中间层特征。如果教师也在更新,那蒸馏就变成了联合训练,效果反而会变差。

3.4 教师模型选型决策流程图

下面这张图是我自己总结的选型流程,每次做新项目我都会过一遍:

教师模型选型决策流程图 教师模型选型决策流程 开始选型 任务类型:理解型 vs 生成型? 理解型 BERT / RoBERTa 生成型 GPT 系列 评估模型容量(3-10倍) 预训练数据域是否匹配? 确定教师模型并加载权重 说明:理解型任务优先 BERT/RoBERTa,生成型任务优先 GPT;容量不足或数据域不匹配时考虑替换

3.5 常见问题与避坑指南

我曾经踩过的坑:

  • 教师模型太大导致 OOM:蒸馏时教师和学生同时加载,显存占用翻倍。我建议先用 teacher_model.half() 转半精度,或者用 CPU 推理教师。
  • 分词器不匹配:教师和学生用不同的分词器,导致 token 对齐出错。一定要确保蒸馏时用同一个分词器。
  • 忘记冻结教师:有一次我忘了设 requires_grad=False,训练了 10 个小时才发现教师参数也在变。白白浪费了算力。

我的建议:如果你不确定选哪个模型,直接跑一个快速对比实验。用 10% 的数据,分别用 BERT-base 和 RoBERTa-base 做教师,蒸馏一个小学生模型,看哪个效果更好。这个时间投入绝对值得。

3.6 小结

教师模型选型是蒸馏流程的基石。记住三个要点:

  • 任务类型决定模型家族
  • 容量和数据域决定具体版本
  • 加载权重后务必冻结并切换到 eval 模式