把这次训练真跑起来 — 显存怎么算、曲线怎么读、什 么时候该收手
这一章讲四件事: 这次训练到底要多少显存(以及那个数为什么大得吓人); 训练跑起来之后,那条曲线的七种形状分别在说什么; 再收一批数据还划不划算,怎么在一张图上当场看出来; 以及一句能当场用的判据——什么时候该停在这一步,什么时候该毕业到下一章。
它在全书链条里的位置: 第 05 章讲了一条训练样本长什么样, 这一章讲把它们真的喂进去会发生什么。 这一章末尾那句判据, 是通向第 07 章的唯一入口。
★ 这一章兑现第 01 章的一笔账:为什么装载和微调是两笔完全不同的账。
1. 先看现象:一张 80GB 的卡,装不下一个 70 亿参数的训练
第 01 章算过一笔账:700 亿参数的模型光装进显存就要 140GB。 很多人由此得到一个错误的推论:那 70 亿参数的模型只要 14GB,一张卡绰绰有余。
推论错在:那 14GB 只够它答话,不够它被训练。
真跑 一次会看到什么:
① 你有一张 80GB 的卡,模型是 70 亿参数,按半精度算 14GB
② 加载完毕,显存占用 14GB。看起来还剩 66GB,很宽裕
③ 开始训练,第一步就报错:显存不够
为什么?因为训练时**同时要装四样东西**,而模型本身只是第一样。
这一章从这四样东西开始。
2. 顶层全景:训练一次要经过的四道关
关 1 装得下吗? ──► 四笔显存账(§3)
装不下 → 换更小的模型 / 换更省的做法(第 11、12 章)/ 拆到多张卡上(§4)
│
关 2 跑得起来吗? ──► 单卡先跑通,再上多卡(§4)
多卡有单卡没有的死法:死锁、静默发散、一卡爆全崩
│
关 3 在往好里走吗? ──► 读曲线(§5)。七种形状,各对应一种病因
⚠️ 训练损失接近零 = 警报,不是成功
│
关 4 真的学到了吗? ──► 留出集 + 四种验证动作(§6)
「看着还行」不算验证
│
关 4.5 再加数据还有没有用? ──► 把表现对数据量画出来(§8)
★ 曲线趴平了不等于成了,也不等于砸了 —— 要看趴在什么高度
│
关 5 该收手了吗? ──► 一句话判据(§9)
「我能亲手为这个输入写出完美回答吗?」
图说:**这几关的顺序不能换。** 关 3 之前谈效果没有意义,
关 4 之前谈上线没有意义,**关 4.5 之前谈「要不要再收数据」全是拍脑袋。**
主走查: 还是那 300 封拒付信,底座取 70 亿参数,一路走完这五关。
3. 关 1:训练时的显存是四笔账
四笔账各是什么
作者把它拆得很清楚1:
| 这一笔 | 装的是什么 | 有多大 |
|---|---|---|
| ① 参数 | 模型本身那些数 | 每个参数 2 个字节(半精度) |
| ② 梯度 | 每个参数「该往哪挪」的那个方向 | 和参数一样大,每个参数 2 个字节 |
| ③ 优化器状态 | 优化器为每个参数记的账(第 05 章讲过它会按历史梯度调节步长,这些历史就存在这儿) | 通 常是参数的两倍,每个参数 8 个字节 |
| ④ 中间结果 | 前向计算过程中每一层留下的东西,反向时要用 | 不固定,随一次喂几条、句子多长而变 |
加起来的经验数是:半精度全量微调大约每个参数 16 个字节1。
走查:70 亿参数要多少
70 亿参数 × 16 字节 = 112GB
├ 参数 70 亿 × 2 = 14GB
├ 梯度 70 亿 × 2 = 14GB
├ 优化器状态 70 亿 × 8 = 56GB
└ 中间结果 还没算进去,另计
→ 作者的原话:这解 释了**为什么 80GB 的卡也只是勉强,
以及为什么那些「只训一小部分」的做法这么流行**[^1]。
这个 112GB 要和第 01 章那个 140GB 摆在一起看,否则会串:
| 那个数 | 它是什么 | |
|---|---|---|
| 第 01 章的 140GB | 700 亿参数 × 2 字节 | 只是把模型装进去、让它能答话 |
| 这一章的 112GB | 70 亿参数 × 16 字节 | 是把一个小十倍的模型训起来 |
这就是「装载」和「微调」两笔账的区别: 训练一个 70 亿的模型,比装载一个 70 亿的模型贵八倍; 它甚至逼近了装载一个大它十倍的模型的开销。 (第 01 章第 5 节许诺过「那三笔账第 06 章算」,这里还上了—— 那三笔就是梯度、优化器状态、中间结果。)
顺带一个默认值:两种半精度不一样
作者用一段专门讲这件事,因为选错会直接让训练崩2:
| 一种 | 另一种(默认选这个) | |
|---|---|---|
| 名字 | float16 | bfloat16(bf16) |
| 16 个位怎么分 | 精度多(10 位)、范围小(5 位) | 精度少(7 位)、范围大(8 位) |
| 后果 | 训练中梯度和中间结果偶尔会飙到它表示不了的大小,溢出、损失变成无效值、整轮训练报废 | 飙上去也接得住,训练更稳;代价是精度略低,实践中几乎无所谓 |
一句话口径:硬件支持就用 bf16。 只支持前一种的老硬件,需要额外小心地做数值缩放和裁剪2。
4. 关 2:装不下的时候,拆到多张卡上
书里讲了两大类做法,它们省的不是同一样东西3:
| 做法 | 每张卡上放什么 | 省了什么 | 代价 |
|---|---|---|---|
| 每张卡各算一批数据 | 整个模型的完整副本 | 什么都不省,只是快 | 显存需求一点没降 |
| 把状态切开分给各张卡 | 参数、梯度、优化器状态各存一小片,要用时通过通信凑齐 | 每张卡的显存需求大幅下降 | 多了通信开销 |
第二类是解决「装不下」的那一类。 作者说它把两类并行的好处结合起来: 每张卡只存总状态的一小部分,同时保持数据并行那种简单的编程模型3。
走查: 那 112GB 的活,切成四份分给四张 24GB 的卡,每张卡只扛 28GB。 这就是从「跑不了」变成「跑得了」的那一步。
但多卡有单卡没有的死法
作者专门用一个警告框列了三种4:
| 故障 | 长什么样 |
|---|---|
| 死锁 | 几张卡在等一个永远不会到达的通信,整个训练卡住不动 |
| 静默发散 | 梯度同步有 bug,各张卡上的模型状态开始不一样,训练悄悄地跑歪 |
| 一卡爆全崩 | 其中一张卡显存不足,整轮训练崩掉 |
注意第二种最毒:它不报错。 你会得到一个跑完了的训练和一个坏掉的模型。
由此得到一条作业顺序:先在单卡上跑通,再上多卡。 排查这些问题需要懂分布式系统,而那不是你在调模型时该分心去学的东西4。
5. 关 3:七种曲线形状,以及那个最容易误读的信号
曲线是这一步的生命体征
作者的比方是:损失曲线之于做模型的人,就像生命体征图表之于医生—— 它是「事情是不是在按该有的样子进行」的首要指标; 学会读它,是这一行最值钱的技能之一5。
而且他提醒:后训练里很多指标的行为,对习惯了传统做法的人来说相当反直觉—— 这里说的「传统做法」指的是后训练出现之前那一大类机器学习任务 (拿标注好的数据训一个模型去做分类、预测这些活)5。