预训练
这一步在整条主线的哪里
到这一节,「训练」二字终于名副其实。
M1 处理了数据、M2 搭好了架构。但那个模型现在毫无用处——权重是随机初始化的,你问它什么,它吐出来的都是乱码。预训练要做的,是让模型反复做一件事:给它一段文本的前半截,预测下一个 token;预测错了就调整权重让它下次错得少一点。在海量文本上重复几十亿次,模型就在这个过程里被迫学会了语法、事实、推理的雏形——因为要准确预测下一个词,这些都得懂。
上游: M1 的分词器 + M2 的模型架构,两者已就位。
本节: 真正烧 GPU 训练——损失函数、优化器、学习率、混合精度、看懂 loss 曲线,以及一个绕不开的大问题:该训多大的模型、喂多少数据。
下游: M4 把这个”只会续写”的预训练模型,微调成”会回答问题”的助手。
怎么衡量「预测得对不对」,又怎么让它变好?
一个损失函数 + 一个优化器,就是训练的全部引擎。
「预测下一个词」这个任务,模型的输出其实是一个概率分布:对词表里每个词,给出”下一个是它”的概率。比如输入「今天天气真」,模型对「好」给 60%、对「热」给 20%。
| 问题 | 答案(本节的两个主角) |
|---|---|
| 怎么把「预测得对不对」变成一个可计算的数字? | 交叉熵损失:真实词是「好」而模型只给 60%,损失就是 −log(0.6)。给得越高损失越小,越离谱惩罚越重。 |
| 有了这个数字,怎么让它变小? | 梯度下降 + 优化器:算出损失对每个参数的梯度,用 AdamW 按梯度更新参数,重复几十亿次。 |
听起来简单,但魔鬼在细节:学习率调大一点就发散(loss 变 NaN)、调小一点几百步都不动;显存永远不够;训到一半 loss 卡在平台期。这些”工程手感”才是预训练真正难的地方——下面的实验让你亲手体会一次。
训练引擎的零件 + 一个绕不开的规模问题
这一节概念最多,但都围绕一件事:怎么让 loss 又快又稳地下降。
交叉熵损失与困惑度
交叉熵损失只看一件事:真实那个词,你给了多大概率。loss = −log(p_真实词)。给 90% → loss=0.10;给 10% → loss=2.30。给得越低惩罚越重,且是指数级加重。
**困惑度(perplexity)**是 loss 取指数:PPL = e^loss。直觉是”模型在犹豫的等可能选项个数”:PPL=1 表示完全确定;PPL=10 表示把握相当于”在 10 个词里瞎猜”。训练时盯 loss,汇报时常用 PPL。
试三档:① 拖到 90%+ 看 loss 趋近 0;② 拖到 10% 以下看 −ln 怎么指数级爆炸;③ 注意 60%→90% 和 10%→40% 的 loss 降幅完全不同——训练初期 loss 掉得飞快、后期越来越慢,根源就在这条曲线的形状。
AdamW:为什么不是普通的 SGD
有了 loss 就能算梯度。最朴素的做法是 SGD(参数 −= 学习率 × 梯度),但训 LLM 几乎都用 AdamW,因为它给每个参数自适应的步长——梯度一直很大的参数走小步(防震荡),梯度很小的走大步(防停滞)。🔍 W 是什么
AdamW 的 “W” 是解耦的权重衰减。有意思的是论文标题里根本没有”AdamW”——它叫《Decoupled Weight Decay Regularization》。贡献不是发明新优化器,而是修了一个大家都没注意到的 bug:Adam 里权重衰减的梯度被塞进梯度、又被自适应分母除掉,导致大权重该受的惩罚反而变小。解耦后衰减直接作用在参数上。
它的更新式就是下面这一行(每个参数独立执行)。M3 讲的显存大头、“每参数 12 字节”,全部能从这行公式里读出来:
公式看完,放到真实地形上看它们各自怎么走——同起点、同学习率,三个优化器赛跑:
地形是 f = 0.5x² + 8y²:y 方向比 x 方向陡 16 倍——损失面像一条狭长山谷,这正是真实训练的常态(不同参数方向的曲率天差地别)。hover 轨迹上的任何一个点,看那一步的全部数值。
三件事:① 默认学习率下看三条轨迹的形状差:SGD 锯齿、动量过冲、AdamW 直奔谷底;② 把 η 拖过 0.125——SGD 和动量当场发散,AdamW 还稳着(自适应分母在陡方向自动踩了刹车);③ hover 任意轨迹点,看那一步的 θ、梯度、m、v 具体数值——上面公式里的每个符号都在这。
学习率:warmup + cosine 衰减
学习率是最难调、也最致命的超参:太大 loss 直接发散成 NaN,太小几千步都不动。现代训练几乎都用同一套调度:
- warmup(预热):前几百步让学习率从 0 线性爬升。因为初始权重随机,一上来用大学习率会剧烈震荡甚至发散——先小步让模型”稳下来”。(经验值:warmup 取总步数的 1%~10%,常用 3%。)
- cosine 衰减:爬到峰值后按余弦曲线缓慢降到接近 0。前期快速学、后期精细调。
上面两句话描述的是一条曲线——与其读文字,不如直接把它画出来、拖着玩:
前沿注脚 · cosine 还是 WSD?WSD 的卖点是「随时可停」:稳定段任意位置截断、补一小段衰减就能出一个可用模型。 但 Kimi K3 技术报告 §3.2 做了一次公平对比——两种调度各自独立跑超参搜索(报告明说:两者最优超参差别很大,共用一套等于偏袒其中一个), 在各自最优设置下比较,结论是 cosine 的最终 loss 更低,所以 K3 用了 cosine。 (这是 K3 报告的自报结论,尚无第三方独立复现;值钱的是那套「两边各自调优再比」的方法论。M7 会展开。)
试三件事:① 把 warmup 比例拖到 0%——曲线开局就是满血峰值,这正是上一个实验(loss 诊断器)里「关掉 warmup + 大学习率 → 开头就发散」的那个配置;② 打开 constant 和 WSD 三条一起看,然后在图上移动鼠标,读同一步上三种调度各自的 η 具体数值——差距在末端最刺眼;③ 把总步数从 1k 拖到 100k,看 warmup 段和衰减段的绝对步数怎么跟着变:调度是按比例定义的,不是按绝对步数。
混合精度:bf16 为什么比 fp16 更适合训练
用 32 位浮点(fp32)存所有数值最精确,但显存翻倍、算得慢。混合精度用 16 位做大部分计算、关键处保留 fp32。16 位有两种:fp16 和 bf16。同样 16 位,bf16 牺牲精度换取更大的数值范围(指数位和 fp32 一样多)。训练时梯度可能非常小或非常大,fp16 范围不够会溢出(inf/nan),bf16 的大范围正好扛得住。所以现代训练几乎都用 bf16。
下面第一个实验是 loss 曲线诊断器——亲手调学习率、开关 warmup,看 loss 怎么正常收敛、发散成 NaN、卡平台期。这些”手感”看十遍文字不如自己调一次。
试三档:① 学习率拉到最右(太大)→ loss 震荡飙升变 NaN;② 拉到最左(太小)→ 几百步几乎不降;③ 中间合适 → 平滑下降。再关掉 warmup 把学习率调大,看开头就炸——这就是 warmup 存在的理由。
显存都花在哪:一个反直觉的事实
训练时显存不够是常态。多数人以为主要是”参数”,其实优化器状态才是大头。以 Adam + 混合精度为例,每个参数要存:fp16 参数、fp16 梯度、以及 Adam 的 fp32 参数副本 + 一阶动量 + 二阶动量。那三份 fp32 往往占到显存的一半以上——这就是为什么”省显存”的技术(8-bit 优化器、LoRA)优先砍这里。下面第二个实验实时画给你看。
Scaling Laws:该训多大、喂多少数据
固定算力预算,该把它花在”训一个大模型”还是”喂更多数据”上?这就是 Scaling Laws 回答的问题。这里有一段教科书级的认知翻转:
- Kaplan 2020:把模型训得尽量大,用相对适中的数据,在收敛前就停。
- Chinchilla 2022 直接推翻了它:模型大小和训练 token 数应该等比例扩展——参数翻倍,数据也要翻倍。社区据此提炼出”参数量 × 20 ≈ token 数”的经验法则。Chinchilla 用同样算力,把参数砍到 Gopher 的 1/4、数据翻 4 倍,全面反超。
这两条结论直接冲突——冲突本身就是最好的教材。Chinchilla 的整套结论,来自拟合下面这条损失公式:
同样的算力,Kaplan 让你训更大的模型、喂相对少的数据,Chinchilla 让你参数和数据均衡扩展。GPT-3(175B,只喂了 300B token)就是 Kaplan 时代的产物——按 Chinchilla 它其实训得远不够充分。
FlashAttention:不改结果,只改怎么算
M2 的注意力要算一个 N×N 的矩阵(N 是序列长度)。序列一长,这个矩阵占的显存和读写就爆炸。FlashAttention 的洞察是:GPU 的瓶颈不是算力而是显存读写(IO)——它用分块(tiling)技巧,在不把完整 N×N 矩阵写进显存的前提下算出完全相同的结果。GPT-2 上实测约 3× 加速,纯工程优化,现在是训练标配。
上面三个实验,就是本节的核心
调一次学习率、看一眼显存分配、对比两条 Scaling Law,手感就有了。
回到上面四个交互,依次做:
- 交叉熵计算器:拖概率看 loss 的指数形状——理解”训练初期掉得快”的根源。
- loss 诊断器:把学习率拉满看它炸成 NaN,拉到最小看它卡住,中间看它健康下降;再关掉 warmup 看开头发散。
- 显存可视化:拖动参数量,盯着橙色那块(优化器状态)——它始终是最大的一块。
- Scaling 计算器:调算力预算,对比 Kaplan 和 Chinchilla 给出的参数量/数据量差多少。
本模块的”真模型实验”是跟着 Karpathy 的 build-nanogpt 走一遍:他从空文件到训完 GPT-2 124M,每个 commit 对应视频里的一步——AdamW、梯度裁剪、warmup+cosine、bf16、FlashAttention 逐个加进去,每加一个都能看到吞吐/loss 的真实变化。
看什么: ① commit 历史就是”每个优化值多少”的实验记录——bf16 一项吞吐从 ~3200 tok/s 提到 ~10500;② 对照上面 loss 诊断器里你调过的超参,看他实际选了什么值、为什么。
真正训练我们的小模型
记住分工:代码 AI 来写,训练决策你来做。
本模块的项目任务单
| 步骤 | 你的决策 / 动作 | 说明 |
|---|---|---|
| 1. 定 token 预算 | 按 Chinchilla:模型 ~50M 参数 × 20 ≈ 10 亿 token | 用上面计算器验证 |
| 2. 让 AI 写训练循环 | AdamW + warmup+cosine + bf16 + 梯度裁剪 + checkpoint | 约 100 行,参考 build-nanogpt |
| 3. 调学习率 | 先用小数据跑几百步,确认 loss 在降、没发散 | 能看懂 loss 曲线是正常/发散/卡住(上面练过) |
| 4. 正式训练 | 盯 loss/PPL 曲线,记录 checkpoint | 会遇到 loss spike,记下来,这是常态 |
| 5. 验收 | 让模型续写一段,看是否”像话”了 | 能连贯成句就说明预训练成功 |
成本要有现实预期: 调研实测——nanochat 训一个 561M 模型,8×H100 约 2 小时 / $48。我们的更小、更省。但训出来就是个”幼儿园水平”的续写模型(M4 才让它会回答问题)。价值在于全流程你亲手跑通了,不在模型多强。
预告 M4:这个预训练模型只会”续写”——你说”今天天气”,它接”真好”,但你问”今天天气怎么样?“它可能接”这个问题问得好呀”而不回答。因为它只学过”预测下一个词”,没学过”回答问题”。M4 的 SFT 就教它这个。
常见的坑 + 该带走的
| 坑 | 症状 / 后果 | 怎么办 |
|---|---|---|
| 学习率太大 | loss 震荡后飙升成 NaN | 调小 + 用 warmup |
| 没加 warmup | 训练开头几步就发散 | 让学习率从 0 爬升 |
| 用 fp16 而非 bf16 | 训到一半梯度溢出变 inf/nan | bf16 数值范围大更稳 |
| 以为显存主要花在参数上 | 估算严重偏低、爆显存 | 优化器状态才是大头 |
| 盲信”参数×20” | 当铁律 | 那是 Chinchilla 计算最优点,现代模型为推理便宜常刻意”过训” |
| loss 卡平台期就放弃 | 误以为失败 | 平台期后常突然下降;真发散(NaN)才要停 |
这一模块你应该带走的
- 训练只有一个任务:预测下一个词;loss = −ln(p_真实词),你亲手拖过那条指数曲线;
- PPL = e^loss,直觉是”在几个词里瞎猜”;
- AdamW = 自适应步长 + 解耦权重衰减,它的三份 fp32 状态是显存大头;
- 学习率是最致命的超参:warmup 从 0 爬升 + cosine 衰减是现代标配;
- bf16 用精度换范围,训练比 fp16 稳;
- Chinchilla 推翻了 Kaplan:参数和数据要等比例扩展(×20 是经验值不是铁律);
- FlashAttention 不改结果只改算法:IO 才是瓶颈;
- 看懂 loss 曲线的三种形态:健康下降 / 发散 NaN / 卡平台——你在诊断器里都见过了。
概念索引(本模块登场): 交叉熵损失 · 困惑度 PPL · 梯度下降 · AdamW · 权重衰减 · warmup · cosine 调度 · 混合精度 bf16/fp16 · 显存分配 · 优化器状态 · Scaling Laws · Kaplan · Chinchilla · FlashAttention · loss spike · checkpoint
有不明白的? 随时在对话里问我,我会记到 05-问答记录/M3-预训练-问答.md。
想往下钻,按你愿意花的时间选
每条都经实测验证。Karpathy 那个 4 小时视频是本模块的骨架。
🎮 想更直观 10–30 分钟
🔬 想吃透原理 1–3 小时
📄 想读原文 按需
我替你排除了什么: 「十分钟速通优化器」类速通 · CSDN 同质化转载 · TensorBoard/wandb 教程(教画图 ≠ 教看图)· 各类推理/量化显存计算器(算的是推理不是训练显存)。
另注:李沐没有 Scaling Laws / Chinchilla / FlashAttention 的精读视频(查了他 paper-reading 仓库 32 篇全表核实);2 个 Karpathy B站字幕版已 404,只收实测可用的 BV12s421u7sZ。