Skip to content

梯度下降与优化器

梯度下降是深度学习训练的核心算法;Adam、AdamW 等现代优化器都在它的基础上改进。本页梳理从最朴素的批量梯度下降到当今主流优化器(包括 2024-2025 年兴起的 Muon 等)的完整谱系,并给出每个优化器的数学推导。前置阅读:数值优化与数学基础。

沿用在数值优化基础中建立的”蒙眼下山”比喻,各种优化器的改进方向一目了然:

  • 批量梯度下降(GD)= 先把整座山精确测量一遍再走一步。方向准,但一步太贵(全量数据)。
  • 随机梯度下降(SGD)= 蒙眼下山,每步只看脚下一个样本就走。方向有噪声但极快,而且噪声反而有助于跳出局部最优。
  • 小批量 SGD(mini-batch)= 每步看一小撮样本(如 32 个)再走——兼顾速度和方向准确度,是实际训练的标准做法。
  • Momentum(动量)= 带着惯性滚下山。球有质量,不会因为一个小坎就停下,能冲过浅坑(局部最优)。
  • Adam= 自适应步长。每个参数方向用不同的有效学习率——梯度大的方向自动减速、梯度小的方向自动加速,像给每个方向装了独立变速箱。

以下推导用数学符号表达。记 θ\theta 为参数,L(θ)L(\theta) 为损失函数,∇L\nabla L 为梯度,η\eta 为学习率,tt 为时间步。

批量梯度下降(Batch GD)用全部 N 个样本计算梯度:

gt=1N∑i=1N∇L(θt;xi,yi)(全量梯度)θt+1=θt−η⋅gt(往梯度反方向走一步)g_t = \frac{1}{N} \sum_{i=1}^{N} \nabla L(\theta_t; x_i, y_i) \quad \text{(全量梯度)} \\ \theta_{t+1} = \theta_t - \eta \cdot g_t \quad \text{(往梯度反方向走一步)}

随机梯度下降(SGD)只用一个样本:

gt=∇L(θt;xi,yi)(随机抽一个样本的梯度,无偏估计)θt+1=θt−η⋅gtg_t = \nabla L(\theta_t; x_i, y_i) \quad \text{(随机抽一个样本的梯度,无偏估计)} \\ \theta_{t+1} = \theta_t - \eta \cdot g_t

小批量 SGD(Mini-batch)取折中,每次用 B 个样本:

gt=1B∑j=1B∇L(θt;xij,yij)θt+1=θt−η⋅gtg_t = \frac{1}{B} \sum_{j=1}^{B} \nabla L(\theta_t; x_{i_j}, y_{i_j}) \\ \theta_{t+1} = \theta_t - \eta \cdot g_t

核心思想:累积历史梯度方向,像物理中的惯性一样平滑轨迹。

vt=β⋅vt−1+gt(v 是速度向量,β 通常取 0.9)θt+1=θt−η⋅vt(沿累积速度方向更新)v_t = \beta \cdot v_{t-1} + g_t \quad \text{($v$ 是速度向量,$\beta$ 通常取 0.9)} \\ \theta_{t+1} = \theta_t - \eta \cdot v_t \quad \text{(沿累积速度方向更新)}

直观理解:如果连续几步梯度方向一致,速度 v 会越积越大(加速);如果方向反复震荡(如锯齿形路径),正负抵消后 v 的震荡分量被抑制——这就是动量”冲过浅坑”和”抹平抖动”的数学根源。

Nesterov 加速梯度(NAG)是 Momentum 的变体,先”往前看一步”再计算梯度:

vt=β⋅vt−1+∇L(θt−η⋅β⋅vt−1)(在"预判位置"算梯度)θt+1=θt−η⋅vtv_t = \beta \cdot v_{t-1} + \nabla L(\theta_t - \eta \cdot \beta \cdot v_{t-1}) \quad \text{(在"预判位置"算梯度)} \\ \theta_{t+1} = \theta_t - \eta \cdot v_t

