【PyTorch】10:学习率调整策略


1. 为什么要调整学习率?

梯度更新公式:
w i + 1 = w i − L R ∗ g ( w i ) w_{i+1} = w_i - LR * g(w_i) wi+1=wiLRg(wi)

随着时间推移,调整学习率与打高尔夫球时击球的力度类似。在一开始,我们希望用较大的击球力度将球击打到离洞口比较近的范围内,然后减小击球力度,使球逐渐靠近洞口,最后将球打进。如果击球力度不减,则球会在离洞口一定范围内震荡,这与loss曲线类似。下图对比了在类似超参数设置条件下的几种不同优化算法。
在这里插入图片描述

图自:LINK



2. PyTorch 学习率调整策略

2.1 手动调节学习率

PyTorch支持在迭代过程中修改学习率,最简单的方法是手动修改学习率。优化器 optimizer 通过 param_group 提供对不同层使用不同的优化方法,其中每组参数保存了各自的学习率、动量等,如果只设置了一种优化方法,修改其第 0 组的 lr 即可,例如设置学习率加倍:

optimizer.param_groups[0]['lr'] *=2 

在使用工具调整学习率的过程中,也可检测学习率的变化:

print(optimizer.state_dict()['param_groups'][0]['lr'])

2.2 库函数调节学习率

class _LRScheduler 基类,官方文档:LINK

主要属性:

  • optimizer:关联的优化器,用于调整学习率;
  • last_epoch:记录 epoch 数,学习率的调整以epoch为周期;
  • base_lrs:记录初始学习率。

主要方法:

  • step():更新下一个epoch的学习率;
  • get_lr():虚函数,计算下一个epoch的学习率。

2.3 torch.optim.lr_scheduler.StepLR

torch.optim.lr_scheduler.StepLR(optimizer, 
                                step_size, 
                                gamma=0.1, 
                                last_epoch=-1, 
                                verbose=False)

功能:等间隔调整学习率,调整方式:lr = lr * gamma

主要参数:

  • step_size:调整间隔数;
  • gamma:调整系数。

2.4 torch.optim.lr_scheduler.MultiStepLR

torch.optim.lr_scheduler.MultiStepLR(optimizer, 
                                     milestones, 
                                     gamma=0.1, 
                                     last_epoch=-1, 
                                     verbose=False)

功能:按给定间隔调整学习率,调整方式:lr = lr * gamma

主要参数:

  • milestones :设定需要调整的时刻数,以列表形式传入;
  • gamma :调整系数。

2.5 torch.optim.lr_scheduler.ExponentialLR

torch.optim.lr_scheduler.ExponentialLR(optimizer, 
                                       gamma, 
                                       last_epoch=-1, 
                                       verbose=False)

功能:按指数衰减调整学习率,调整方式:lr = lr * gamma ** epoch

主要参数:

  • gamma :指数的底,通常设置为接近于1的数,比如0.95;
    在这里插入图片描述

2.6 torch.optim.lr_scheduler.CosineAnnealingLR

torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, 
                                           T_max, 
                                           eta_min=0, 
                                           last_epoch=-1, 
                                           verbose=False)

功能:余弦周期调整学习率。调整方式:

η t = η m i n + 1 2 ( η m a x − η m i n ) ( 1 + cos ⁡ ( T c u r T m a x π ) ) \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})\left(1 + \cos\left(\frac{T_{cur}}{T_{max}}\pi\right)\right) ηt=ηmin+21(ηmaxηmin)(1+cos(TmaxTcurπ))

主要参数:

  • T_max :下降周期;
  • eta_min :学习率下限。

在这里插入图片描述


2.7 torch.optim.lr_scheduler.ReduceLROnPlateau

torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', 
                                           factor=0.1, 
                                           patience=10, 
                                           threshold=0.0001, 
                                           threshold_mode='rel', 
                                           cooldown=0, 
                                           min_lr=0, 
                                           eps=1e-08, 
                                           verbose=False)

功能:监控指标,当指标不再变化则调整。

主要参数:

  • mode:min/max 两种模式;
  • factor:调整系数;
  • patience:“耐心”,接受几次不变化;
  • cooldown:“冷却时间”,停止监控一段时间;
  • verbose:是否打印日志;
  • min_lr:学习率下限;
  • eps:学习率衰减最小值。

2.8 torch.optim.lr_scheduler.LambdaLR

torch.optim.lr_scheduler.LambdaLR(optimizer, 
                                  lr_lambda, 
                                  last_epoch=-1, 
                                  verbose=False)

功能:自定义调整策略,针对不同的参数组设置不同的调整策略。

主要参数:

  • lr_lambda:function or list。

实例:

import torch
import matplotlib.pyplot as plt

torch.manual_seed(1)

LR = 0.1
iteration = 10
max_epoch = 200

lr_init = 0.1

weights_1 = torch.randn((6, 3, 5, 5))
weights_2 = torch.ones((5, 5))

optimizer = torch.optim.SGD([
    {'params': [weights_1]},
    {'params': [weights_2]}], lr=lr_init)

lambda1 = lambda epoch: 0.1 ** (epoch // 20)
lambda2 = lambda epoch: 0.95 ** epoch

scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=[lambda1, lambda2])

lr_list, epoch_list = list(), list()
for epoch in range(max_epoch):
    for i in range(iteration):

        # train(...)

        optimizer.step()
        optimizer.zero_grad()

    scheduler.step()

    lr_list.append(scheduler.get_lr())
    epoch_list.append(epoch)

    print('epoch:{:5d}, lr:{}'.format(epoch, scheduler.get_lr()))

plt.plot(epoch_list, [i[0] for i in lr_list], label="lambda 1")
plt.plot(epoch_list, [i[1] for i in lr_list], label="lambda 2")
plt.xlabel("Epoch")
plt.ylabel("Learning Rate")
plt.title("LambdaLR")
plt.legend()
plt.show()

在这里插入图片描述


3. 总结

  1. 有序调整: Step、 MultiStep、 Exponential 和 CosineAnnealing;
  2. 自适应调整: ReduceLROnPleateau;
  3. 自定义调整: Lambda。

学习率初始化:

  • 设置较小数: 0.01 、 0.001 、 0.0001
  • 搜索最大学习率: 《Cyclical Learning Rates for Training NeuralNetworks》,其核心思想是学习率从较小值变化到较大值的过程中,观察某一指标(比如准确率)的变化情况,将该指标出现下降趋势时的学习率作为初始学习率。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页