TT Lab
开始
学习 学习路径 课程

MiniMind — 亲手从头到尾训练一个小型语言模型

小模型里,记住与学会的界线格外清晰

在 TT Lab 中继续学习

一句话总结

评估要超越“损失很低”,去分辨 能做什么、不能做什么。用困惑度和 BPB 测量作为语言模型的质量,从训练损失与验证损失之间的差距看过拟合,并把在没见过的问题、位数和长度上崩溃的样子用数字留下来。100 万参数的模型,这条界线非常清晰,所以可以把大模型里模糊地混在一起的现象一个个单独拿出来看。

为什么需要它

在前面的模块里,损失下降得很顺利,SFT 模型对训练时见过的问题也全都答对了。可是,这个模型能称为“了解村庄的聊天机器人”吗?MiniMind 的 README 原样登出了自己 zero 模型的对话示例——对中文问题回答得像模像样,对英文问题却拼凑出毫无意义的话。并且写道“事实知识和泛化能力依然有限”。评估就是找出这个“有限”从哪里开始,不知道这条界线,就会把模型用在错误的地方。

工作原理

困惑度与 BPB。困惑度是 exp(平均损失),可以理解为“模型在每个令牌上平均在多少个候选之间犹豫”。不过它会随令牌的大小而变。BPB 是把总损失(奈特)除以 ln 2 换算成比特,再除以同一段文本的 字节数,所以分词器不同也能比较。我们的基准预训练模型,验证困惑度为 2.48,BPB 为 0.21。在同一位置上,基准 SFT 模型的困惑度会变成几百——它只用 1e-3 这么大的学习率学了聊天格式,忘掉了续写语料的能力(灾难性遗忘)。

过拟合。只用 100 篇文档训练得久了,训练损失一直下降,验证损失却从某一刻开始上升。这就是模型不再学规则,而开始背那 100 篇的时刻。这门课程的语料是套模板做出来的句子,所以过拟合反而来得晚——如果是真实的文章,差距会拉开得更早。

见过的与没见过的。基准 SFT 模型对 SFT 中见过的问题,100% 都能回答。可是对于预训练语料里出现过、但在 SFT 里 没见过那种问法 的事实,正确率是 0%。要分清原因,得先看预训练模型是否知道那个事实——让它续写“○○ 村的特产是”,会发现守护动物大多能答对,特产却只答对几个。知道的东西也无法以提问的形式取出来,不知道的东西自然更取不出来。加法就不同了——没见过的一位数加法配对,它能答对 77%。重复出现的规则能泛化,必须一条条背下来的事实则无法泛化。

分布外。只见过一位数加法的模型,被问到两位数加法时,会给出格式正确的一位数答案。只用 128 个令牌训练的模型,放入 256 个令牌时,靠后位置的损失会上升。RoPE 用的是相对位置,所以不会崩溃,但在没见过的距离上会不够准确。MiniMind 在推理时用扩展 RoPE 的 YaRN(inference_rope_scaling)来处理这个问题,而 eval_llm.py 的参数说明写道,它只解决位置编码的问题——并没有赋予处理长文本的能力本身。

在现场相遇的样子

评估公司内部模型时,如果只收集与训练时所用问题相似的内容,分数看起来会虚高。必须另外准备一个评估集,把问题的形式、主题、长度一格一格地移到训练分布之外,才能看出界线。另外,SFT、DPO 之后,还要重新测量原有能力(续写语料的困惑度、通用知识)——只测新教的东西,忘掉的东西就哪里都没有记录。看到错误的回答时,先分清是“不知道、知道却取不出来,还是超出了范围”。这三种的处方不同——不知道就补数据,取不出来就补提问形式多样的 SFT 数据,超出范围就放入那个范围的数据,或者缩小使用范围。

本课程与 MiniMind 原版的不同之处

MiniMind 的 eval_llm.py 是加载训练好的权重、让它回答准备好的几个问题并打印速度(tokens/s)的工具——由人来读并判断。除此之外,MiniMind 还用 C-Eval、C-MMLU、OpenBookQA 这类外部基准来测量模型——它们是上万道选择题,所以 64M 的模型也能判断是否比随机更好。1M 的模型在这类基准上与随机无法区分,所以这门课程把世界封闭起来(12 个村庄、100 道加法题),在里面准确地分开测量见过的、没见过的和超出范围的。封闭世界的好处是能一个个分清答错的原因,坏处是数字无法搬到外面的世界。这个模型的正确率 100%,只意味着“村庄问答做得好”,并不意味着它理解语言。制作评估集时,总要先写下这个集合代表什么。

下一项实验要做什么

测出两个基准模型的困惑度和 BPB,并用 100 篇文档做出过拟合曲线。依次测量 SFT 中见过的和没见过的问题的正确率、两位数加法、训练长度之外的损失、预训练模型是否知道事实,并把这个模型做不到的事,用报告留下来。