核心思想:对每个参数维护一个”历史梯度平方和”,梯度一直很大的参数说明它”跑太快”,给它更小的有效学习率。

Gt=Gt−1+gt⊙gt(G 累积所有历史梯度的逐元素平方,⊙ 是逐元素乘)θt+1=θt−η⋅gtGt+ϵ(有效学习率=η/Gt)G_t = G_{t-1} + g_t \odot g_t \quad \text{($G$ 累积所有历史梯度的逐元素平方,$\odot$ 是逐元素乘)} \\ \theta_{t+1} = \theta_t - \frac{\eta \cdot g_t}{\sqrt{G_t} + \epsilon} \quad \text{(有效学习率} = \eta / \sqrt{G_t}\text{)}

问题:GtG_t 单调递增,学习率会一直衰减直到趋零,训练后期”学不动了”。

核心思想:用指数移动平均(EMA)代替无限累积,让学习率”忘掉远古历史”。

E[g2]t=ρ⋅E[g2]t−1+(1−ρ)⋅gt⊙gt(ρ 通常取 0.99)θt+1=θt−η⋅gtE[g2]t+ϵE[g^2]_t = \rho \cdot E[g^2]_{t-1} + (1 - \rho) \cdot g_t \odot g_t \quad \text{($\rho$ 通常取 0.99)} \\ \theta_{t+1} = \theta_t - \frac{\eta \cdot g_t}{\sqrt{E[g^2]_t} + \epsilon}

Adam 同时维护梯度的一阶矩(均值,相当于 Momentum)和二阶矩(未中心化方差,相当于 RMSProp):

mt=β1⋅mt−1+(1−β1)⋅gt(一阶矩——梯度的指数移动平均,"方向")vt=β2⋅vt−1+(1−β2)⋅gt⊙gt(二阶矩——梯度平方的指数移动平均,"幅度")m^t=mt1−β1t(偏差校正,因为 m 和 v 初始化为 0,早期会偏小)v^t=vt1−β2tθt+1=θt−η⋅m^tv^t+ϵ(更新)m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t \quad \text{(一阶矩——梯度的指数移动平均,"方向")} \\ v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g_t \odot g_t \quad \text{(二阶矩——梯度平方的指数移动平均,"幅度")} \\ \hat{m}_t = \frac{m_t}{1 - \beta_1^t} \quad \text{(偏差校正,因为 $m$ 和 $v$ 初始化为 0,早期会偏小)} \\ \hat{v}_t = \frac{v_t}{1 - \beta_2^t} \\ \theta_{t+1} = \theta_t - \frac{\eta \cdot \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \quad \text{(更新)}

典型超参数:η=10−3\eta = 10^{-3}, β1=0.9\beta_1 = 0.9, β2=0.999\beta_2 = 0.999, ϵ=10−8\epsilon = 10^{-8}。

直观理解:m^t\hat{m}_t 提供”平均方向”(类似 Momentum),v^t\hat{v}_t 提供”每个参数的波动幅度”。除以 v^t\sqrt{\hat{v}_t} 后,梯度幅度一直很大的参数被缩小、一直很小的参数被放大——这就是”逐参数自适应步长”。

Adam 中的权重衰减(weight decay)实现有微妙问题:当权重衰减通过 L2 正则化(把 λθ\lambda\theta 加到梯度里)实现时,它会和自适应学习率耦合,导致实际衰减量被 v^t\sqrt{\hat{v}_t} 缩放——频繁更新的参数衰减不够,不频繁更新的参数衰减过多。

AdamW 的修复:把权重衰减从梯度中分离出来,直接对参数做衰减:

mt=β1⋅mt−1+(1−β1)⋅gtvt=β2⋅vt−1+(1−β2)⋅gt⊙gtm^t=mt1−β1t,v^t=vt1−β2t(标准 Adam 梯度步骤)θt+1=θt−η⋅(m^tv^t+ϵ+λ⋅θt)(解耦的权重衰减——直接乘以 η,不再进入梯度)m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t \\ v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g_t \odot g_t \\ \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t} \quad \text{(标准 Adam 梯度步骤)} \\ \theta_{t+1} = \theta_t - \eta \cdot \left( \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} + \lambda \cdot \theta_t \right) \quad \text{(解耦的权重衰减——直接乘以 $\eta$,不再进入梯度)}

