大模型知识体系 第 2 章 🎮 交互版(含动画演示与测验)
← 深度学习基础:回归、Loss、梯度与 Softmax🏠 回到交互版首页模型评估与泛化:指标、过拟合与正则化 →
你正在浏览静态阅读版(无 JavaScript 也可阅读,便于搜索与 AI 抓取)。交互演示与答题功能请前往 交互版。
第 2 章 · 第一部分 · 理解 (Understand)

优化器:SGD → Momentum → Adam

SGD、Momentum、Adam 完整推导与算例,AdamW 解耦正则,优化器竞赛演示。

对应课件:2.1 自然语言处理

本章对应课件:《2.1 自然语言处理》中的优化器部分。核心内容:SGD、Momentum、Adam、AdamW——如何更好地利用梯度来更新参数。

2.1 为什么需要优化器

先懂直觉

最朴素的更新是「沿梯度反方向走一步」。但真实损失面是崎岖的:有的方向陡、有的方向平、还有噪声。优化器就是「怎么走得更快更稳」的策略集合。

第 1 章学过最朴素的更新公式:

wt+1=wt−η∂L∂ww_{t+1} = w_t - \eta \frac{\partial L}{\partial w}

但真实训练中,梯度并不总是这么「听话」:

优化器就是如何更好地利用梯度来更新参数的工程方案。

2.2 SGD(随机梯度下降)

Wt=Wt−1−η gtW_t = W_{t-1} - \eta\, g_t

其中 gtg_t 是当前 batch 算出的梯度。

特点:只看当前梯度,实现简单、显存开销小。

缺点:

📘 三种 SGD 变体
变体 每步用的数据 特点
BGD(全批量) 全部训练集 方向准,极慢
SGD(单样本) 1 条 快、噪声大
Mini-batch SGD 32~4096 条 实际使用的版本

深度学习里说的「SGD」通常指 mini-batch 版本。

2.3 Momentum:给优化加一点「惯性」

先懂直觉

像球下山:一直朝一个方向滚就积累速度;左右摇摆的方向会互相抵消。这样既抑制震荡,又加速稳定方向。

引入速度变量 vtv_t:

vt=γ vt−1+η gtv_t = \gamma\, v_{t-1} + \eta\, g_t
Wt=Wt−1−vtW_t = W_{t-1} - v_t

直觉像一个球下山:前几步一直往一个方向走,就积累速度。

因此能:

其中 γ\gamma 通常取 0.9 左右,表示「保留多少历史速度」。

🧮 为什么能加速(以峡谷为例)

在陡峭方向,梯度正负交替,历史速度互相抵消 → 有效步长变小 → 不震荡; 在平坦方向,梯度方向一致,速度不断累积 → 有效步长变大 → 加速前进。

等效学习率约为 η1−γ\frac{\eta}{1-\gamma}(γ=0.9 时约 10 倍),但只在方向一致时生效。

2.4 Adam:Momentum + 自适应学习率 ★

先懂直觉

Adam = 动量(记住方向)+ 自适应(每个参数自己调步长)。梯度大的参数步子缩小,梯度小的参数步子放大,所以对学习率没那么敏感。

Adam 同时维护两个统计量。

一阶矩(梯度的指数移动平均,类似 Momentum):

mt=β1mt−1+(1−β1) gtm_t = \beta_1 m_{t-1} + (1 - \beta_1)\, g_t

二阶矩(梯度平方的指数移动平均,衡量梯度尺度):

vt=β2vt−1+(1−β2) gt2v_t = \beta_2 v_{t-1} + (1 - \beta_2)\, g_t^2

偏差修正(因为 m0=v0=0m_0 = v_0 = 0,训练初期估计偏小):

m^t=mt1−β1t,v^t=vt1−β2t\hat m_t = \frac{m_t}{1 - \beta_1^t}, \qquad \hat v_t = \frac{v_t}{1 - \beta_2^t}

