minimind/course/notes/07_amp_gradient_notes.md

2.5 KiB
Raw Blame History

第7节:混合精度 + 梯度累积 + 梯度裁剪

训练流程核心机制笔记


📚 本节目录

  1. 整体训练流程
  2. 每一步在干什么
  3. 三大核心机制总结
  4. 一句话总理解

1. 整体训练流程(核心顺序)

scaler.scale(loss).backward()

if step % accumulation_steps == 0:
    scaler.unscale_(optimizer)
    clip_grad_norm_(model.parameters(), max_norm)
    scaler.step(optimizer)
    scaler.update()
    optimizer.zero_grad(set_to_none=True)

2. 每一步在干什么

(1) scaler.scale(loss).backward()

作用:AMP 防止 FP16 下溢

  • loss 先乘一个 scale(放大)
  • backward 计算梯度

目的:防止 FP16 数值太小 → 梯度变 0


(2) 梯度累积(accumulation)

每 N 步才更新一次参数

作用:

  • 模拟大 batch training
  • 节省显存

(3) scaler.unscale_(optimizer)

作用:梯度"还原"

因为之前 loss 被放大了:grad = grad × scale

所以这里要把梯度恢复到真实数值(为了梯度裁剪)


(4) clip_grad_norm_()

作用:防止梯度爆炸

数学本质:

先算整体梯度范数:

\|g\| = \sqrt{\sum_i g_i^2}
  • 如果 norm ≤ max_norm:不变
  • 如果 norm > max_norm:缩放 → g := g × max_norm / norm

直觉:不改变方向,只限制"更新步子大小"


(5) scaler.step(optimizer)

作用:真正更新参数

  • 如果检测到 NaN/Inf → 自动跳过
  • 否则正常 optimizer.step()

(6) scaler.update()

作用:动态调整 loss scale

情况 动作
出现 NaN/Inf scale ↓(变小,更保守)
训练稳定 scale ↑(变大,提高精度)

本质:自动调节 FP16 "放大倍率",保证稳定 + 高效


(7) optimizer.zero_grad(set_to_none=True)

作用:清空梯度

set_to_none=True → 更省显存 + 更快


3. 三大核心机制总结

AMP(scaler)

👉 解决 FP16 数值问题

  • scale loss(防 underflow)
  • 自动调 scale(防 overflow)

梯度累积

👉 解决显存限制

  • 多 step 累积梯度
  • 再统一更新

梯度裁剪

👉 解决梯度爆炸

  • 控制 norm 上限
  • 保持方向不变

4. 一句话总理解

这套流程本质是在做三件事:

  1. 用 AMP 提速
  2. 用 accumulation 放大 batch
  3. 用 clipping 保稳定