这个看似微小的改动对大模型训练影响巨大——AdamW 是当前 GPT、LLaMA 等所有主流大模型预训练的标准优化器。

从 1950s 的梯度下降到如今的 AdamW,每一步改进都解决前一代的痛点:

不同优化器在损失曲面上的行为

Section titled “不同优化器在损失曲面上的行为”

同样是”下山”,不同优化器走出完全不同的轨迹:

PyTorch:SGD vs Adam 训练同一个模型

Section titled “PyTorch:SGD vs Adam 训练同一个模型”
import torch
import torch.nn as nn
# 一个简单的线性模型 + 随机数据
model = nn.Linear(10, 1)
X = torch.randn(100, 10)
y = X @ torch.randn(10, 1) + 0.1 * torch.randn(100, 1)
criterion = nn.MSELoss()
# 分别用 SGD 和 Adam,对比同样步数下的收敛
for name, opt in [("SGD", torch.optim.SGD(model.parameters(), lr=0.01)),
("Adam", torch.optim.Adam(model.parameters(), lr=0.01))]:
# 每次重新初始化模型权重
torch.nn.init.normal_(model.weight); torch.nn.init.zeros_(model.bias)
for epoch in range(100):
loss = criterion(model(X), y)
opt.zero_grad(); loss.backward(); opt.step()
print(f"{name}: 最终 loss = {loss.item():.4f}")
# Adam: 最终 loss ≈ 0.01(收敛更快)
# SGD: 最终 loss ≈ 0.03(lr=0.01 下偏慢)
import numpy as np
# 权重更新公式:w ← w - lr * grad(这就是 SGD 的全部)
w = np.array([3.0, -1.0]) # 初始权重
lr = 0.1 # 学习率
for step in range(20):
grad = 2 * w # 假设梯度 = ∇(w²) = 2w
w = w - lr * grad # 核心:往梯度反方向走一步
print(w) # → [≈0, ≈0] 收敛到最优

理解 Adam 最简单的方式是从零实现——100 行不到就能复现 PyTorch 的 torch.optim.Adam:

import numpy as np
class SimpleAdam:
"""最小化 Adam 实现,展示核心逻辑"""
def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8):
self.lr, self.b1, self.b2, self.eps = lr, *betas, eps
self.m = [np.zeros_like(p) for p in params] # 一阶矩
self.v = [np.zeros_like(p) for p in params] # 二阶矩
self.t = 0 # 时间步
def step(self, params, grads):
self.t += 1
for i, (p, g) in enumerate(zip(params, grads)):
# 一阶矩:梯度的指数移动平均(方向)
self.m[i] = self.b1 * self.m[i] + (1 - self.b1) * g
# 二阶矩:梯度平方的指数移动平均(幅度)
self.v[i] = self.b2 * self.v[i] + (1 - self.b2) * g**2
# 偏差校正
m_hat = self.m[i] / (1 - self.b1 ** self.t)
v_hat = self.v[i] / (1 - self.b2 ** self.t)
# 更新参数:有效学习率 = η * m_hat / (√v_hat + ε)
params[i] -= self.lr * m_hat / (np.sqrt(v_hat) + self.eps)
# 测试:优化 f(w) = w²(最优解 w=0)
w = [np.array([3.0, -1.0])]
opt = SimpleAdam(w, lr=0.1)
for step in range(50):
grads = [2 * w[0]] # ∇(w²) = 2w
opt.step(w, grads)
print(w[0]) # → [≈0, ≈0] 比 SGD 更快收敛

学习率不是固定的——好的调度(schedule)对训练效果影响极大。常见的策略:

import numpy as np
# Cosine Annealing(余弦退火):大模型训练最常用的调度
def cosine_schedule(step, total_steps, lr_max=1e-3, lr_min=1e-5, warmup_steps=500):
"""warmup → cosine 衰减 → lr_min"""
if step < warmup_steps:
return lr_max * step / warmup_steps # 线性预热
progress = (step - warmup_steps) / (total_steps - warmup_steps)
return lr_min + 0.5 * (lr_max - lr_min) * (1 + np.cos(np.pi * progress))
# 模拟 10000 步训练的学习率变化
for s in [0, 250, 500, 5000, 9999]:
print(f"step {s:5d}: lr = {cosine_schedule(s, 10000):.6f}")
# step 0: lr = 0.000000 ← warmup 阶段
# step 250: lr = 0.000500 ← warmup 中途
# step 500: lr = 0.001000 ← warmup 结束,峰值
# step 5000: lr = 0.000502 ← cosine 中途
# step 9999: lr = 0.000010 ← 接近 lr_min
  • Adam 是默认首选:90% 的深度学习任务,第一选择就是 Adam(lr=1e-3),快速验证想法。如果 Adam 效果不够好,再尝试 SGD+Momentum(往往泛化更好,尤其在图像分类)。
  • 学习率预热(warmup):Transformer 训练初期梯度极不稳定,先用很小的学习率线性升温到目标值,再正常训练——这是 GPT/BERT 训练的标配。
  • 学习率衰减:训练后期降低学习率,让模型在最优解附近”精调”,避免在最优点附近来回震荡。
  • 梯度裁剪(gradient clipping):RNN / Transformer 训练中,当梯度范数超过阈值就缩放——防止梯度爆炸导致 NaN。
  • AdamW ≠ Adam + weight_decay:Adam 中的 L2 正则化和权重衰减在自适应学习率下不等价,AdamW 修正了这个问题,是当前大模型训练的标准选择。
  • Muon 的适用范围:Muon 只对 2D 隐藏层权重有效,嵌入层、分类头、LayerNorm 参数仍用 AdamW。在训练 Transformer 时,Q/K/V 分别作为独立矩阵做正交化效果更好。详见上文”最新进展”中的 Muon 小节。
  • 分布式训练用 LAMB:超大 batch(数万 token)训练时,LAMB(Layer-wise Adaptive Moments)为每层独立做自适应,比 AdamW 更稳定。
  • 所有深度学习训练:PyTorch 的 optimizer.step() 就是梯度下降——CNN、Transformer、扩散模型,无一例外。详见Transformer 架构。
  • 逻辑回归求解:大规模广告 CTR 模型用 SGD/FTRL 在稀疏高维特征上训练,Google/Facebook 的核心广告系统即基于此。
  • SVM 对偶优化:SMO 算法本质是坐标下降(一种特殊的优化策略),逐次优化两个拉格朗日乘子。详见SVM 支持向量机。
  • 大语言模型预训练:GPT-4、LLaMA 等用 AdamW + cosine 学习率衰减 + warmup 在万亿 token 上训练。详见语言模型演进。
  • 扩散模型训练:Stable Diffusion 等生成模型同样用 Adam 优化噪声预测网络。详见扩散模型。
