PyTorch优化器全解析:从SGD到AdamW,选对算法让模型训练事半功倍
在深度学习的训练过程中,优化器 扮演着至关重要的角色。它负责根据损失函数计算出的梯度,更新模型的权重,从而不断降低训练误差。PyTorch 的 torch.optim 模块提供了丰富的优化算法,几乎涵盖了现代深度学习中所有主流优化器。本文将对 PyTorch 中常用的优化器进行简要介绍。
常用优化器
Adadelta
特点:Adadelta 是 Adagrad 的改进,不再需要手动设置全局学习率,使用参数更新的平方梯度来调整学习率。
优点:消除了对全局学习率的依赖,训练后期仍能保持更新。
缺点:计算量稍大,部分任务上收敛速度不如 Adam。
Adafactor
特点:专为大模型设计,矩阵参数按行、列分别维护二阶矩,大幅减少内存占用。
优点:内存效率极高,适合 Transformer 等大参数量模型。
缺点:非矩阵参数表现可能下降,某些任务需要调整阈值。
Adagrad
特点:自适应调整学习率,频繁更新的参数学习率小,稀疏参数学习率大。
优点:适合处理稀疏特征(如词嵌入、推荐系统)。
缺点:学习率单调递减,后期过于保守,容易提前停止学习。
Adam
特点:结合动量和 RMSprop,同时维护一阶矩(动量)和二阶矩(自适应学习率)。
优点:收敛快,对超参数鲁棒,适用绝大多数深度学习任务。
缺点:可能泛化性略差于 SGD,权重衰减实现不理想(原始 Adam)。
AdamW
特点:将权重衰减从梯度更新中解耦,独立施加于参数。
优点:改善泛化性能,训练更稳定,是目前 Adam 的推荐替代。
缺点:比原始 Adam 多一个超参数(weight decay),但通常默认值 0.01 即可。
SparseAdam
特点:Adam 的变体,专门处理稀疏梯度(如 Embedding 层)。
优点:对稀疏参数更新高效,内存使用更优。
缺点:仅适用于稀疏梯度场景,稠密梯度下不如标准 Adam。
Adamax
特点:Adam 的变体,使用无穷范数替代二阶矩。
优点:在某些任务(如 GAN、强化学习)比 Adam 更稳定。
缺点:适用范围较窄,不是通用首选。
ASGD(平均 SGD)
特点:标准 SGD 加上参数平均,最终返回训练过程中的平均权重。
优点:提高泛化能力,收敛结果通常更平滑。
缺点:需要保存平均参数,增加内存;收敛速度不占优势。
LBFGS
特点:拟牛顿法,利用历史梯度近似 Hessian 矩阵的逆。
优点:收敛速度快(尤其在小规模问题),参数更新更精准。
缺点:内存和计算开销大,不适合大型数据集或深度网络。
NAdam
特点:Nesterov 动量 + Adam,利用前瞻梯度更新。
优点:收敛速度和稳定性进一步提升,理论上有更优 regret bound。
缺点:相比 Adam 提升有限,实际应用中非必选。
RAdam
特点:Adam 的整流版本,训练初期根据方差自适应调整动量。
优点:缓解 Adam 早期因采样不足导致的发散问题,训练更稳定。
缺点:相比 Adam 多一步计算,但开销可忽略。
RMSprop
特点:使用均方根(RMS)缩放学习率,解决 Adagrad 学习率过快衰减的问题。
优点:适合非平稳目标(如 RNN、语音任务),无需全局学习率精细调参。
缺点:依然需要设置初始学习率,对某些任务不如 Adam 通用。
Rprop(弹性反向传播)
特点:仅使用梯度符号,而非梯度大小,独立调整每个权重的更新步长。
优点:收敛快,对梯度缩放不敏感。
缺点:不适用于 mini-batch 训练(梯度波动会导致效果下降),主要用于全批量学习。
SGD(随机梯度下降)
特点:最基础的优化器,沿着负梯度方向更新,支持动量(Momentum)。
优点:泛化性能优异,理论和实践都很成熟。
缺点:收敛慢,对学习率和动量系数敏感,需要仔细调参。
选择方法
虽然优化器有很多,但在实际应用中,绝大多数任务都可以从 Adam 或 SGD 开始尝试:
Adam:收敛快,对超参数相对不敏感,适合大多数分类、生成任务。
SGD (with momentum):虽然收敛较慢,但通常能获得更好的泛化能力,尤其适合图像分类等任务。
AdamW:如果使用 Adam 出现过拟合或正则化效果不佳,可以尝试 AdamW。
对于大规模稀疏特征(如推荐系统、NLP 词嵌入),可以考虑 Adagrad 或 SparseAdam。 对于内存有限的大模型训练,Adafactor 是不错的选择。
使用示例
下面是一个简单的 PyTorch 优化器使用示例(以 Adam 为例):
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个简单模型
model = nn.Linear(10, 2)
# 定义损失函数
criterion = nn.CrossEntropyLoss()
# 定义优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 模拟训练步骤
inputs = torch.randn(4, 10)
labels = torch.tensor([0, 1, 0, 1])
# 前向传播
outputs = model(inputs)
loss = criterion(outputs, labels)
# 反向传播与参数更新
optimizer.zero_grad()
loss.backward()
optimizer.step()
总结
PyTorch 提供的优化器涵盖了从经典 SGD 到自适应学习率算法,再到专门用于稀疏梯度和大规模模型的多种选择。理解每种优化器的基本原理和适用场景,能够帮助我们在实际项目中更高效地训练模型。
一般来说:
- 快速试验 → Adam
- 追求极致泛化 → SGD + Momentum
- 需要正则化效果更优 → AdamW