根据 PyTorch 官网(pytorch.org)的文档,torch.optim
是 PyTorch 中用于优化神经网络参数的模块,提供了多种优化算法(如 SGD、Adam 等)。以下是对 torch.optim
模块中所有优化器及其核心方法的详细讲解,基于官方文档(截至 2025 年 9 月 9 日的最新信息)以及 torch.optim
的功能。
torch.optim
模块包含多个优化器类,每个优化器都继承自 torch.optim.Optimizer
基类。优化器的主要作用是通过梯度下降或其他优化算法更新模型参数。以下是 torch.optim
模块中常见优化器及其方法的讲解,结合代码示例和实际用途。
1. torch.optim.Optimizer
基类
所有优化器都继承自 torch.optim.Optimizer
,它是所有优化器的基类,定义了通用的方法和属性。
核心方法
以下是 torch.optim.Optimizer
基类中定义的主要方法:
-
__init__(params, defaults)
- 作用: 初始化优化器,指定需要优化的参数和默认超参数。
- 参数:
params
: 可迭代对象,通常是模型参数(通过model.parameters()
获取)或参数组(包含参数和特定超参数的字典列表)。defaults
: 默认的超参数字典(如学习率lr
、动量momentum
等)。
- 示例:
import torch import torch.nn as nn import torch.optim as optim model = nn.Linear(10, 2) optimizer = optim.SGD(model.parameters(), lr=0.01)
-
zero_grad(set_to_none=True)
- 作用: 将所有优化参数的梯度清零,为下一次前向传播和反向传播做准备。
- 参数:
set_to_none
: 如果为True
,梯度张量被设置为None
(更高效);如果为False
,梯度被置为 0。
- 用途: 在每次优化步骤前调用,以避免梯度累积。
- 示例:
optimizer.zero_grad() # 清零梯度
-
step(closure=None)
- 作用: 执行一次优化步骤,更新模型参数。
- 参数:
closure
: 可选的闭包函数,用于某些需要多次计算梯度的优化器(如 LBFGS)。
- 用途: 根据梯度和优化算法更新参数。
- 示例:
loss = loss_fn(model(inputs), targets) loss.backward() # 计算梯度 optimizer.step() # 更新参数
-
add_param_group(param_group)
- 作用: 向优化器添加新的参数组,允许对不同参数设置不同的超参数(如学习率)。
- 参数:
param_group
: 包含参数和超参数的字典,如{'params': parameters, 'lr': 0.01}
。
- 用途: 用于动态调整优化器管理的参数或为不同层设置不同的学习率。
- 示例:
optimizer.add_param_group({'params': model.new_layer.parameters(), 'lr': 0.001})
-
state_dict()
- 作用: 返回优化器的状态字典,包含优化器的超参数和状态(如动量缓冲区)。
- 用途: 用于保存优化器状态以便后续恢复。
- 示例:
torch.save(optimizer.state_dict(), 'optimizer.pth')
-
load_state_dict(state_dict)
- 作用: 从状态字典中加载优化器状态。
- 参数:
state_dict
: 通过state_dict()
保存的状态字典。
- 用途: 用于恢复优化器状态,通常与模型权重恢复一起使用。
- 示例:
optimizer.load_state_dict(torch.load('optimizer.pth'))
-
param_groups
属性- 作用: 优化器管理的参数组列表,每个参数组是一个字典,包含参数和对应的超参数。
- 用途: 可用于检查或修改优化器的参数组。
- 示例:
for group in optimizer.param_groups: print(group['lr']) # 打印每个参数组的学习率
2. 常见优化器
torch.optim
提供了多种优化算法,每种优化器都继承自 Optimizer
基类,并实现了特定的 step()
方法。以下是常见优化器的介绍及其特定参数。
2.1 torch.optim.SGD
- 描述: 随机梯度下降(Stochastic Gradient Descent),支持动量法和 Nesterov 动量。
- 初始化参数:
params
: 优化参数。lr
(float): 学习率(必须)。momentum
(float, optional): 动量因子(默认 0)。weight_decay
(float, optional): L2 正则化系数(默认 0)。dampening
(float, optional): 动量阻尼(默认 0)。nesterov
(bool, optional): 是否使用 Nesterov 动量(默认 False)。
- 示例:
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=1e-4)
2.2 torch.optim.Adam
- 描述: Adam 优化器,结合一阶和二阶动量,自适应调整学习率。
- 初始化参数:
params
: 优化参数。lr
(float, optional): 学习率(默认 1e-3)。betas
(tuple, optional): 动量系数(beta1, beta2)
(默认 (0.9, 0.999))。eps
(float, optional): 数值稳定性小值(默认 1e-8)。weight_decay
(float, optional): L2 正则化系数(默认 0)。amsgrad
(bool, optional): 是否使用 AMSGrad 变体(默认 False)。
- 示例:
optimizer = optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999), weight_decay=1e-2)
2.3 torch.optim.AdamW
- 描述: Adam 的改进版本,解耦权重衰减(更适合正则化)。
- 初始化参数:
- 与
Adam
类似,但weight_decay
默认值为 1e-2。
- 与
- 示例:
optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
2.4 torch.optim.RMSprop
- 描述: RMSprop 优化器,使用移动平均的平方梯度来归一化梯度。
- 初始化参数:
params
: 优化参数。lr
(float, optional): 学习率(默认 1e-2)。alpha
(float, optional): 平滑因子(默认 0.99)。eps
(float, optional): 数值稳定性小值(默认 1e-8)。weight_decay
(float, optional): L2 正则化系数(默认 0)。momentum
(float, optional): 动量因子(默认 0)。centered
(bool, optional): 是否中心化梯度(默认 False)。
- 示例:
optimizer = optim.RMSprop(model.parameters(), lr=0.01, alpha=0.99)
2.5 torch.optim.Adagrad
- 描述: Adagrad 优化器,自适应调整学习率,适合稀疏数据。
- 初始化参数:
params
: 优化参数。lr
(float, optional): 学习率(默认 1e-2)。lr_decay
(float, optional): 学习率衰减(默认 0)。weight_decay
(float, optional): L2 正则化系数(默认 0)。eps
(float, optional): 数值稳定性小值(默认 1e-10)。
- 示例:
optimizer = optim.Adagrad(model.parameters(), lr=0.01)
2.6 torch.optim.Adadelta
- 描述: Adadelta 优化器,Adagrad 的改进版本,无需手动设置学习率。
- 初始化参数:
params
: 优化参数。lr
(float, optional): 初始学习率(默认 1.0)。rho
(float, optional): 梯度平方移动平均的衰减率(默认 0.9)。eps
(float, optional): 数值稳定性小值(默认 1e-6)。weight_decay
(float, optional): L2 正则化系数(默认 0)。
- 示例:
optimizer = optim.Adadelta(model.parameters(), lr=1.0)
2.7 torch.optim.LBFGS
- 描述: L-BFGS 优化器,适合小规模数据,使用二阶信息。
- 初始化参数:
params
: 优化参数。lr
(float): 学习率(默认 1)。max_iter
(int, optional): 每次优化的最大迭代次数(默认 20)。max_eval
(int, optional): 每次优化的最大函数评估次数(默认 None)。tolerance_grad
(float, optional): 梯度收敛阈值(默认 1e-7)。tolerance_change
(float, optional): 参数变化收敛阈值(默认 1e-9)。history_size
(int, optional): 历史更新向量数量(默认 100)。
- 注意: 需要提供闭包函数给
step()
。 - 示例:
optimizer = optim.LBFGS(model.parameters(), lr=1) def closure(): optimizer.zero_grad() loss = loss_fn(model(inputs), targets) loss.backward() return loss optimizer.step(closure)
2.8 其他优化器
torch.optim.Adamax
: Adam 的变体,基于无穷范数。torch.optim.ASGD
: 平均随机梯度下降,适合非凸问题。torch.optim.Rprop
: 弹性反向传播,适合全批量梯度下降。torch.optim.SparseAdam
: Adam 的稀疏版本,适合稀疏张量。
3. 学习率调度器(torch.optim.lr_scheduler
)
虽然 lr_scheduler
不是 torch.optim
的核心部分,但它与优化器密切相关,用于动态调整学习率。以下是常见调度器及其方法:
-
常见调度器:
torch.optim.lr_scheduler.StepLR
: 每隔固定步数降低学习率。torch.optim.lr_scheduler.MultiStepLR
: 在指定步数降低学习率。torch.optim.lr_scheduler.ExponentialLR
: 指数衰减学习率。torch.optim.lr_scheduler.CosineAnnealingLR
: 余弦退火调整学习率。torch.optim.lr_scheduler.ReduceLROnPlateau
: 根据指标(如验证损失)降低学习率。
-
核心方法:
step()
: 更新学习率,通常在每个 epoch 或 step 调用。get_last_lr()
: 获取当前学习率。state_dict()
和load_state_dict()
: 保存和加载调度器状态。
-
示例:
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1) for epoch in range(100): optimizer.step() scheduler.step() # 每 10 个 epoch 降低学习率
4. 实际使用示例
以下是一个完整的训练循环示例,展示优化器和调度器的使用:
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
model = nn.Linear(10, 1)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
# 训练循环
for epoch in range(50):
optimizer.zero_grad() # 清零梯度
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward() # 计算梯度
optimizer.step() # 更新参数
scheduler.step() # 更新学习率
print(f'Epoch {epoch}, Loss: {loss.item()}, LR: {scheduler.get_last_lr()[0]}')
5. 注意事项
- 选择优化器: 根据任务选择合适的优化器。Adam 和 AdamW 是大多数深度学习任务的默认选择;SGD 适合需要精细控制的任务;LBFGS 适合小规模数据集。
- 超参数调优: 学习率、动量等超参数对收敛影响很大,需通过实验调整。
- 梯度裁剪: 对于梯度爆炸问题,可使用
torch.nn.utils.clip_grad_norm_
。 - 保存和加载: 训练时应同时保存模型和优化器状态。
如果需要更详细的某优化器或方法的解释,或者需要针对具体任务的优化建议,请告诉我!
我来为你详细解释 torch.optim
中提到的这些优化器(SGD、LBFGS、Adadelta、Adagrad、RMSProp、Adam、AdamW)的概念和特点。这些都是 PyTorch 中用于优化神经网络参数的算法,基于梯度下降的原理,但各有不同的改进和适用场景。以下是简洁而清晰的讲解,尽量避免重复之前的内容,并专注于每个优化器的核心思想、公式和用途。
1. SGD(Stochastic Gradient Descent,随机梯度下降)
- 是什么:
- SGD 是最基础的优化算法,通过梯度下降更新参数,每次使用一个样本或一个小批量(mini-batch)计算梯度。
- 支持动量法(Momentum)和 Nesterov 动量,进一步加速收敛。
- 核心思想:
- 参数更新基于梯度的负方向,步长由学习率控制。
- 动量法通过累积历史梯度加速更新,Nesterov 动量在计算梯度时考虑了动量的前瞻性。
- 更新公式:
- 基本 SGD:
( \theta_{t+1} = \theta_t - \eta \cdot \nabla_\theta J(\theta_t) )- (\eta): 学习率
- (\nabla_\theta J): 损失函数 (J) 对参数 (\theta) 的梯度
- 带动量:
( v_t = \gamma v_{t-1} + \eta \cdot \nabla_\theta J(\theta_t) )
( \theta_{t+1} = \theta_t - v_t )- (\gamma): 动量因子(通常 0.9)
- Nesterov 动量:
( v_t = \gamma v_{t-1} + \eta \cdot \nabla_\theta J(\theta_t - \gamma v_{t-1}) )
( \theta_{t+1} = \theta_t - v_t )
- 基本 SGD:
- 特点:
- 简单,易于理解,适合大多数任务。
- 需要手动调整学习率,可能收敛较慢。
- 动量和 Nesterov 动量能加速收敛,减少震荡。
- 适用场景:
- 凸优化问题或需要精细控制的任务。
- 常用于简单的神经网络或大型数据集。
- PyTorch 示例:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9, nesterov=True)
2. LBFGS(Limited-memory Broyden-Fletcher-Goldfarb-Shanno)
- 是什么:
- LBFGS 是一种准牛顿法(Quasi-Newton Method),使用二阶信息(近似 Hessian 矩阵)来优化参数。
- 它是 BFGS 算法的内存优化版本,适合小规模数据集。
- 核心思想:
- 利用历史梯度和参数更新信息近似计算 Hessian 矩阵的逆,指导更高效的参数更新。
- 需要闭包函数多次计算梯度和损失。
- 更新公式:
- 复杂且依赖于近似 Hessian 的逆,无法简单表达。
- 核心是基于历史梯度和参数变化构建搜索方向,更新参数。
- 特点:
- 收敛速度快,适合小型数据集。
- 计算开销大,内存需求较高。
- 需要提供闭包函数,代码实现稍复杂。
- 适用场景:
- 小规模数据集或非深度学习任务(如逻辑回归)。
- 不适合大规模深度神经网络(因内存和计算限制)。
- PyTorch 示例:
optimizer = torch.optim.LBFGS(model.parameters(), lr=1) def closure(): optimizer.zero_grad() loss = loss_fn(model(inputs), targets) loss.backward() return loss optimizer.step(closure)
3. Adagrad(Adaptive Gradient Algorithm)
- 是什么:
- Adagrad 是一种自适应学习率的优化算法,通过累积历史梯度的平方来自动调整学习率。
- 核心思想:
- 为每个参数分配不同的学习率,频繁更新的参数学习率较小,稀疏更新的参数学习率较大。
- 适合处理稀疏数据(如自然语言处理中的词嵌入)。
- 更新公式:
- ( G_t = G_{t-1} + (\nabla_\theta J(\theta_t))^2 )
- ( \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t} + \epsilon} \cdot \nabla_\theta J(\theta_t) )
- (G_t): 梯度平方的累积
- (\epsilon): 数值稳定性小值(防止除零)
- 特点:
- 自适应学习率,初期收敛快。
- 后期因 (G_t) 持续累积,学习率可能变得过小,导致收敛停滞。
- 适用场景:
- 稀疏数据或凸优化问题。
- 不适合深度神经网络(因学习率衰减过快)。
- PyTorch 示例:
optimizer = torch.optim.Adagrad(model.parameters(), lr=0.01)
4. Adadelta
- 是什么:
- Adadelta 是 Adagrad 的改进版本,解决了学习率过快衰减的问题,无需手动设置初始学习率。
- 核心思想:
- 使用固定时间窗口的梯度平方移动平均代替 Adagrad 的累积和。
- 引入参数更新的移动平均来稳定更新步长。
- 更新公式:
- ( E[g^2]t = \rho E[g^2]{t-1} + (1-\rho)(\nabla_\theta J(\theta_t))^2 )
- ( \Delta \theta_t = -\frac{\sqrt{E[\Delta \theta^2]_{t-1} + \epsilon}}{\sqrt{E[g^2]t + \epsilon}} \cdot \nabla\theta J(\theta_t) )
- ( \theta_{t+1} = \theta_t + \Delta \theta_t )
- (\rho): 衰减率(类似动量)
- (E[\Delta \theta^2]): 参数更新的移动平均
- 特点:
- 无需手动设置学习率,适合长期训练。
- 比 Adagrad 更稳定,但仍可能对超参数敏感。
- 适用场景:
- 稀疏数据或需要稳定学习率的场景。
- 比 Adagrad 更适合深度学习任务。
- PyTorch 示例:
optimizer = torch.optim.Adadelta(model.parameters(), lr=1.0, rho=0.9)
5. RMSProp(Root Mean Square Propagation)
- 是什么:
- RMSProp 是 Adagrad 的另一种改进,通过指数移动平均来限制梯度平方的累积,保持学习率稳定。
- 核心思想:
- 类似 Adadelta,使用梯度平方的指数移动平均来归一化梯度。
- 比 Adagrad 更适合非凸问题(如深度神经网络)。
- 更新公式:
- ( E[g^2]t = \alpha E[g^2]{t-1} + (1-\alpha)(\nabla_\theta J(\theta_t))^2 )
- ( \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{E[g^2]t + \epsilon}} \cdot \nabla\theta J(\theta_t) )
- (\alpha): 平滑因子(默认 0.99)
- 特点:
- 学习率自适应,适合深度学习。
- 超参数(如 (\alpha)、(\epsilon))对性能影响较大。
- 适用场景:
- 深度神经网络,尤其适合非平稳目标函数。
- PyTorch 示例:
optimizer = torch.optim.RMSprop(model.parameters(), lr=0.01, alpha=0.99)
6. Adam(Adaptive Moment Estimation)
- 是什么:
- Adam 结合了动量法和 RMSProp,通过一阶动量(梯度均值)和二阶动量(梯度平方均值)自适应调整学习率。
- 核心思想:
- 使用梯度的指数移动平均(一阶动量)和梯度平方的指数移动平均(二阶动量)来更新参数。
- 包含偏差校正,初期更稳定。
- 更新公式:
- 一阶动量: ( m_t = \beta_1 m_{t-1} + (1-\beta_1) \nabla_\theta J(\theta_t) )
- 二阶动量: ( v_t = \beta_2 v_{t-1} + (1-\beta_2) (\nabla_\theta J(\theta_t))^2 )
- 偏差校正: ( \hat{m}_t = \frac{m_t}{1-\beta_1^t} ), ( \hat{v}_t = \frac{v_t}{1-\beta_2^t} )
- 参数更新: ( \theta_{t+1} = \theta_t - \frac{\eta \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} )
- (\beta_1, \beta_2): 动量系数(默认 0.9, 0.999)
- 特点:
- 收敛快,超参数鲁棒性强。
- 是深度学习任务的默认选择。
- 适用场景:
- 几乎所有深度学习任务(图像、NLP 等)。
- PyTorch 示例:
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))
7. AdamW
- 是什么:
- AdamW 是 Adam 的改进版本,解耦了权重衰减(Weight Decay)与优化步骤,优化正则化效果。
- 核心思想:
- 在 Adam 的基础上,将权重衰减从梯度更新中分离,直接应用于参数。
- 更适合正则化,防止过拟合。
- 更新公式:
- 与 Adam 类似,但在参数更新时显式添加权重衰减项:
( \theta_{t+1} = \theta_t - \frac{\eta \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} - \eta \lambda \theta_t )- (\lambda): 权重衰减系数
- 与 Adam 类似,但在参数更新时显式添加权重衰减项:
- 特点:
- 比 Adam 更适合需要强正则化的任务。
- 通常比 Adam 性能略好,尤其在 Transformer 等模型中。
- 适用场景:
- 深度学习任务,尤其是需要正则化的场景(如 Transformer 模型)。
- PyTorch 示例:
optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
总结对比
优化器 | 自适应学习率 | 动量 | 适合场景 | 优点 | 缺点 |
---|---|---|---|---|---|
SGD | 否 | 可选 | 简单任务、大规模数据 | 简单,易于调试 | 收敛慢,需调学习率 |
LBFGS | 否 | 无 | 小规模数据集、凸优化 | 收敛快 | 内存占用高,不适合深度学习 |
Adagrad | 是 | 无 | 稀疏数据、凸优化 | 自适应,适合稀疏数据 | 学习率过快衰减 |
Adadelta | 是 | 无 | 稀疏数据、深度学习 | 无需设学习率,较稳定 | 超参数敏感 |
RMSProp | 是 | 可选 | 深度学习、非平稳目标 | 适合非凸问题 | 超参数需调优 |
Adam | 是 | 是 | 几乎所有深度学习任务 | 收敛快,鲁棒性强 | 正则化效果稍弱 |
AdamW | 是 | 是 | 深度学习、需要正则化 | 改进正则化,性能更优 | 超参数需调优 |
选择建议
- 默认选择: Adam 或 AdamW,适合大多数深度学习任务,收敛快且超参数鲁棒。
- 稀疏数据: Adagrad 或 Adadelta,适合 NLP 或推荐系统。
- 简单任务或需精细控制: SGD(带动量)。
- 小数据集: LBFGS(需闭包函数)。
- Transformer 模型: AdamW 是首选(如 BERT、GPT 等)。
如果你对某个优化器的实现细节、数学推导或具体应用场景有疑问,或者想看某优化器的代码示例,请告诉我,我可以进一步展开!