类库语言说明
torch.optimPythonPyTorch 优化器模块:SGD、Adam、AdamW、LAMB 等
tf.keras.optimizersPythonTensorFlow / Keras 优化器,接口与 PyTorch 类似
optaxPythonJAX 生态的优化器库,Google 大模型训练首选
apexPythonNVIDIA 的混合精度训练库,提供 FusedAdam 等加速优化器
acceleratePythonHuggingFace 训练加速库,封装多种优化器与学习率调度策略
MuonPython新兴的正交化优化器(2024),用于隐藏层 2D 权重,Kimi.ai 大规模 LLM 训练采用
schedulefreePythonSchedule-Free SGD/Adam(Defazio et al. 2024),无需手动设计学习率调度
术语英文解释
随机梯度下降SGD每次只用一个(或一小批)样本计算梯度,引入随机噪声以加速训练
小批量Mini-batch每次迭代使用的一小撮样本(如 32/64/256 个),兼顾速度和稳定性
动量Momentum累积历史梯度方向,像惯性一样平滑更新轨迹,加速收敛并冲过浅坑
学习率衰减Learning Rate Decay训练后期逐步降低学习率,帮助模型在最优解附近稳定收敛
AdaGradAdaGrad累积历史梯度平方,给频繁更新的参数更小的学习率(但会单调衰减)
RMSPropRMSProp用指数移动平均代替累积,解决 AdaGrad 学习率过早趋零的问题
AdamAdam结合 Momentum(一阶矩)和 RMSProp(二阶矩),自适应学习率 + 动量
AdamWAdamWAdam 的改进版,将权重衰减从梯度中解耦,正则化效果更好
学习率预热Warmup训练初期从极小学习率线性升温,防止早期梯度不稳定
梯度裁剪Gradient Clipping当梯度范数超过阈值时按比例缩放,防止梯度爆炸
MuonMuon正交化优化器(2024),对动量更新矩阵做 Newton-Schulz 正交化,放大”罕见方向”
LionLion符号优化器(2023),只用梯度符号更新,比 Adam 少一个状态变量
SophiaSophia二阶优化器(2023),用对角 Hessian 估计加速收敛
Schedule-FreeSchedule-Free无需学习率调度的优化器(2024),自动在探索和精调间切换
Cosine 退火Cosine Annealing学习率按余弦曲线从峰值衰减到最小值,大模型训练标配

Muon(MomentUm Orthogonalized by Newton-Schulz)是 2024 年底由 Keller Jordan 提出的优化器,迅速在社区引起轰动。它的核心创新是:对 SGD-Momentum 产生的更新矩阵做近似正交化处理,然后再更新参数。

设计思路:

Gt=β⋅Gt−1+∇L(θt)(标准 SGD-Momentum,动量累积梯度)Newton-Schulz 迭代近似正交化(避免昂贵的 SVD,用矩阵乘法近似):X=G∥G∥F(归一化到 Frobenius 范数 1)for k=1…5:A=XX⊤,X=3.4445 X+(−4.7750 A+2.0315 AA)Xθt+1=θt−η⋅X(用正交化后的更新)G_t = \beta \cdot G_{t-1} + \nabla L(\theta_t) \quad \text{(标准 SGD-Momentum,动量累积梯度)} \\ \text{Newton-Schulz 迭代近似正交化(避免昂贵的 SVD,用矩阵乘法近似):} \\ X = \frac{G}{\|G\|_F} \quad \text{(归一化到 Frobenius 范数 1)} \\ \text{for } k = 1 \ldots 5: \quad A = X X^\top, \quad X = 3.4445\, X + (-4.7750\, A + 2.0315\, A A) X \\ \theta_{t+1} = \theta_t - \eta \cdot X \quad \text{(用正交化后的更新)}

为什么正交化有效?实证观察发现,SGD-Momentum 和 Adam 产生的 2D 更新矩阵(权重矩阵)通常条件数极高——即几乎所有更新能量集中在少数几个方向上,而其他”罕见方向”虽然重要但被淹没。正交化把所有奇异值拉到 1,相当于放大了那些被忽略的方向。

Muon 的突破性成果:

  • 将 NanoGPT 训练速度记录提升 1.35 倍
  • 将 1.5B 参数 Transformer 训练到 GPT-2 XL 水平,计算量仅需 AdamW 的 75%
  • 被 Kimi.ai(月之暗面)用于大规模 LLM 训练,是前沿 AI 实验室首次采用非 Adam 系优化器

注意:Muon 只适用于隐藏层的 2D 权重矩阵;嵌入层、分类头、标量参数仍用 AdamW。当前最佳实践是 Muon + AdamW 混合使用。

