1-Cycle 调度

本教程展示了如何在 PyTorch 中实现学习率和动量的 1Cycle 调度。

1-Cycle 调度

最近的研究表明,可以通过在训练期间使用循环和衰减调度调整关键超参数(如学习率和动量)来解决大批量大小训练的缓慢收敛问题。在 DeepSpeed 中,我们实现了一种名为 1-Cycle 的最先进调度,以帮助数据科学家有效地使用更大的批次大小在 PyTorch 中训练其模型。

先决条件

要将 1-Cycle 调度用于模型训练,您应满足以下两个要求

  1. 使用 入门 指南将 DeepSpeed 集成到您的训练脚本中。
  2. 将配置 1-Cycle 调度的参数添加到模型的参数中。我们将在下面定义 1-Cycle 参数。

概述

1-Cycle 调度分为两个阶段,一个循环阶段和一个衰减阶段,它们跨越训练数据的一次迭代。为了具体起见,我们将回顾 1-Cycle 学习率调度的工作原理。在循环阶段,学习率在一定数量的训练步骤内在最小值和最大值之间振荡。在衰减阶段,学习率从循环阶段的最小值开始衰减。下图说明了模型训练期间 1-Cycle 学习率调度的示例。

1cycle_lr

1-Cycle 参数

1-Cycle 调度由许多参数定义,这些参数允许用户探索不同的配置。文献建议同时调整学习率和动量,因为它们是相关的超参数。我们利用此建议通过将 1-Cycle 参数组织成两组来减少配置负担

  1. 用于配置循环和衰减阶段的全局参数。
  2. 用于配置学习率和动量的局部参数。

配置 1-Cycle 阶段的全局参数为

  1. cycle_first_step_size:完成循环阶段第一步的训练步骤数。
  2. cycle_first_stair_count:循环阶段第一步中的更新(或阶梯)次数。
  3. cycle_second_step_size:完成循环阶段第二步的训练步骤数。
  4. cycle_second_stair_count:循环阶段第二步中的更新(或阶梯)次数。
  5. post_cycle_decay_step_size:在衰减阶段衰减超参数的训练步骤间隔。

超参数的局部参数为

学习率:

  1. cycle_min_lr:循环阶段的最小学习率。
  2. cycle_max_lr:循环阶段的最大学习率。
  3. decay_lr_rate:衰减阶段学习率的衰减率。

虽然可以根据经验或专业知识选择合适的 cycle_min_lrcycle_max_lr 值,但我们建议使用 DeepSpeed 的 学习率范围测试 功能来配置它们。

动量

  1. cycle_min_mom:循环阶段的最小动量。
  2. cycle_max_mom:循环阶段的最大动量。
  3. decay_mom_rate:衰减阶段动量的衰减率。

所需的模型配置更改

为了说明在模型训练中使用 1-Cycle 调度所需的模型配置更改,我们将使用具有以下属性的调度

  1. 一个对称的循环阶段,其中循环的每一半跨越相同数量的训练步骤。对于此示例,学习率将需要 1000 个训练步骤才能从 0.0001 增加到 0.0010(10 倍),然后减少回 0.0001。动量将在类似的步骤数内相应地在 0.85 和 0.99 之间循环。
  2. 一个衰减阶段,其中学习率每 1000 步衰减 0.001,而动量不会衰减。

请注意,这些参数由 DeepSpeed 作为会话参数处理,因此应添加到模型配置的相应部分。

PyTorch 模型

PyTorch 1.0.1 及更高版本提供了一个用于实现超参数调度的功能,称为 学习率调度器。我们使用此功能实现了 1-Cycle 调度。您将添加一个类型为 “OneCycle” 的调度器条目,如下所示。

"scheduler": {
    "type": "OneCycle",
    "params": {
        "cycle_first_step_size": 1000,
        "cycle_first_stair_count": 500,
        "cycle_second_step_size": 1000,
        "cycle_second_stair_count": 500,
        "decay_step_size": 1000,
        "cycle_min_lr": 0.0001,
        "cycle_max_lr": 0.0010,
        "decay_lr_rate": 0.001,
        "cycle_min_mom": 0.85,
        "cycle_max_mom": 0.99,
        "decay_mom_rate": 0.0
    }
},

批次缩放示例

作为 1-Cycle 调度如何能够实现有效批次缩放的示例,我们简要分享了我们在 Microsoft 内部模型上的经验。在这种情况下,该模型针对单个 GPU 上的快速收敛(以数据样本为单位)进行了良好的调整,但在 8 个 GPU(8 倍批次大小)上训练时收敛到目标性能 (AUC) 速度较慢。下图显示了使用 8 个 GPU 对这些学习率调度进行模型收敛。

  1. 固定:使用 1-GPU 训练的最佳固定学习率。
  2. 线性缩放:使用是 固定 的 8 倍的固定学习率。
  3. 1Cycle:使用 1-Cycle 调度。

model_convergence

使用 1Cycle,模型比其他调度更快地收敛到目标 AUC。实际上,1Cycle 的收敛速度与最佳 1-GPU 训练一样快(未显示)。对于 固定,收敛速度大约慢 5 倍(需要 5 倍的数据样本)。使用 线性缩放,模型会发散,因为学习率过高。下图通过报告 8-GPU 训练期间的学习率值来说明这些调度。

lr_schedule

我们看到,1Cycle 的学习率始终大于 固定,并且短暂大于 线性缩放 以实现更快的收敛。此外,1Cycle 在训练后期降低学习率以避免模型发散,这与 线性缩放 相反。总之,通过配置适当的 1-Cycle 调度,我们能够将此模型的训练批次大小有效地扩展 8 倍,而不会损失收敛速度。

更新: