Learning Rate Scheduler(一)

torch.optim.lr_scheduler 提供了动态调整学习率的方法。在使用的时, Learning Rate Scheduler 一般在优化器的更新参数之后调用。另外,我们也可以在程序中使用多个 scheduler 来调整学习率,如下代码所示:

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()

接下来,介绍 PyTorch 官网提供的几种学习率优化策略。主要包含以下几种:

  1. lr_scheduler.LambdaLR
  2. lr_scheduler.MultiplicativeLR
  3. lr_scheduler.StepLR
  4. lr_scheduler.MultiStepLR
  5. lr_scheduler.ConstantLR
  6. lr_scheduler.LinearLR
  7. lr_scheduler.ExponentialLR

1. LambdaLR

LambdaLR 每个 step 后,lr 调整为上一个时刻的 lr_lambda,例如:lr_lambda=0.9,则 lambda step: 0.9 ** step

LambdaLR(optimizer, lr_lambda, last_epoch=- 1, verbose=False)

示例代码:

import torch
from torch.optim.lr_scheduler import LambdaLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.Adam(parameter, lr=0.1)
    # 调度器
    scheduler = LambdaLR(optimizer=optimizer,
                         lr_lambda=lambda step: 0.9 ** step)

    learning_rates = [0.1]
    for _ in range(10):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        learning_rates.append(scheduler.get_last_lr()[0])
        print('%.5f' % scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(11), learning_rates, 'ro-')
    plt.title('LambdaLR')
    plt.grid()
    plt.show()

2. MultiplicativeLR

MultiplicativeLR 与 LambdaLR 区别如下:

LambdaLR 是由初始学习率乘以 lambda 函数的返回值,而 MultiplicativeLR 则是使用上一个学习率乘以 lambda 函数的返回值。

MultiplicativeLR(optimizer, lr_lambda, last_epoch=- 1, verbose=False)

示例代码:

import torch
from torch.optim.lr_scheduler import MultiplicativeLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.Adam(parameter, lr=0.1)
    # 调度器
    scheduler = MultiplicativeLR(optimizer=optimizer,
                                 lr_lambda=lambda step: 0.9)

    learning_rates = [0.1]
    for _ in range(10):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        learning_rates.append(scheduler.get_last_lr()[0])
        print('%.5f' % scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(11), learning_rates, 'ro-')
    plt.title('MultiplicativeLR')
    plt.grid()
    plt.show()

3. StepLR

StepLR 可以实现迭代固定多少 epoch 时,对学习率进行衰减。

StepLR(optimizer, step_size, gamma=0.1, last_epoch=- 1, verbose=False)
  1. gamma 就是衰减的系数。假设:gamma=0.1,则学习率衰减为上一个学习率的 0.1
  2. step_size 表示经过多少个 step 对学习率进行一次衰减

比如:我们每 5 个 epoch,就把学习修改为上一个学习率的 0.5,如下代码所示:

import torch
from torch.optim.lr_scheduler import StepLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.SGD(parameter, lr=0.1)
    # 调度器
    scheduler = StepLR(optimizer=optimizer, step_size=5, gamma=0.5)

    learning_rates = [0.1]
    for _ in range(100):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        print('%.5f' % scheduler.get_last_lr()[0])
        learning_rates.append(scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(101), learning_rates)
    plt.title('StepLR')
    plt.grid()
    plt.show()

4. MultiStepLR

MultiStepLR 和 StepLR 的区别是,前者可以自定义多个 step 点来进行学习率衰减,而后者只能根据固定的间隔来衰减学习率。

MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=- 1, verbose=False)

参数中 milestones 是列表类型,用来设置需要进行学习率衰减的 epoch 点。例如,我们总共进行 100 epoch,设置 [10, 40, 50, 80] 这 4 个 epoch 点来衰减学习率。

import torch
from torch.optim.lr_scheduler import MultiStepLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.SGD(parameter, lr=0.1)
    # 调度器
    scheduler = MultiStepLR(optimizer=optimizer, gamma=0.5, milestones=[10, 40, 50, 80])

    learning_rates = [0.1]
    for _ in range(100):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        print('%.5f' % scheduler.get_last_lr()[0])
        learning_rates.append(scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(101), learning_rates)
    plt.title('MultiStepLR')
    plt.grid()
    plt.show()

5. ConstantLR

我们希望训练开始时,使用较小的学习率训练多个 step,然后再使用大的学习率继续训练。在这里,小学习率和大学习率都是固定的。ConstantLR 可以做这样的工作。

ConstantLR(optimizer, factor=0.33, total_iters=5, last_epoch=- 1, verbose=False)

factor 用来指定小学习率,total_iters 指定使用该小学习率训练多少 step,在 total_iters 轮次结束之后,学习率会回到我们在 optimizer 里设置的初始学习率。

import torch
from torch.optim.lr_scheduler import ConstantLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.Adam(parameter, lr=1)
    # 调度器
    scheduler = ConstantLR(optimizer=optimizer, factor=0.1, total_iters=5)

    learning_rates = [0.1]
    for _ in range(10):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        learning_rates.append(scheduler.get_last_lr()[0])
        print('%.5f' % scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(11), learning_rates, 'ro-')
    plt.title('ConstantLR')
    plt.grid()
    plt.show()

6. LinearLR

LinearLR(optimizer, start_factor=0.33, end_factor=1.0, total_iters=5, last_epoch=- 1, verbose=False)

学习率经过 total_iters 个 step 从 lr * start_factorlr * end_factor,然后恒定保持不变, lr 为优化器指定。

import torch
from torch.optim.lr_scheduler import LinearLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    model_parameters = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.SGD(model_parameters, lr=0.1)
    # 调度器
    scheduler = LinearLR(optimizer=optimizer, start_factor=0.001, end_factor=0.10, total_iters=50)

    learning_rates = []
    for _ in range(100):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        print('%.5f' % scheduler.get_last_lr()[0])
        learning_rates.append(scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(100), learning_rates)
    plt.title('LinearLR')
    plt.grid()
    plt.show()

7. ExponentialLR

ExponentialLR 表示学习率每个 epoch 是 epoch-1 学习率的 0.9(gamma=0.9)。

ExponentialLR(optimizer, gamma, last_epoch=- 1, verbose=False)
import torch
from torch.optim.lr_scheduler import ExponentialLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 模型参数
    model_parameters = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
    # 优化器
    optimizer = optim.SGD(model_parameters, lr=0.1)
    # 调度器
    scheduler = ExponentialLR(optimizer=optimizer, gamma=0.9)

    learning_rates = []
    for _ in range(100):
        # 先优化器更新
        optimizer.step()
        # 再调度器更新
        scheduler.step()
        # 存储学习率
        print('%.5f' % scheduler.get_last_lr()[0])
        learning_rates.append(scheduler.get_last_lr()[0])

    # 绘制学习率变化
    plt.plot(range(100), learning_rates)
    plt.title('ExponentialLR')
    plt.grid()
    plt.show()

输出结果:

0.09000  # 0.1000 * 0.9
0.08100  # 0.9000 * 0.9 
0.07290  # 0.0810 * 0.9
0.06561  # 0.7290 * 0.9
# 后面以此类推

未经允许不得转载:一亩三分地 » Learning Rate Scheduler(一)