最终更新:

W←W−ηm^tv^t+ϵW \leftarrow W - \eta \frac{\hat m_t}{\sqrt{\hat v_t} + \epsilon}

直觉:

🧮 为什么需要偏差修正

训练开始时 m0=0m_0 = 0,第一步 m1=0.1g1m_1 = 0.1 g_1(β₁=0.9 时),只有真实梯度的 1/10。如果不修正,前几十步的更新会严重偏小。

除以 1−β1t1-\beta_1^t:t=1t=1 时 1−0.9=0.11-0.9 = 0.1,m1/0.1=g1m_1/0.1 = g_1——修正回真实尺度。随着 tt 增大,1−β1t→11-\beta_1^t \to 1,修正自然消失。

📌 具体数字算一遍(单参数)

设 η=0.001\eta = 0.001,β1=0.9\beta_1 = 0.9,β2=0.999\beta_2 = 0.999,梯度序列 g1=1.0g_1 = 1.0,g2=1.0g_2 = 1.0:

第 1 步:

  • m1=0.1×1.0=0.1m_1 = 0.1 \times 1.0 = 0.1,m^1=0.1/0.1=1.0\hat m_1 = 0.1/0.1 = 1.0
  • v1=0.001×1.0=0.001v_1 = 0.001 \times 1.0 = 0.001,v^1=0.001/0.001=1.0\hat v_1 = 0.001/0.001 = 1.0
  • 更新量 =0.001×1.01.0+10−8≈0.001= 0.001 \times \frac{1.0}{\sqrt{1.0} + 10^{-8}} \approx 0.001

第 2 步:

  • m2=0.9×0.1+0.1×1.0=0.19m_2 = 0.9 \times 0.1 + 0.1 \times 1.0 = 0.19,m^2=0.19/(1−0.81)≈1.0\hat m_2 = 0.19/(1-0.81) \approx 1.0
  • v2=0.999×0.001+0.001=0.001999v_2 = 0.999 \times 0.001 + 0.001 = 0.001999,v^2=0.001999/(1−0.998001)≈1.0\hat v_2 = 0.001999/(1-0.998001) \approx 1.0
  • 更新量 ≈0.001\approx 0.001

可以看到:梯度持续为 1 时,自适应分母让每步更新稳定在 η\eta 附近。

2.5 常用超参数

参数 典型值 含义
η\eta 1e-3 ~ 3e-4 学习率(大模型常用更小)
β1\beta_1 0.9 一阶矩衰减率
β2\beta_2 0.95 ~ 0.999 二阶矩衰减率(LLM 常用 0.95)
ϵ\epsilon 1e-8 数值稳定项
🎮 交互:三种优化器赛跑交互演示 · 静态阅读版

同一起点、同一学习率,SGD(红)、Momentum(橙)、Adam(绿)在带波浪的非凸函数上赛跑。观察谁更快到达谷底、谁的轨迹更抖。

在交互版中打开这个演示 →

工程里怎么用(PyTorch 优化器配置)
# SGD + Momentum
opt = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)

# Adam(大模型训练默认用 AdamW)
opt = torch.optim.AdamW(
    model.parameters(),
    lr=3e-4,              # 大模型常用 1e-4 ~ 3e-4
    betas=(0.9, 0.95),    # LLM 常用 β₂=0.95
    weight_decay=0.1,     # 解耦的 weight decay
    eps=1e-8,
)

2.6 为什么大模型常见 AdamW

AdamW 是 Adam 的改进版:把 weight decay(L2 正则) 从梯度更新中解耦出来,直接作用于参数:

W←W−ηm^tv^t+ϵ−ηλWW \leftarrow W - \eta \frac{\hat m_t}{\sqrt{\hat v_t} + \epsilon} - \eta\lambda W
🧮 为什么要「解耦」

在原始 Adam 中把 L2 项 λW\lambda W 加进梯度:gt←gt+λWg_t \leftarrow g_t + \lambda W。

但 Adam 会用 v^t\sqrt{\hat v_t} 归一化梯度——梯度大的参数,其 L2 项也被同比例缩小,导致正则化效果被自适应学习率扭曲:大梯度参数几乎不受正则约束。

AdamW 把 decay 从梯度里拿出来,直接乘在参数上:无论梯度大小,正则强度一致。

这也是为什么训练 Transformer、大模型时你经常会看到 AdamW(如 torch.optim.AdamW)。

2.7 三者对比

优化器 核心思想 优点 缺点
SGD 只用当前梯度 简单、省显存、泛化有时更好 震荡、收敛慢、对 lr 敏感
Momentum 累积速度 抑制震荡、加速 仍需手动调学习率
Adam / AdamW 一阶矩 + 二阶矩 + 偏差修正 自适应、收敛快、对超参不敏感 显存多(存 m、v)、有时泛化略差
🎯 面试常问

Q1:Adam 的显存开销为什么这么大?

查看答案

除了权重本身,还要保存一阶矩 m 和二阶矩 v(各同参数量大小)。混合精度训练还要 FP32 master weights 和 FP32 梯度。合计约 18 bytes/参数(见第 13 章)。这是分布式训练需要 ZeRO/FSDP 分片优化器状态的原因。

Q2:Adam 和 AdamW 的区别?

查看答案

Adam 把 L2 正则加进梯度,会被自适应学习率缩放,正则效果不稳定;AdamW 把 weight decay 解耦,直接作用于参数,正则强度与梯度大小无关。现代 Transformer 训练默认 AdamW。

Q3:为什么大模型训练常用 β₂ = 0.95 而不是 0.999?

查看答案

β₂ 越大,二阶矩估计越平滑但越滞后。大模型训练梯度噪声大、训练步数少,0.95 让估计更快跟上梯度变化,训练更稳定(LLaMA 等模型的常见配置)。

🔑 本节必须记住
优化器 一句话
SGD W←W−ηgW \leftarrow W - \eta g,简单但震荡
Momentum 累积速度 vt=γvt−1+ηgtv_t = \gamma v_{t-1} + \eta g_t,抑制震荡
Adam 一阶矩 + 二阶矩 + 偏差修正,自适应步长
AdamW 解耦 weight decay,LLM 训练默认
显存 Adam 额外存 m、v,共约 18 bytes/参数(混合精度)
📝 小测验
Adam 的偏差修正(除以 1−β^t)解决什么问题?
A梯度爆炸
B训练初期 m、v 从 0 开始导致估计偏小
C学习率过大
D过拟合
显示答案与解析

正确答案:B

m₀ = v₀ = 0,初期移动平均只有真实值的 (1−β) 比例。偏差修正把估计恢复到真实尺度,且随 t 增大自动消失。
📝 小测验
Momentum 能抑制震荡的原因是?
A减小学习率
B方向相反的梯度在速度变量中互相抵消
C增加 batch size
D使用二阶矩
显示答案与解析

正确答案:B

在峡谷的陡峭方向,梯度正负交替,历史速度相互抵消;平坦方向梯度一致,速度累积加速。这就是「惯性」的效果。
📝 小测验
AdamW 与 Adam 的关键区别是?
AAdamW 不需要二阶矩
BAdamW 把 weight decay 从梯度更新中解耦,直接作用于参数
CAdamW 学习率更大
DAdamW 不支持 Transformer
显示答案与解析

正确答案:B

原始 Adam 把 L2 加进梯度,会被自适应学习率缩放而失效;AdamW 解耦后正则强度与梯度大小无关,行为更一致,是 LLM 训练默认选择。
← 深度学习基础:回归、Loss、梯度与 Softmax🏠 回到交互版首页模型评估与泛化:指标、过拟合与正则化 →
本章完。原始 Markdown:content/02-optimizers.md