从 Bit 到 AGI第七章:训练(Training)

训练稳定性

从 Bit 到 AGI · 第七章:训练 · Loss spike、梯度爆炸与 NaN 的排查与预防

作者 David更新于 第 114 篇(共 186 篇)

训练稳定性(Training Stability)指 loss 曲线平滑下降、无数值崩溃(NaN/Inf)、无突发 spike。预训练 1T token 长跑中,一次未处理的 spike 可能浪费 数十亿 token 的 GPU·小时;对齐阶段 RM hacking 也会导致 loss 假降、质量真崩。

直觉:高速公路上突然急刹

稳定训练像匀速巡航;spike 像急刹——有时能恢复,有时后车追尾(梯度爆炸 → 权重 corrupt → 全程 NaN)。

LLM 训练栈有多层「安全带」:梯度裁剪、warmup、混合精度 选择、数据去重、MoE 负载均衡。

定义

常见异常信号:

信号阈值(经验)含义
loss spike单 step > 2× 滑动平均坏 batch / LR 过高
grad norm> 1.0(clip 前)即将爆炸
NaN/Inf任意立即停止、回滚 checkpoint
PPL 突升val +20%过拟合或数据污染
MoE aux loss> 0.1路由崩溃

恢复策略:回滚到最近 stable checkpoint,降 LR 10–50%,跳过可疑 data shard,继续训。

例子 1:预训练 spike 的真实成本

7B,512 GPU,全局 4M token/step,在 step 120,000 发生 spike 未处理:

项数值
spike 后仍跑到 step 125,0005k step × 4M = 20B token
20B token GPU·小时20B / 1T × 40,400 ≈ 808 GPU·小时
若 weights 已 corrupt808 GPU·小时作废 + 回滚重跑

若每 2000 step 存 checkpoint + 自动 NaN 检测停训:最多损失 2000 step = 8B token ≈ 323 GPU·小时。

例子 2:SFT 不稳定对比

7B LoRA,peak LR 2e-4 vs 1e-3:

配置step 50 lossstep 200结果
2e-4 + warmup 501.81.35正常
1e-3 无 warmup3.2→NaN—~6 GPU·小时浪费
2e-4 + 无 grad clip1.9spike@180可恢复

LoRA 总预算仅 ~6 GPU·小时,一次 NaN 占 100% 重跑——小项目更要保守 LR。

量化:稳定化技术清单

技术预训练SFT/LoRA效果
Grad clip (max_norm=1.0)✓✓防爆炸
Warmup✓✓起步稳
BF16 vs FP16BF16BF16减 overflow
Weight decay 0.1✓0.01正则
Dedup 数据✓✓✓减重复 spike
z-loss (logit L2)部分模型—压 logits 极端值

全局范数裁剪:g←g⋅min⁡(1, τ/∥g∥2)g \leftarrow g \cdot \min(1,\ \tau/\|g\|_2),典型 τ=1.0\tau=1.0。

深入:监控栈与自动熔断

生产训练应 每 step 记录:loss、grad_norm、LR、tokens/sec、MFU(Model FLOPs Utilization)。MFU 低于 25% 说明 IO/通信瓶颈,同样 1T token 墙钟拉长 2–4×,等价多烧 29k–58k GPU·小时(7B)。

自动熔断规则:

条件动作
loss NaN立即停止,回滚上一 stable ckpt
grad_norm > 10 连续 3 step降 LR ×0.5,跳过当前 shard
tokens/sec 跌 >30%检查 checkpoint 写入 / 网络
val PPL 单点 +15%暂停,查 data shard 污染

GRPO 长 RL 会出现 语言崩溃:entropy 突然 低于 1.0 while reward 仍升——应 早停 + 降 KL β,而非继续烧 100M+ 生成 token / 100+ GPU·小时。

动手试一试:梯度裁剪

import torch
import torch.nn as nn

model = nn.Sequential(nn.Linear(128, 128), nn.ReLU(), nn.Linear(128, 10))
opt = torch.optim.AdamW(model.parameters(), lr=1e-3)
x, y = torch.randn(32, 128), torch.randint(0, 10, (32,))

for step in range(100):
    loss = nn.functional.cross_entropy(model(x), y)
    opt.zero_grad()
    loss.backward()
    total_norm = torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
    opt.step()
    if step % 25 == 0:
        print(f"step {step} loss={loss.item():.3f} grad_norm={float(total_norm):.3f}")

常见误区

  1. 「spike 后会自己好」 — 大模型常不会;可能进入高 loss 盆地。
  2. 「只监控 train loss」 — 并行跑 小 val PPL;train 降 val 升 = 过拟合或 hack。
  3. 「稳定性只在大预训练重要」 — GRPO 长 RL 同样会语言崩溃。

小结

训练稳定性靠 clip + warmup + BF16 + 好数据 + 频繁 checkpoint;7B 预训练一次 blind spike 可浪费 ~800 GPU·小时(20B token)。监控 grad norm 与 val PPL,NaN 即停、回滚。

本章完结,阅读 本章总结。

延伸:确定性、种子与复现

torch.use_deterministic_algorithms(True) 可提升复现性,但 tokens/s 降 10–30%——大预训练常只要求 loss 曲线同形,非 bit-exact。LoRA 6 GPU·小时 实验应 固定 seed、记录 data order、保存 tokenizer 版本;「第二次 loss 不同」常是 flash attention 非确定 或 shuffle。NaN 时 dump 问题 batch 的 input_ids(脱敏)到 json,100 条足够定位 bad token。预训练 spike 后 不要 仅从当前 step 续训——回滚 1–3k step 的 checkpoint 再降 LR,否则 corrupt 权重 浪费后续全部 token(20B token ≈ 808 GPU·小时)。

本页目录