共计 1936 个字符,预计需要花费 5 分钟才能阅读完成。
优化算法在深度学习中的核心作用
在神经网络训练过程中,优化算法直接决定了模型如何从损失函数的梯度信息中更新权重参数。好的优化器能显著加快收敛速度、提高模型性能,而选择不当则可能导致训练不稳定甚至完全无法收敛。目前最主流的两种优化算法——随机梯度下降 (SGD) 和 Adam,在实际应用中展现出截然不同的特性。

数学原理对比
基础 SGD 更新规则
传统 SGD 的参数更新非常简单:
θ_{t+1} = θ_t - η·∇_θJ(θ_t)
其中 η 是学习率,∇_θJ(θ_t)是当前参数 θ_t 下的梯度。这个朴素版本在实践中往往收敛缓慢且容易陷入局部最优。
SGD with Momentum
引入动量 (momentum) 后的 SGD 可以积累之前的梯度信息:
- 计算当前梯度:g_t = ∇_θJ(θ_t)
- 更新动量项:v_t = γ·v_{t-1} + η·g_t
- 参数更新:θ_{t+1} = θ_t – v_t
其中 γ 是动量系数(通常 0.9),v_t 是当前动量。这种 ” 惯性 ” 特性帮助算法越过局部极小点。
Adam 更新规则
Adam(Adaptive Moment Estimation)结合了动量思想和自适应学习率:
- 计算梯度:g_t = ∇_θJ(θ_t)
- 更新一阶矩估计:m_t = β1·m_{t-1} + (1-β1)·g_t
- 更新二阶矩估计:v_t = β2·v_{t-1} + (1-β2)·g_t²
- 偏差校正:m̂_t = m_t/(1-β1^t), v̂_t = v_t/(1-β2^t)
- 参数更新:θ_{t+1} = θ_t – η·m̂_t/(√v̂_t + ε)
其中 β1、β2 通常取 0.9 和 0.999,ε 是为数值稳定的小常数(默认 1e-8)。
核心差异分析
收敛速度
- Adam 通常在前中期训练阶段收敛更快,尤其适合稀疏梯度场景
- SGD(with momentum)在后期可能找到更精确的最优点,适合需要精细调优的任务
内存占用
- Adam 需要维护 m_t 和 v_t 两个状态变量,内存占用是 SGD 的两倍
- 对于超大模型(如 LLM),这可能成为显存瓶颈
超参数敏感性
- SGD 对学习率 η 非常敏感,需要精心设置学习率调度
- Adam 对初始学习率的鲁棒性更强,但 β1、β2 和 ε 也需要适当调整
PyTorch 实现对比
import torch
import torch.nn as nn
import torch.optim as optim
torch.manual_seed(42) # 固定随机种子
# 定义简单模型
model = nn.Sequential(nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
# SGD with Momentum 配置
optimizer_sgd = optim.SGD(model.parameters(),
lr=0.01,
momentum=0.9
)
# Adam 配置
optimizer_adam = optim.Adam(model.parameters(),
lr=0.001,
betas=(0.9, 0.999),
eps=1e-8
)
# 学习率调度示例
scheduler_sgd = optim.lr_scheduler.StepLR(
optimizer_sgd,
step_size=30,
gamma=0.1
)
scheduler_adam = optim.lr_scheduler.ReduceLROnPlateau(
optimizer_adam,
mode='min',
patience=5,
factor=0.5
)
实践中的避坑指南
Adam 常见误区
- ε 参数不应随意调大:默认 1e- 8 通常足够,增大可能影响稳定性
- 学习率不宜过高:Adam 的自适应特性使得其有效学习率比设定值大
- 在 GAN 等特殊场景中,Adam 可能导致模式坍塌
SGD 调优技巧
- 配合学习率 warmup:前几个 epoch 逐步提高学习率
- 动量系数 0.9 是良好起点,对 CV 任务可尝试 0.99
- 周期性学习率重置 (如 SGDR) 可能带来意外收益
MNIST 上的性能对比实验
我们构建了包含 2 个隐藏层的 MLP,批量大小 128,训练 50 个 epoch:
| 指标 | SGD+momentum | Adam |
|---|---|---|
| 最终准确率 | 98.2% | 98.5% |
| 达到 95% 准确率 | epoch 12 | epoch 6 |
| 显存占用(MB) | 45 | 52 |
Adam 的泛化性能讨论
ICLR 2018 论文指出:
- Adam 在训练集上收敛更快,但测试集表现有时不如 SGD
- 自适应方法找到的最优点可能位于较 ” 尖锐 ” 的区域
- 对于需要强泛化的任务,后期切换为 SGD 可能有益
思考与实践建议
- 默认首选 Adam:适合大多数前中期训练场景
- 计算资源紧张时考虑 SGD:减少显存占用
- 最终微调阶段尝试 SGD:可能获得更好的泛化性能
- 对于周期性数据:SGDR(SGD with warm restart)值得尝试
留给读者的思考题
在实际项目中,你会根据哪些具体信号决定从 Adam 切换回 SGD 进行模型微调?
正文完
