深度学习中的优化器旨在通过更新网络参数(权重和偏置)来最小化损失函数。近年来,优化器的发展主要沿着两条主线:动量机制(加速收敛并抑制震荡)和自适应学习率(为不同参数单独设置学习率)。
下面我们将目前主流的优化器按发展脉络分类,详细解析它们的原理与公式。
0. 统一符号定义
在介绍具体公式前,先统一符号:
- $\theta_t$: 第 $t$ 步的模型参数
- $g_t$: 第 $t$ 步的梯度,即 $g_t = \nabla_\theta L(\theta_t)$
- $\eta$: 全局学习率
- $\odot$: 哈达玛乘积(按元素相乘)
一、 基础与动量系列(固定学习率家族)
1. SGD (Stochastic Gradient Descent)
- 原理:最基础的优化方式,沿着梯度的反方向更新参数。所谓的“随机”是指每次只用一个Batch的数据来估算梯度,而不是全量数据。
- 公式:
$$
\theta_{t+1} = \theta_t – \eta g_t
$$ - 优缺点:实现简单,理论完备;但在平坦区域容易停滞,在峡谷区域(如RNN)容易发生剧烈震荡,且对学习率的选择极其敏感。
2. SGD + Momentum (动量法)
- 原理:模拟物理中的“惯性”。在下降过程中,不仅看当前的梯度,还保留上一步的更新方向。如果当前梯度与上一步方向一致,则加速;如果相反(如穿过峡谷),则减速。
- 公式:
$$
v_t = \gamma v_{t-1} + \eta g_t
$$
$$
\theta_{t+1} = \theta_t – v_t
$$ - (注:$\gamma$ 通常设为 0.9,称为动量系数)
- 优缺点:极大减少了震荡,加快了在正确方向上的收敛速度。
3. Nesterov Accelerated Gradient (NAG)
- 原理:Nesterov 动量的改进在于“先往前看一步”。它先按照上一步的动量走一小步,在这个“未来位置”计算梯度,然后用这个梯度来修正当前的动量。
- 公式:
$$
v_t = \gamma v_{t-1} + \eta \nabla_\theta L(\theta_t – \gamma v_{t-1})
$$
$$
\theta_{t+1} = \theta_t – v_t
$$ - 优缺点:在动量的基础上进一步增加了对梯度的“预见性”,在RNN等任务上比标准Momentum收敛更快、更稳。
二、 自适应学习率系列
这类优化器认识到:不同参数需要的更新步长是不同的。出现频率低的特征,需要大步长更新;出现频率高的特征,需要小步长。
4. AdaGrad (Adaptive Gradient)
- 原理:累计历史梯度的平方和。某个参数历史梯度平方和越大,说明它更新得很频繁,就缩小它的学习率;反之则增大。
- 公式:
$$
G_t = G_{t-1} + g_t \odot g_t
$$
$$
\theta_{t+1} = \theta_t – \frac{\eta}{\sqrt{G_t + \epsilon}} \odot g_t
$$ - *(注:$\epsilon$ 是为了防止分母为0的极小数,通常取 $10^{-8}$)*
- 优缺点:非常适合处理稀疏数据(如NLP中的词向量)。致命缺点:分母 $G_t$ 是只增不减的,随着训练进行,学习率会单调衰减趋近于0,导致模型提前停止学习。
5. RMSProp (Root Mean Square Propagation)
- 原理:Hinton 为了解决 AdaGrad 学习率不断衰减的问题提出的。不再累计全部历史梯度,而是计算梯度的指数移动平均(EMA),相当于只关注最近一段时间的梯度情况。
- 公式:
$$
E[g^2]_t = \beta E[g^2]_{t-1} + (1 – \beta) g_t \odot g_t
$$
$$
\theta_{t+1} = \theta_t – \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} \odot g_t
$$ - *(注:$\beta$ 通常设为 0.9)*
- 优缺点:彻底解决了学习率衰减到零的问题,非常适合非平稳目标(如在线学习、RNN),是Adam诞生的重要前置。
6. Adam (Adaptive Moment Estimation) 🔥🔥🔥
- 原理:目前最主流的通用优化器。它结合了 Momentum(一阶矩估计,控制方向)和 RMSProp(二阶矩估计,控制步长)。此外,为了解决初始阶段 $v_0$ 和 $m_0$ 接近0导致估算偏倚的问题,引入了偏差校正。
- 公式:
- 计算一阶矩(动量):
$$
m_t = \beta_1 m_{t-1} + (1 – \beta_1) g_t
$$ - 计算二阶矩(梯度平方的指数移动平均):
$$
v_t = \beta_2 v_{t-1} + (1 – \beta_2) 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}
$$ - 更新参数:
$$
\theta_{t+1} = \theta_t – \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \odot \hat{m}_t
$$
- 计算一阶矩(动量):
- *(注:默认超参 $\beta_1=0.9, \beta_2=0.999, \epsilon=10^{-8}$)*
- 优缺点:收敛极快,几乎不需要手动调学习率,对初始值不敏感,是各种任务的“Baseline首选”。缺点:在某些情况下(如Transformer预训练),Adam 可能会陷入局部最优,泛化能力略逊于带精调学习率的 SGD。
7. AdamW 🔥🔥🔥
- 原理:大模型(如Transformer/ViT)时代的新霸主。原始的 Adam 在加入 L2 正则化(Weight Decay)时,正则化项会被自适应学习率除以二阶矩,导致正则化效果大打折扣。AdamW 将权重衰减从梯度更新中解耦出来,独立进行衰减。
- 公式:
前三步与 Adam 完全一致(计算 $\hat{m}_t$ 和 $\hat{v}_t$),更新步骤变为:
$$
\theta_{t+1} = \theta_t – \eta \left( \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} + \lambda \theta_t \right)
$$ - *(注:$\lambda$ 是权重衰减系数 Weight Decay)*
- 优缺点:解决了 Adam 配合 L2 正则化时失效的问题,在复杂大模型中表现出了比原版 Adam 更好的泛化能力和训练稳定性。
三、 其他值得关注的进阶优化器
虽然不如 SGD 和 Adam 系列普及,但在特定领域有亮眼表现:
- AdaBound: 结合了 Adam 前期的快速收敛和 SGD 后期的优秀泛化。原理是给 Adam 的自适应学习率加上一个动态的上下界,随着训练进行,上下界收紧,最终退化为类似 SGD 的固定学习率。
- LAMB (Layer-wise Adaptive Moments optimizer for Batch training): 专门针对超大 Batch Size(如几万甚至几万以上)设计的优化器。它对每一层的更新应用了信任域,防止超大 Batch 导致的不稳定。用于训练 BERT 等超大模型。
- Lion (EvoLved Sign Momentum): 2023年由 Google Brain 提出通过符号搜索发现的优化器。公式极其简单:去掉了分母的自适应项,直接对动量 $m$ 求 Sign(符号函数)来更新参数,内存占用比 Adam 少 20%。
四、 总结与工程选择指南
| 优化器 | 核心优势 | 适用场景 | 调参难度 |
|---|---|---|---|
| SGD + Momentum | 极致的泛化能力上限 | CV经典模型 (ResNet等),算力充足可以反复调参 | 极难(需配合Cosine衰减等调度器) |
| Adam | 训练极快,开箱即用 | NLP中小模型、快速实验验证、代码跑通阶段 | 简单 |
| AdamW | 正则化准确,泛化好 | 现代大模型绝对标配 (LLM, ViT, Stable Diffusion) | 中等(需调 Weight Decay) |
| RMSProp | 处理非平稳数据 | RNN序列模型、强化学习 | 简单 |
工程实战建议:
- 日常打比赛/做实验:无脑首选 AdamW + 线性预热+ 余弦衰减。
- 工业级复现经典CV模型:使用 SGD + Momentum + 余弦退火,虽然训练慢,但最终精度往往能高出 0.5%~1%。
- 超大数据集/超大Batch Size:尝试 LAMB 或 AdamW。
- 永远记住:优化器只是工具,学习率调度策略往往比优化器本身的选择更重要。
Adam 优化器中引入偏差校正的核心原因,用一句话概括就是:为了消除初始化为 0 导致的“冷启动”阶段对梯度和学习率的严重低估,防止训练初期发生剧烈震荡。
Adam 的偏差校正本质上是一个 “安全启动” 机制,它通过数学上的补偿,完美抵消了将动量变量初始化为 0 带来的早期系统性偏差,是 Adam 能够做到“开箱即用、不用精调”的关键设计之一。
1. 数学根源:初始化为零的“原罪”
在 Adam 中,一阶矩(动量 $m_t$)和二阶矩(梯度平方和 $v_t$)都被初始化为 0。
我们以一阶矩 $m_t$ 为例,它的更新公式是指数移动平均(EMA):
$$
m_t = \beta_1 m_{t-1} + (1 – \beta_1) g_t
$$
假设 $\beta_1 = 0.9$,我们手动展开前几步的计算:
- 第 1 步 ($t=1$) : $m_1 = 0.9 \times 0 + 0.1 \times g_1 = \mathbf{0.1 g_1}$
- 第 2 步 ($t=2$) : $m_2 = 0.9 \times (0.1 g_1) + 0.1 \times g_2 = \mathbf{0.09 g_1 + 0.1 g_2}$
- 第 3 步 ($t=3$) : $m_3 = 0.9 \times (0.09 g_1 + 0.1 g_2) + 0.1 \times g_3 = \mathbf{0.081 g_1 + 0.09 g_2 + 0.1 g_3}$
仔细观察各项的系数之和:
- $t=1$ 时,系数和 = $0.1$
- $t=2$ 时,系数和 = $0.09 + 0.1 = 0.19$
- $t=3$ 时,系数和 = $0.081 + 0.09 + 0.1 = 0.271$
理论上,如果我们要计算梯度的真实期望值,这些系数之和应该等于 1。但正是因为初始值 $m_0=0$ 的拖累,在训练初期,$m_t$ 的系数之和远远小于 1(在数学上等于 $1 – \beta_1^t$)。
这意味着,$m_t$ 在训练早期被严重缩小了(比如第1步只有真实梯度的10%)。同理,二阶矩 $v_t$ 也被严重缩小了。
2. 实际影响:为什么会导致“震荡”?
在 Adam 的最终更新公式中,$m_t$ 在分子,$\sqrt{v_t}$ 在分母:
$$
\theta_{t+1} = \theta_t – \frac{\eta}{\sqrt{v_t} + \epsilon} \odot m_t
$$
由于 Adam 的默认超参数是 $\beta_1 = 0.9$,$\beta_2 = 0.999$。注意这两个值的差异!
- $m_t$ 在第 1 步被低估了约 10倍 ($1-0.9^1 = 0.1$)
- $v_t$ 在第 1 步被低估了约 1000倍 ($1-0.999^1 = 0.001$)
灾难性的后果发生了:
分子缩小了 10 倍,但分母缩小了 1000 倍!这导致分母变得极其微小,最终计算出的实际更新步长被异常放大了约 100 倍($\sqrt{1000}/10 \approx 31.6$ 倍)。
如果不做处理,模型在训练的最初几步会发生极其剧烈的震荡,甚至直接导致梯度爆炸或损失变成 NaN。
3. 偏差校正的精妙之处
为了修复这个问题,Adam 引入了偏差校正机制:
$$
\hat{m}_t = \frac{m_t}{1 – \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 – \beta_2^t}
$$
我们把前文推导出的真实系数和 $1 – \beta^t$ 除掉,就相当于强行把系数之和“拉回”到 1。
再看训练第 1 步的效果:
- 校正后的 $\hat{m}_1 = \frac{0.1 g_1}{0.1} = g_1$ (完美还原真实梯度)
- 校正后的 $\hat{v}_1 = \frac{0.001 g_1^2}{0.001} = g_1^2$ (完美还原真实梯度平方)
此时更新步长变得合理,震荡被消除。
随着训练进行(比如 $t=10000$):
- $0.9^{10000} \approx 0$
- $1 – \beta_1^t \approx 1$
分母变成了 1,偏差校正的作用自动消失,不影响后期的正常训练。