1. Token到底是什么:大模型眼中的“文字碎片”
先说一个很多人困惑的现象:你在API账单里看到的token用量,跟实际字数经常对不上。中文一句话可能被切成七八个token,英文一个单词却常常只占一两个token。我第一次调大模型接口时也懵过——明明只发了三百字,账单却显示耗了一千多token,一度怀疑是不是统计有问题。后来才明白,token从来就不等于“字”,它是模型处理文本的基本单位,理解为“文字碎片”更准确。
Tokenization(分词)是大模型的第一道工序:把一段自然语言切成模型能处理的离散符号序列。主流分词器用的是BPE(Byte Pair Encoding,字节对编码)算法,核心思路不复杂:在训练语料上统计字符或字节的共现频率,把高频出现的相邻片段逐步合并成新的“词”,反复迭代,最后形成一张词表。词表里既有完整的常见词(比如“模型”“token”),也有更细碎的子词(比如“深入理解”的木马拆成几个片段)。这样做的好处是:既能控制词表大小,又能处理训练时没见过的生僻词——遇到新词就拆成已知片段,不至于直接变成“未知字符”丢给模型。
这里有个很容易忽略的细节:不同模型的tokenizer是各自训练出来的,词表和切分规则都不一样。同一句中文,用GPT系列的分词器可能切成800个token,换另一个模型可能是650个,不是因为谁更“省”,纯粹是分词策略不同。所以现在很多模型厂商会把“每百万token价格”折算成“每百万汉字价格”来宣传,但实际换算只能是个约数。我自己在做成本对比时,都是拿同一段真实业务文本,分别调用各家tokenizer或者直接用平台的计数接口去算,绝不拍脑袋估。
从使用者角度看,token数量直接影响两件事:一是成本,二是上下文窗口的容量。上下文窗口再大,也是以token为单位计算的;你粘贴进去的资料越多,留给模型生成回复的空间就越少。理解了这一层,后面聊蒸馏时你就能明白,为什么蒸出来的小模型要在同样甚至更小的预算下干活,token利用效率反而是核心指标之一。
2. 大模型的“学习”到底在学什么:从预测下一个词到涌现能力
2.1 自监督预训练:一场规模空前的“填空游戏”
大模型的核心训练方式叫自监督学习,具体到语言模型,就是最朴素的“预测下一个词”。给模型一段文本,盖住后半部分,让它猜下一个token是什么;猜错了就调整参数,猜对了就继续。这个“填空游戏”在数万亿token的语料上反复进行,模型的参数就被逐步调整到能高概率预测出合理的下一个词。
那为什么预测下个词能产生语言理解能力?这是很多人第一次接触大模型时的疑问。一个看似微小的任务,其实迫使模型学会了海量的隐性知识:要猜得准,它得懂语法;要接得上话,它得懂语义;要回答得出事实,它得记住语料里的常识。就像你在一个陌生城市天天做“猜下一站”的游戏玩一年,最后你肯定把整个地铁线路背下来了。语言模型也是这样——预测下一个词是手段,学会语言的规律和世界的知识是结果。
2.2 人类反馈微调:从“会说话”到“懂规矩”
不过,单靠预训练出来的模型,用起来体验其实很差。它会说话,但可能答非所问,可能输出有害内容,也可能罗里吧嗦。这就引出了后面的环节:监督微调(SFT)让模型学会按人类期望的格式回答问题,RLHF(基于人类反馈的强化学习)则让模型在多个候选回复中学会选那个更符合人类偏好的。
这里有一个值得注意的点:这些阶段的目标函数不一样。预训练学的是“概率”,微调学的是“偏好”。所以你拿大模型做同一个任务,不同层级的模型表现差异明显——基座模型像一个刚毕业的聪明学生,知识面很广但不懂职场规矩;Chat版本才是经过入职培训的老员工,知道怎么把话说到点子上。
2.3 “涌现”不是魔法,是规模带来的质变
“涌现能力”这几年被讨论得很多,什么“缩放定律”“顿悟时刻”,听着很玄。我的理解是:当模型参数和训练数据达到某个量级后,它内部学会的规律开始交叉支撑,一些没被显式训练过的能力就出现了,比如少样本学习、链式推理、代码生成。它像拼拼图,碎片少时看不出图案,碎片够了,整幅图突然清晰起来。
理解了这条训练链路:预训练(学知识)→微调(学格式)→对齐(学偏好),你对后面讲的蒸馏会有更清晰的坐标系。蒸馏本质上是在“知识”和“能力”层面做迁移,而不是在参数层面复制。
3. 蒸馏在做什么:把大模型的“内功”传给小模型
3.1 一句话理解蒸馏:学生不抄答案,抄解题思路
模型蒸馏(Knowledge Distillation)最早由Hinton在2015年提出,思路用一句话概括就是:用一个能力更强但推理成本高的大模型(教师模型),去指导一个体积更小、推理更快的模型(学生模型)训练,让小模型在特定任务上逼近大模型的水平。
但“逼近”不是让小模型背答案,而是让它学“解题思路”。这里的关键是软标签(soft label)的概念。传统分类任务里,标签是硬性的:一张图要么是猫(1),要么不是猫(0)。但大模型在做推理时,输出的其实是每个类别上的概率分布:它可能会给“猫”0.7、“狗”0.2、“狐狸”0.1。这个分布里藏着信息——模型认为“狗比狐狸更接近猫”,这种类别之间的相似关系,是硬标签完全无法表达的。
3.2 用温度把“软标签”的信息量撑开
为了让这些概率分布中的“暗知识”更清晰,Hinton引入了一个技巧:温度参数T。标准的softmax公式是:
[ p_i = \frac{e^{z_i / T}}{\sum_j e^{z_j / T}} ]
当T=1时就是普通softmax;T越高,分布越平坦,类别之间的微小概率差异被放大,小模型就有机会学到“这个类别跟那个类别有点接近”这类细微知识。训练时通常的做法是:用高温蒸馏出软标签指导学生模型训练,训练后期再把温度调回1,让学生模型在正常温度下也表现良好。
这个“利用类别概率分布当监督信号”的思路,跟前面讲Tokenization时提到的“信息密度”是一脉相承的:硬标签的信息量只有1比特(是不是),软标签的信息量可能有几十比特,学生模型等于拿到了一个信息量高得多的训练信号。同样的样本量下,学得更快、学得更准,这就是蒸馏“省数据”的原理所在。
3.3 不只是分类任务:从logits蒸馏到特征蒸馏
后来蒸馏从最经典的logits蒸馏一路演进,衍生出很多变种:
- 特征蒸馏:不只看最后一层的输出,还让中间层特征图也尽可能对齐,让学生模型每一层都“模仿”教师模型的表征方式。典型代表是FitNets。
- 关系蒸馏:不再要求单个样本的输出对齐,而是让样本之间的关系(比如样本A和B的距离)保持一致,适合图数据和检索场景。
- 自我蒸馏:教师和学生是同一个模型,或者学生模型从自身更深层网络蒸馏到更浅层网络,属于一种结构优化手段。
- 黑盒蒸馏:不访问教师模型内部参数和输出分布,只靠调用API收集输入输出对来构造训练数据,再微调小模型。现在很多大模型厂商的应用层蒸馏场景用的都是这种。
对你来说,最需要想清楚的第一件事不是选哪种蒸馏变体,而是:你的场景到底需要小模型继承什么?
4. 手把手走一遍蒸馏流程:以文本分类为例
前面原理讲了不少,下面用一个非常实际的例子把流程串起来。假设我有一个情感分类任务:判断一段产品评论是正向、负向还是中性。大模型(教师)已经能在这个任务上达到95%的准确率,但单次推理要几百毫秒,成本也高。我的目标是训练一个几百MB的小模型,在保持接近的准确率的同时把延迟压到毫秒级。
4.1 准备数据集:有标签没标签都能蒸
蒸馏对数据标注的要求很宽容。经典的流程是:先准备一批任务相关的输入样本(评论文本),然后让教师模型跑一遍,拿它的输出分布当软标签。也就是说,你甚至不需要人工标注的硬标签,只要输入样本足够有代表性,教师模型输出的分布就是训练信号。
但实际项目中我建议软硬标签都要:硬标签保证学生模型不跑偏,软标签提供类别间的相似结构。如果用的是公开分类数据集,硬标签本来就有;如果任务是你自己业务里的,那至少要准备几百条人工确认过的种子数据,再让教师模型在此基础上扩展。
我习惯把数据集按8:1:1分成训练、验证、测试,其中验证集要用来盯着学生模型有没有过拟合,测试集必须保证教师模型和学生模型从来都没见过,否则评估结果会虚高。
4.2 选择学生模型:先定“体量预算”
学生模型的选择不是参数越小越好,而是要在你定义好的“推理预算”内选最优。先想清楚部署环境:跑在什么硬件上?单条推理可接受的延迟是多少?显存多大?以CPU部署为例,如果延迟目标在10毫秒左右,参数规模基本就被锁在几亿以内了。
建议从简单模型开始,跑通全流程再逐步加复杂度。不要一上来就搞BERT-large级别的蒸馏,先在同样结构的模型里留足优化的空间。
4.3 设计损失函数:二合一才是精髓
蒸馏的损失函数通常由两部分组成:蒸馏损失(跟教师模型软标签之间的KL散度)和任务损失(跟真实标签之间的交叉熵)。总损失是两者的加权和:
[ L = \alpha \cdot L_{task} + \beta \cdot L_{distill} ]
其中α和β是权重系数,常见做法是让蒸馏损失权重稍大一些(比如α=0.3,β=0.7),因为教师模型已经提供了比较可靠的监督信号。但这里有一个需要手动调的点:如果任务本身对准确性要求极高,硬标签的权重可以适当提高;如果你希望学生模型学到更多类别间的细微差异,就提高蒸馏损失的权重。
4.4 训练参数与验证指标:别只盯着准确率
训练时的关键参数我整理成一张表,这组参数是基于常见实践调出来的初始值,不同任务可在此基础上微调:
| 参数 | 建议值 | 说明 |
|---|---|---|
| 温度T | 2-6 | 太低软标签信息量不够,太高会把分布彻底抹平 |
| 学生模型学习率 | 2e-5 ~ 5e-5 | 从教师模型常用学习率降一个量级起步 |
| 蒸馏损失权重β | 0.6-0.8 | 与任务损失权重互补 |
| batch size | 32-64 | 显存允许的前提下尽量大 |
| 训练轮数 | 3-5 | 小模型容易过拟合,监控验证集 |
评估不能只看准确率,还要看延迟和吞吐。蒸馏的意义本来就是用精度换速度,你得把这个“换算率”量化出来:如果精度只掉了1.5个点,但推理速度快了20倍,这笔交易很可能非常划算。
4.5 关键操作顺序:从大模型采样到小模型上线
整个流程可以归纳成五个步骤,按顺序执行:
- 用教师模型处理所有训练输入,保存下每个样本的logits(最后一层输出,不取argmax)。
- 将logits除以温度T,做softmax,得到软标签。
- 加载学生模型,用软标签和硬标签组合成的损失函数进行训练。
- 在验证集上对比学生模型与教师模型的准确率分布,观察是否出现明显掉点。
- 部署后先跑灰度流量,用线上真实请求验证效果,再逐步把流量切过去。
我第一次做蒸馏时卡在最简单的一步上:教师模型的输出忘了除温度,直接用普通softmax算的软标签,结果训练出来的学生模型虽然准确率还行,但在类别边界上的判断非常僵硬,看起来就是什么都不会但能压线过。后来检查代码才发现温度参数根本没传进去。这种细节坑,文档里一般不会提醒你。
5. 蒸馏实操中的关键决策:软标签、教师模型与评估指标
5.1 教师模型的可靠性比“大”更重要
一个常见的误区是:教师模型越大越好。这个逻辑在极端情况下不一定成立。大模型在特定任务上可能有过拟合训练数据的现象,或者因为本身偏好太强,输出分布与真实场景不匹配。我见过有人拿一个千亿级基座模型当教师蒸馏客服意图识别模型,结果教师模型在几个边缘类上的预测分布明显是乱的,学生模型照单全收,越蒸越差。
判断教师模型是否称职,最简单的办法是抽一批验证样本,人工检查教师模型给出的软标签是否合理:“不相关”类别的概率是不是真的比“高度相关”类别的概率低很多?如果分布平滑得像随机噪声,要么换教师模型,要么在蒸馏损失里调高任务损失的权重,用硬标签稳住大方向。
5.2 数据质量与数量:软标签不万能
蒸馏虽然能缓解对标注数据的需求,但它对“教师模型输出质量”的依赖转移成了新的约束。教师模型喂给你的软标签如果系统性偏向某个类,学生模型就会被带偏。这里的应对策略是:对教师模型做一定程度的校准,或者在损失函数里以更高的权重来使用人工标注的硬标签。
至于数据量,我实测下来,在文本分类任务上几千到几万条样本量区间内,蒸馏收益非常明显;但数据量越大,越接近教师模型自己训练的数据规模,同等样本数下收益会递减。不用迷信“数据越多越好”,而是要保证数据覆盖足够多的边界情况。把教师模型预测置信度最低的那部分样本挑出来,人工补充标注,再一起参与蒸馏,这样的数据质量提升远比单纯增加数量有效。
5.3 模型规模悬殊时:加一个中间层适配器
教师模型大、学生模型小,直接让最后一层logits对齐,小模型往往学不动。原因很朴素:学生模型的表征空间和教师模型完全不是一个“维度”,强行让输出靠近,学生只能自己硬拟合,结果就是泛化能力差。
一个被验证有效的做法是:在两者之间插入一个适配层(通常是简单的线性变换或多层感知机),先让适配层吸收掉表征空间的差距,再逐步把适配层去掉或简化。蒸馏不仅仅是调参问题,更是一个架构匹配问题。
5.4 评估时的“物理限制”:模型能力有天花板
最后必须摆正预期:蒸馏无法超越教师模型的天花板。如果你的教师模型在某个任务上只有85分,学生模型能蒸到82分已经算非常优秀了,而不是幻想它能反超。所以做蒸馏项目前,第一件事就是先把教师模型的基准线打出来,然后跟你业务上能接受的最低精度做对照,决定这笔“蒸馏投资”值不值得做。如果教师模型本身就达不到业务要求,那该做的不是蒸馏,而是换教师模型或者继续微调大模型。
6. 蒸馏之外:当大模型能力下沉还有哪些路径
蒸馏是模型小型化的经典路径,但不是唯一路径。实际工程里,大模型能力下沉通常有四条路线:
- 量化:把模型权重从FP16压到INT8甚至INT4,牺牲少量精度换取大幅内存和速度优化。这个通常是蒸馏后的“下一道工序”,两者兼容。
- 剪枝:去掉网络中不重要的连接或注意力头,结构上做减法。
- 早停和动态推理:简单样本走浅层就输出,难样本才走到全深度,适合处理速度要求苛刻的场景。
- 软硬件协同优化:用推理框架(如vLLM、TensorRT-LLM)做算子融合、缓存优化。
实际操作中,蒸馏和量化经常一起上:先用蒸馏把模型从7B压到1B级别,再做INT8量化进一步减半内存占用。两条路线叠加后,模型体积降到原来的十几分之一,推理速度提升明显,精度损失控制在可接受范围内。
了解这些路径,是为了帮你建立一张“能力下沉决策树”:先判断瓶颈是精度还是延迟;如果延迟不达标,优先试量化;精度不够,再考虑蒸馏或换更强的教师模型。不同场景的落地方案会完全不同,没有万能解。
7. 踩坑记录:我跑蒸馏时真实遇到过的三个问题
7.1 教师模型输出没除温度,软标签成了“硬标签”
这是新手最容易忽略的细节。很多开源代码里的KD实现默认温度是1,你一旦忘了给教师模型的输出除以温度,softmax出来的分布就非常尖锐——接近one-hot编码。这样的软标签几乎没有提供类别间相似度信息,蒸馏效果跟直接有监督微调差不多。排查方法很笨但有效:把软标签打印出来看一下,如果绝大多数概率都集中在GT类上,分布跟硬标签一样干净利落,那基本就是温度参数没生效。
7.2 小模型学习率太激进,蒸馏损失怎么都降不下来
蒸馏对小模型来说任务并不轻松:它要同时拟合硬标签和软标签,目标函数比普通微调更复杂。一上来就照搬预训练时的学习率,往往导致震荡,损失曲线看着像心电图。我的经验是从小学习率2e-5起步,先让模型稳定收敛,再根据验证集表现浅调。这比一开始就用大学习率、然后又回头排查半天损失不收敛要省时间。
7.3 只在训练集上蒸,线上效果崩了
蒸馏模型最容易得的“职业病”是过拟合到教师模型的输出分布上。因为教师模型也是模型,它有自己的偏差和盲区;学生模型如果只见过教师模型的输出,学到的就是“教师模型的偏见”,而不是“任务本身的知识”。解决办法之前说过:保留一部分真实硬标签参与损失计算,并把教师模型置信度最低的那部分样本找出来做人工标注,合成进训练集。这两个动作能显著提升小模型的泛化能力。
8. 一条完整的学习路线:从Token到蒸馏怎么串起来学
如果这篇博文是你入门大模型的第一篇,我建议你把内容按下面的顺序重读一遍,形成一个完整闭环:
- 理解Tokenization:随便找一个在线分词工具,把一段中文切分后数数token数,感受一下“字”和“token”的差别。
- 跑通一次微调:用开源的预训练模型在公开数据集上做一次分类或生成微调,你不需要自己从头训练,而是学会加载权重,理解“预训练+微调”的范式。
- 跑通一次蒸馏:按我上面给的流程,拿一个已经微调好的模型当教师,蒸馏到一个小模型上,记录精度和速度的变化数字。
- 叠加量化部署:把蒸馏后的小模型再量化一次,部署到CPU上测试延迟,完成“能力下沉”的完整链路。
上海交大的《动手学大模型》开源项目我翻过,对新手很友好,里面有大量可直接运行的代码示例,适合配合这条路线做配套练习。GitHub上搜“LLM cookbook”类项目也可以,关键是要动手把代码跑起来,不是只读文档。
大模型的原理看起来深不见底,但拆开来看,每一步都是工程问题:Token化是预处理格式,预训练是算力换能力,微调是数据换适配,蒸馏是算力换效率。理解了这四层,你再看任何所谓的新技术,本质上都逃不开这几个问题的排列组合。