torch.optim 是一个实现各种优化算法的包。 大部分常用的方法都已经支持,接口也足够通用,以后也可以轻松集成更复杂的方法。
How to use an optimizer
要使用 torch.optim,您必须构造一个优化器对象,该对象将保存当前状态并根据计算出的梯度更新参数。
构建它
要构造一个优化器,你必须给它一个包含要优化的参数(都应该是 Variable)的迭代。 然后,您可以指定特定于优化器的选项,例如学习率、权重衰减等。
如果您需要通过 .cuda() 将模型移动到 GPU,请在为其构建优化器之前执行此操作。 .cuda() 之后的模型参数将是与调用之前不同的对象。
通常,在构建和使用优化器时,您应该确保优化的参数位于一致的位置。
例子:
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr=0.0001)
每个参数选项
优化器还支持指定每个参数的选项。 为此,不要传递 Variable 的迭代,而是传递 dict 的迭代。 它们中的每一个都将定义一个单独的参数组,并且应该包含一个 params 键,其中包含一个属于它的参数列表。 其他键应与优化器接受的关键字参数匹配,并将用作该组的优化选项。
您仍然可以将选项作为关键字参数传递。 它们将在没有覆盖它们的组中用作默认值。 当您只想改变单个选项,同时在参数组之间保持所有其他选项一致时,这很有用。
例如,当您想要指定每层学习率时,这非常有用:
optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 1e-3}
], lr=1e-2, momentum=0.9)
这意味着model.base的参数将使用默认的1e-2学习率,model.classifier的参数将使用1e-3的学习率,所有参数将使用0.9的动量。
采取优化步骤
所有优化器都实现了一个 step() 方法,该方法更新参数。 它可以通过两种方式使用:
optimizer.step()
这是大多数优化器支持的简化版本。 一旦使用例如backward()计算梯度,就可以调用该函数。
例子:
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
optimizer.step(closure)
一些优化算法(例如共轭梯度和 LBFGS)需要多次重新计算函数,因此您必须传入一个闭包,以便它们重新计算您的模型。 闭包应该清除梯度,计算损失并返回它。
例子:
for input, target in dataset:
def closure():
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
return loss
optimizer.step(closure)
Base class
CLASS torch.optim.Optimizer(params, defaults)
所有优化器的基类。
warning:
需要将参数指定为具有在运行之间一致的确定性排序的集合。 不满足这些属性的对象的例子是字典值的集合和迭代器。
参数:
1、params (iterable) – 一个 Torch.Tensor 或 dict 的迭代。 指定应该优化哪些张量。
2、defaults – (dict):一个包含优化选项默认值的字典(当参数组没有指定它们时使用)。
向优化器的 param_groups 添加一个参数组。 | |
加载优化器状态。 | |
以字典的形式返回优化器的状态。 | |
执行单个优化步骤(参数更新)。 | |
将所有优化的 torch.Tensor 的梯度设置为零。 |
Algorithms
实现 Adadelta 算法。 | |
实现 Adagrad 算法。 | |
实现Adam算法。 | |
实现 AdamW 算法。 | |
实现适用于稀疏张量的 Adam 算法的惰性版本。 | |
实现 Adamax 算法(基于无穷范数的 Adam 变体)。 | |
实现平均随机梯度下降。 | |
实现 L-BFGS 算法,深受 minFunc 的启发。 | |
实现 RMSprop 算法。 | |
实现弹性反向传播算法。 | |
实现随机梯度下降(可选动量)。 |
How to adjust learning rate
torch.optim.lr_scheduler 提供了多种方法来根据 epoch 数调整学习率。 torch.optim.lr_scheduler.ReduceLROnPlateau 允许基于一些验证测量降低动态学习率。
学习率调度应在优化器更新后应用; 例如,你应该这样写你的代码:
例子:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler = ExponentialLR(optimizer, gamma=0.9)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler.step()
大多数学习率调度器都可以称为back-to-back(也称为链式调度器)。 结果是每个调度器都被一个接一个地应用于前一个调度器获得的学习率。
例子:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler1 = ExponentialLR(optimizer, gamma=0.9)
scheduler2 = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler1.step()
scheduler2.step()
在文档的许多地方,我们将使用以下模板来引用调度程序算法。
>>> scheduler = ...
>>> for epoch in range(100):
>>> train(...)
>>> validate(...)
>>> scheduler.step()
warning
在 PyTorch 1.1.0 之前,学习率调度器预计会在优化器更新之前被调用; 1.1.0 以一种打破 BC 的方式改变了这种行为。 如果在优化器更新(调用 optimizer.step())之前使用学习率调度器(调用 scheduler.step()),这将跳过学习率调度的第一个值。 如果升级到 PyTorch 1.1.0 后无法重现结果,请检查您是否在错误的时间调用了 scheduler.step()。
Sets the learning rate of each parameter group to the initial lr times a given function. | |
Multiply the learning rate of each parameter group by the factor given in the specified function. | |
Decays the learning rate of each parameter group by gamma every step_size epochs. | |
Decays the learning rate of each parameter group by gamma once the number of epoch reaches one of the milestones. | |
Decays the learning rate of each parameter group by gamma every epoch. | |
Set the learning rate of each parameter group using a cosine annealing schedule, where \eta_{max}ηmax is set to the initial lr and T_{cur}Tcur is the number of epochs since the last restart in SGDR: | |
Reduce learning rate when a metric has stopped improving. | |
Sets the learning rate of each parameter group according to cyclical learning rate policy (CLR). | |
Sets the learning rate of each parameter group according to the 1cycle learning rate policy. | |
Set the learning rate of each parameter group using a cosine annealing schedule, where \eta_{max}ηmax is set to the initial lr, T_{cur}Tcur is the number of epochs since the last restart and T_{i}Ti is the number of epochs between two warm restarts in SGDR: |
Stochastic Weight Averaging
torch.optim.swa_utils 实现随机权重平均 (SWA)。 特别是,torch.optim.swa_utils.AveragedModel 类实现了 SWA 模型,torch.optim.swa_utils.SWALR 实现了 SWA 学习率调度程序,torch.optim.swa_utils.update_bn() 是一个实用函数,用于在 训练结束。
SWA 已在 Averaging Weights Leads to Wide Optima and Better Generalization 中提出。
Constructing averaged models
AveragedModel 类用于计算 SWA 模型的权重。 您可以通过运行来创建平均模型:
>>> swa_model = AveragedModel(model)
这里模型可以是任意的 torch.nn.Module 对象。 swa_model 将跟踪模型参数的运行平均值。 要更新这些平均值,您可以使用 update_parameters() 函数:
>>> swa_model.update_parameters(model)
SWA learning rate schedules
通常,在 SWA 中,学习率设置为较高的恒定值。 SWALR 是一种学习率调度器,它将学习率退火到一个固定值,然后保持不变。 例如,以下代码创建了一个调度程序,它在每个参数组内的 5 个时期内将学习率从其初始值线性退火到 0.05:
>>> swa_scheduler = torch.optim.swa_utils.SWALR(optimizer, \
>>> anneal_strategy="linear", anneal_epochs=5, swa_lr=0.05)
您还可以通过设置anneal_strategy="cos" 将余弦退火用于固定值而不是线性退火。
Taking care of batch normalization
update_bn() 是一个实用函数,它允许在训练结束时在给定的数据加载器上计算 SWA 模型的batchnorm 统计信息:
>>> torch.optim.swa_utils.update_bn(loader, swa_model)
update_bn() 将 swa_model 应用于数据加载器中的每个元素,并计算模型中每个batch normalization层的激活统计信息。
warning
update_bn() 假设数据加载器加载器中的每个批次都是张量或张量列表,其中第一个元素是应应用网络 swa_model 的张量。 如果您的数据加载器具有不同的结构,您可以通过在数据集的每个元素上使用 swa_model 进行前向传递来更新 swa_model 的批量标准化统计信息。
Custom averaging strategies
默认情况下,torch.optim.swa_utils.AveragedModel 计算您提供的参数的运行相等平均值,但您也可以使用带有 avg_fn 参数的自定义平均函数。 在以下示例中,ema_model 计算指数移动平均线。
例子:
>>> ema_avg = lambda averaged_model_parameter, model_parameter, num_averaged:\
>>> 0.1 * averaged_model_parameter + 0.9 * model_parameter
>>> ema_model = torch.optim.swa_utils.AveragedModel(model, avg_fn=ema_avg)
Putting it all together
在下面的示例中,swa_model 是累积权重平均值的 SWA 模型。 我们总共训练了 300 个时期的模型,然后切换到 SWA 学习率计划并开始收集第 160 个时期参数的 SWA 平均值:
>>> loader, optimizer, model, loss_fn = ...
>>> swa_model = torch.optim.swa_utils.AveragedModel(model)
>>> scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=300)
>>> swa_start = 160
>>> swa_scheduler = SWALR(optimizer, swa_lr=0.05)
>>>
>>> for epoch in range(300):
>>> for input, target in loader:
>>> optimizer.zero_grad()
>>> loss_fn(model(input), target).backward()
>>> optimizer.step()
>>> if epoch > swa_start:
>>> swa_model.update_parameters(model)
>>> swa_scheduler.step()
>>> else:
>>> scheduler.step()
>>>
>>> # Update bn statistics for the swa_model at the end
>>> torch.optim.swa_utils.update_bn(loader, swa_model)
>>> # Use swa_model to make predictions on test data
>>> preds = swa_model(test_input)