金洋新闻
分类

torch.optim_2

发布时间:2024-04-29 04:08:08    浏览:

[返回]

是一个实现各种优化算法的软件包。大多数常用的方法都已经支持,并且接口足够通用,因此将来也可以轻松集成更复杂的方法。

要使用 ,您必须构造一个优化器对象,该对象将保存当前状态并根据计算的梯度更新参数。

要构建 ,您必须为其提供一个包含要优化的参数(全部应为 )的迭代。然后,您可以指定优化器特定的选项,例如学习率、权重衰减等。

Example:

optimizer=optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer=optim.Adam([var1, var2], lr=0.0001)

还支持指定每个参数选项。为此,不要传递 的可迭代对象,而是传递 的可迭代对象。它们中的每一个都将定义一个单独的参数组,并且应包含一个 密钥,其中包含属于它的参数列表。其他键应与优化器接受的关键字参数匹配,并将用作该组的优化选项。

Note

您仍然可以将选项作为关键字参数传递。它们将在未覆盖它们的组中用作默认值。当您只想更改单个选项,同时保持参数组之间的所有其他选项一致时,这非常有用。

例如,当想要指定每一层的学习率时,这非常有用:

optim.SGD([
                {'params': model.base.parameters()},
                {'params': model.classifier.parameters(), 'lr': 1e-3}
            ], lr=1e-2, momentum=0.9)

这意味着 的参数将使用 的默认学习率, 的参数将使用 的学习率,所有参数将使用 的动量。

所有优化器都实现更新参数的 方法。它可以通过两种方式使用:

这是大多数优化器支持的简化版本。一旦使用例如 计算梯度,就可以调用该函数。

Example:

for input, target in dataset:
    optimizer.zero_grad()
    output=model(input)
    loss=loss_fn(output, target)
    loss.backward()
    optimizer.step()

一些优化算法(例如共轭梯度和 LBFGS)需要多次重新评估函数,因此您必须传入一个闭包以允许它们重新计算您的模型。闭包应该清除梯度,计算损失并返回它。

Example:

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)
[source]

所有优化器的基类。

Warning

需要将参数指定为具有在运行之间保持一致的确定性顺序的集合。不满足这些属性的对象的示例是字典值的集合和迭代器。

Parameters
  • params (iterable) – 的可迭代。指定应优化哪些张量。
  • defaults ( Dict [ str , Any ]) – (dict):包含优化选项默认值的字典(当参数组未指定它们时使用)。

和 添加参数组。

加载优化器状态。

形式返回优化器的状态。

执行单个优化步骤(参数更新)。

重置所有优化的 的梯度。

实现 Adadelta 算法。

实现 Adagrad 算法。

实现 Adam 算法。

实现 AdamW 算法。

SparseAdam 实现了适合稀疏梯度的 Adam 算法的屏蔽版本。

实现 Adamax 算法(Adam 基于无穷范数的变体)。

实现平均随机梯度下降。

实现 L-BFGS 算法,深受 minFunc 启发。

实现 NAdam 算法。

实现RAdam算法。

实现 RMSprop 算法。

实现弹性反向传播算法。

实现随机梯度下降(可以选择使用动量)。

我们的许多算法都有针对性能、可读性和/或通用性进行优化的各种实现,因此如果用户没有指定特定的实现,我们会尝试默认为当前设备通常最快的实现。

我们有 3 个主要的实现类别:for-loop、foreach(多张量)和 fused。最直接的实现是对具有大量计算的参数进行 for 循环。For-循环通常比我们的 foreach 实现慢,后者将参数组合成多张量并一次运行大量计算,从而节省了许多连续的内核调用。我们的一些优化器具有更快的融合实现,它将大块计算融合到一个内核中。我们可以将 foreach 实现视为水平融合,将 fused 实现视为在此基础上垂直融合。