Schedule-Free Optimizer:无需学习率调度

Section titled “Schedule-Free Optimizer:无需学习率调度”

2024 年 Aaron Defazio 等人提出 Schedule-Free SGD/Adam,核心思想是把学习率调度内化到优化器中——不再需要手动设计 warmup + cosine 衰减等复杂调度策略。优化器自动在”探索”(大学习率)和”精调”(小学习率)之间切换,减少了需要调节的超参数数量。Meta 已将其集成到 PyTorch 生态。

Lion(EvoLved Sign Momentum,2023,Google)由进化算法自动搜索发现,比 Adam 更简单:只用梯度的符号(sign),不需要计算二阶矩 vtv_t。

update=sign(β1⋅mt−1+(1−β1)⋅gt)(只取符号!)θt=θt−η⋅updatemt=β2⋅mt−1+(1−β2)⋅gt(更新动量)\text{update} = \text{sign}(\beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t) \quad \text{(只取符号!)} \\ \theta_t = \theta_t - \eta \cdot \text{update} \\ m_t = \beta_2 \cdot m_{t-1} + (1 - \beta_2) \cdot g_t \quad \text{(更新动量)}

优势:内存占用比 Adam 少约 50%(不需要存 vtv_t),在大模型训练中有意义。Google VeGVa(2025)进一步将 Lion 与 AdamW 在训练不同阶段切换,综合两者优势。

Sophia(Second-order Clipped Stochastic Optimization,2023,Stanford)尝试用对角 Hessian(二阶导数)估计来加速训练,理论上比一阶方法(Adam 等)收敛更快。它用 Hutchinson 方法(随机估计)近似 Hessian 对角线,避免完整 Hessian 的 O(n2)O(n^2) 内存开销。在大语言模型上声称比 Adam 快 2 倍,但泛化性仍在验证中。

  • Adam 终于被证明收敛(Zhang et al., NeurIPS 2022):Reddi et al. (2018) 曾指出 Adam 在某些凸问题上不收敛,Zhang et al. 证明了在适当条件下 Adam 无需任何修改即可收敛,终结了这个长期争论。
  • 过参数化(over-parameterized)下的隐式偏置:当参数维度远大于数据量时(大模型常态),SGD/Adam 隐式地找到最小范数解(minimum norm solution)——这解释了为什么过参数化的模型不一定会过拟合。
  • Kingma & Ba,「Adam: A Method for Stochastic Optimization」(ICLR 2015):Adam 原始论文,提出自适应矩估计,引用量 10 万+,深度学习最重要的优化器论文之一。
  • Loshchilov & Hutter,「Decoupled Weight Decay Regularization」(ICLR 2019):AdamW 论文,指出 Adam 中 L2 正则与权重衰减不等价,并提出解耦方案。
  • Ruder,「An overview of gradient descent optimization algorithms」(2016):arXiv 综述,清晰梳理 GD→SGD→Momentum→AdaGrad→RMSProp→Adam 的演进,入门首选。
  • Reddi et al.,「On the Convergence of Adam and Beyond」(ICLR 2018):指出 Adam 在某些凸问题上不收敛,提出 AMSGrad 修正——理解 Adam 局限性的关键文献。
  • Jordan et al.,「Muon: An optimizer for hidden layers in neural networks」(2024):Muon 优化器原始博文,提出 Newton-Schulz 正交化方案,附带完整 PyTorch 实现和 NanoGPT 训练基准。
  • Defazio et al.,「Schedule-Free Learning」(ICLR 2025):Schedule-Free 优化器论文,把学习率调度内化到优化器中,Meta 出品。
  • Chen et al.,「Lion: Adapting Large Language Models with Only Sign」(ICLR 2024):Lion 符号优化器论文,由进化算法自动发现。
  • Liu et al.,「Sophia: A Scalable Stochastic Second-order Optimizer for Language Model Pre-training」(2023):Sophia 二阶优化器,用对角 Hessian 估计加速 LLM 预训练。