Pretrain 训练导言
终于进入激动人心的训练部分了。
前面几节更多是在回答“模型是什么”:Language Model 是什么,Transformer 是什么,Attention 怎么算,Tokenizer 如何把文本变成 token id。可是只知道这些定义,和真正把一个模型训练出来,中间还隔着很长的一段路。
这也是我觉得 MiniMind 很有价值的地方。它不只是给出一段模型结构代码,而是提供了一个真实、完整、又足够小的训练入口。以前我也通过 NLP 课程和各种文章学过很多概念,比如语言模型、交叉熵、优化器、学习率、梯度下降。单独看每个概念,好像都能理解;但一旦离开上下文,很快又会变得模糊。直到真正跑起 MiniMind 的 pretrain 流程,这些东西才开始连成一条线。
模型训练本身是一件非常复杂的事情。它当然有理论基础,但工程上还有大量经验性的细节:数据怎么组织,loss 怎么算,学习率怎么调,梯度为什么会爆,混合精度为什么会出 NaN,断点恢复到底保存了什么,训练日志里哪些指标真正值得看。这些问题如果只停留在抽象层面,很难形成直觉;只有真的训练一次,才会发现训练不是“调用一个脚本”这么简单。
不过也需要先说明边界。这里的讨论主要基于 MiniMind 这样的个人可复现实验,以及一类相对小规模的模型训练经验。对于真正工业级的大模型,训练规模、数据规模、并行策略和工程复杂度都会高很多。所以这一章里的结论不能直接外推到所有大模型训练场景。更合理的态度是:把 MiniMind 当成一个最小但完整的观察窗口,通过它理解 pretrain 的核心问题和常见坑。
这一章我仍然会尽量用 QA 的方式来组织。因为训练部分最适合从问题出发:为什么 pretrain 的 loss 是交叉熵?为什么不是 BCE?为什么要做梯度累积?GradScaler 到底在缩放什么?loss 下降是不是就代表模型变好了?这些问题看起来很细,但它们恰好组成了训练代码里最关键的骨架。
这一节之后,Pretrain 训练部分会先按“理论问题”和“实际操作”两条线展开。
理论部分会尽量先回答训练到底涉及哪些核心问题:
- 损失函数是什么:pretrain 为什么是 next token prediction,为什么用 Cross Entropy Loss,以及代码里的
loss_mask如何影响 loss。 - 优化器是什么:参数更新到底在做什么,为什么大模型训练里常见的是 AdamW。
- Learning Rate 如何设置和调整:学习率为什么重要,为什么需要 schedule,MiniMind 里的 cosine decay 对应什么含义。
- 数据如何设置:数据集质量、数据分布、
max_seq_len、padding、truncation、batch size 和有效 batch size 会如何影响训练。 - 训练过程中如何评估效果:training loss、validation loss、perplexity 和生成样例分别能说明什么。
这些内容都会拆成不同的小节展开。Loss 会单独成节,优化器、学习率和数据设置会放在一节里,Eval 也会单独成节。
实际操作部分则更关注训练能不能稳定跑起来,包括分布式训练、混合精度、梯度累积、梯度缩放、梯度裁剪、seed、checkpoint、可视化和断点恢复。这些内容不只是工程实现,也常常是训练中最容易踩坑的地方。
最后再回到 MiniMind 的实际训练流程,记录数据准备、训练命令、输出目录和实验现象。
我也建议在阅读训练部分之前,先把 MiniMind 的最小训练流程跑起来。哪怕模型效果很弱,哪怕输出还前言不搭后语,只要完整跑过一次,后面再看 loss、optimizer、AMP、checkpoint 和 eval,就会有完全不同的感觉。