一般来说,3种实现的性能排序是 fused > foreach > for-loop。因此,在适用时,我们默认使用 foreach 而不是 for-loop。适用意味着 foreach 实现可用,用户未指定任何特定于实现的 kwargs(例如,融合、foreach、可微分),并且所有张量都是本机的且位于 CUDA 上。请注意,虽然 fused 应该比 foreach 更快,但实现较新,我们希望在到处切换开关之前给它们更多的烘烤时间。不过,欢迎您尝试一下!

下表显示了每种算法的可用和默认实现:

Algorithm

Default

Has foreach?

Has fused?

foreach

yes

no

foreach

yes

no

foreach

yes

yes

foreach

yes

yes

for-loop

no

no

foreach

yes

no

foreach

yes

no

for-loop

no

no

foreach

yes

no

foreach

yes

no

foreach

yes

no

foreach

yes

no

foreach

yes

no

提供了多种根据epoch数调整学习率的方法。 允许根据一些验证测量动态降低学习率。

学习率调度应在优化器更新后应用;例如,您应该这样编写代码:

Example:

optimizer=optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
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()

大多数学习率调度程序可以称为背靠背(也称为链接调度程序)。结果是每个调度器相继应用前一个调度器获得的学习率。

Example:

optimizer=optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
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 的方式改变了这种行为。如果您在优化器更新(调用 )之前使用学习率调度程序(调用 ),这将跳过学习率调度的第一个值。如果升级到 PyTorch 1.1.0后无法重现结果,请检查是否在错误的时间调用 。

将每个参数组的学习率设置为初始 lr 乘以给定函数。

将每个参数组的学习率乘以指定函数中给出的因子。

每step_size epoch将每个参数组的学习率衰减gamma。

一旦 epoch 的数量达到里程碑之一,就将每个参数组的学习率衰减 gamma。

将每个参数组的学习率衰减一个小的常数因子,直到 epoch 的数量达到预定义的里程碑:total_iters。

通过线性改变小的乘法因子来降低每个参数组的学习率,直到 epoch 的数量达到预定义的里程碑:total_iters。

每个时期将每个参数组的学习率衰减 gamma。

使用给定total_iters中的多项式函数衰减每个参数组的学习率。

使用余弦退火计划设置每个参数组的学习率,其中ηmax\eta_{max}设置为初始 lr 并且TcurT_{cur}是自 SGDR 上次重启以来的纪元数:

学习率调度程序的链列表。

接收预计在优化过程中按顺序调用的调度程序列表和里程碑点,提供精确的时间间隔以反映在给定时期应调用哪个调度程序。

当指标停止改进时降低学习率。

根据循环学习率策略(CLR)设置每个参数组的学习率。

按照1cycle学习率策略设置各参数组的学习率。

使用余弦退火计划设置每个参数组的学习率,其中ηmax\eta_{max}被设置为初始lr,TcurT_{cur}是自上次重新启动以来的纪元数,TiT_{i}是 SGDR 中两次热重启之间的纪元数:

实现随机权重平均 (SWA) 和指数移动平均 (EMA)。特别是, 类实现了 SWA 和 EMA 模型, 实现了 SWA 学习率调度程序, 是一个实用函数,用于在训练结束时更新 SWA/EMA 批量归一化统计数据。

SWA已在 Averaging Weights Leads to Wider Optima and Better Generalization 中被提出。

EMA 是一种众所周知的技术,可通过减少所需的权重更新次数来减少训练时间。它是 Polyak averaging 的变体,但在迭代中使用指数权重而不是相等权重。

类用于计算 SWA 或 EMA 模型的权重。

您可以通过运行以下命令创建 SWA 平均模型:

>>> averaged_model=AveragedModel(model)

EMA 模型是通过指定 参数构建的,如下所示:

>>> decay=0.999
>>> averaged_model=AveragedModel(model, multi_avg_fn=get_ema_multi_avg_fn(decay))

衰减是一个介于 0 和 1 之间的参数,用于控制平均参数衰减的速度。如果 未提供,则默认值为 0.999。

返回一个函数,该函数将以下 EMA 方程应用于权重:

Wt+1EMA=αWtEMA+(1α)WtmodelW^ extrm{EMA}_{t+1}=\alpha W^ extrm{EMA}_{t} + (1 - \alpha) W^ extrm{model}_t

其中 alpha 是 EMA 衰减。

这里模型 可以是任意 对象。 将跟踪 参数的运行平均值。要更新这些平均值,您应该在 之后使用 函数:

>>> averaged_model.update_parameters(model)

对于 SWA 和 EMA,此调用通常在优化器 之后立即完成。对于 SWA,通常在训练开始时跳过一些步骤。

默认情况下, 计算您提供的参数的运行相等平均值,但您也可以对 或 参数使用自定义平均函数:

  • 允许定义对每个参数元组(平均参数、模型参数)进行操作的函数,并应返回新的平均参数。
  • 允许同时定义作用于参数列表元组(平均参数列表、模型参数列表)的更有效操作,例如使用 函数。该函数必须就地更新平均参数。

在以下示例中, 使用 参数计算指数移动平均值:

>>> ema_avg=lambda averaged_model_parameter, model_parameter, num_averaged:\
>>>         0.9 * averaged_model_parameter + 0.1 * model_parameter
>>> ema_model=torch.optim.swa_utils.AveragedModel(model, avg_fn=ema_avg)

在以下示例中, 使用更高效的 参数计算指数移动平均值:

>>> ema_model=AveragedModel(model, multi_avg_fn=get_ema_multi_avg_fn(0.9))

通常,在 SWA 中,学习率被设置为一个较高的恒定值。 是一个学习率调度器,它将学习率退火到固定值,然后保持恒定。例如,以下代码创建一个调度程序,在每个参数组内的 5 个时期内将学习率从初始值线性退火到 0.05:

>>> swa_scheduler=torch.optim.swa_utils.SWALR(optimizer, \
>>>         anneal_strategy="linear", anneal_epochs=5, swa_lr=0.05)

您还可以通过设置 使用余弦退火到固定值而不是线性退火。

是一个实用函数,允许在训练结束时计算给定数据加载器 上的 SWA 模型的批标准化统计数据:

>>> torch.optim.swa_utils.update_bn(loader, swa_model)

将 应用于数据加载器中的每个元素,并计算模型中每个批量归一化层的激活统计数据。

Warning

假设数据加载器 中的每个批次都是一个张量或张量列表,其中第一个元素是网络 应应用的张量。如果您的数据加载器具有不同的结构,您可以通过对数据集的每个元素使用 进行前向传递来更新 的批量归一化统计信息。

在下面的示例中, 是累加权重平均值的 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()
>>>
>>> # 最后更新 swa_model 的 bn 统计信息
>>> torch.optim.swa_utils.update_bn(loader, swa_model)
>>> # 使用swa_model对测试数据进行预测
>>> preds=swa_model(test_input)

在下面的示例中, 是 EMA 模型,它累积权重的指数衰减平均值,衰减率为 0.999。我们对模型进行了总共 300 个 epoch 的训练,并立即开始收集 EMA 平均值。

>>> loader, optimizer, model, loss_fn=...
>>> ema_model=torch.optim.swa_utils.AveragedModel(model, \
>>>             multi_avg_fn=torch.optim.swa_utils.get_ema_multi_avg_fn(0.999))
>>>
>>> for epoch in range(300):
>>>       for input, target in loader:
>>>           optimizer.zero_grad()
>>>           loss_fn(model(input), target).backward()
>>>           optimizer.step()
>>>           ema_model.update_parameters(model)
>>>
>>> # 最后更新 ema_model 的 bn 统计信息
>>> torch.optim.swa_utils.update_bn(loader, ema_model)
>>> # 使用ema_model对测试数据进行预测
>>> preds=ema_model(test_input)

© 2019-2024 Torch Contributors
Licensed under the 3-clause BSD License.
https://pytorch.org/docs/2.1/optim.html

搜索

平台注册入口