动态调整Learning Rate:TORCH.OPTIM.LR_SCHEDULER

动态调整Learning Rate:TORCH.OPTIM.LR_SCHEDULER

[TOC]

pytorch提供的动态调整LR的策略。源码

在1.1.0之前,scheduler的更新要在optimizer之前,为了向后兼容,在1.1.0之后scheduler需要放在optimizer更新之后,如果依然放在optimizer更新之前,那么就会跳过设定的LR的第一个值,官方推荐如下。

scheduler = ...
for epoch in range(100):
    train(...)
    validate(...)
    scheduler.step()

1. BaseClass _LRScheduler

class _LRScheduler(object):
    def __init__(self, optimizer, last_epoch=-1): #初始化
    def state_dict(self): #返回self.__dict__
    def load_state_dict(self, state_dict): #加载self.__dict__,当模型需要resume的时候加载参数
    def get_lr(self): #接口,获得LR
    def step(self, epoch=None): #执行一次更新

def init(self, optimizer, last_epoch=-1) :初始化参数,last_epoch为-1的时候,初始化’initial_lr’参数为optimizer的lr参数。同时设定last_epoch为0,为optimizer.step函数添加装饰器。

def step(self, epoch=None) :LR更新,同时检查LRScheduler与optimizer的执行顺序。

self.base_lrs = list(map(lambda group: group[‘initial_lr’], optimizer.param_groups)) :通过初始化的LR设置基础的base_lr。

2. LambdaLR(optimizer,lr_lambda,last_epoch=-1)

通过设置函数更新LR,lr_lambda可以是一个函数或者函数列表,但是需要和optimizer的参数组数量相同,一个参数一个更新函数,但是有多个参数组的话可以只设定一个更新函数,所有参数组共用这个更新函数。注意LR更新函数是与Base_lr相乘。

# Assuming optimizer has two groups.
lambda1 = lambda epoch: epoch // 30
lambda2 = lambda epoch: 0.95 ** epoch
scheduler = LambdaLR(optimizer, lr_lambda=[lambda1, lambda2])
for epoch in range(100):
    train(...)
    validate(...)
    scheduler.step()

def get_lr(self): :

def get_lr(self):
        return [base_lr * lmbda(self.last_epoch)
                for lmbda, base_lr in zip(self.lr_lambdas, self.base_lrs)]

3. StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)

这个规定了一个特殊的LambdaLR方式,每step_size步之后衰减gamma。多个参数组共用Step_size和gamma,同时Step_size固定。

# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.05     if epoch < 30
# lr = 0.005    if 30 <= epoch < 60
# lr = 0.0005   if 60 <= epoch < 90
# ...
scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(100):
    train(...)
    validate(...)
    scheduler.step()

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

当模型的指标停止增加的时候,可以适当降低LR,在Patience时间内模型没有改进的时候,LR会降低。

  • mode:指指标的模型是’min‘还是’max‘,‘min’的时候不降低会减少LR,‘max’则相反。
  • factor:LR降低的速率,newLR=lr \star factor
  • patience:多少个epoch没有改善之后更新LR。
  • verbose:每次更新的时候是否打印信息。
  • threshold:判定为新的最优值的门槛,当新的最优值增加了threshold才会更新。
  • threshold_mode:‘rel’:best \star (1 + threshold)(’max‘), ‘abs‘:best + threshold(‘max’)。
  • cooldown:当LR降低之后经过多少个epoch恢复原始的操作,让模型冷静下来。
  • min_lr:LR最低可以降到多少,这个可以是list。
  • eps:更新的值变化小于这个数就可以不用管了。
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = ReduceLROnPlateau(optimizer, 'min')
for epoch in range(10):
    train(...)
    val_loss = validate(...)
    # Note that step should be called after validate()
    scheduler.step(val_loss) # val_loss is a float or zero_dim Tensor

5. CyclicLR(optimizer, base_lr, max_lr, step_size_up=2000, step_size_down=None, mode=’triangular’, gamma=1.0, scale_fn=None, scale_mode=’cycle’, cycle_momentum=True, base_momentum=0.8, max_momentum=0.9, last_epoch=-1)

上述的方法都是每次epoch之后更新,CyclicLR会在每个batch之后更新,更新频率更快。 Cyclical Learning Rates for Training Neural Networks

  • base_lr:LR下界。
  • max_lr:LR上界
  • step_size_up:每个循环分为两部分,一部分上升,一部分下降,构成一个三角形,这部分设置上升区间的迭代次数(注意是迭代,每一个batch算一次,而不是epoch)。
  • step_size_down:下降区间的迭代次数。
  • mode:三种模式,‘triangular’,‘triangular2’,‘exp_range‘。如果设定了scale_fn,那么这个参数就没用了。
  • gamma:‘exp_range‘模式下的更新常数。
  • scale_fn:自定义放缩函数,保证值为[0,1]。
  • scale_mode:‘cycle’,‘iterations’
  • cycle_momentum,base_momentum, max_omentum:LR更新的动量。
  • last_epoch:-1为初始化,用于Resume训练。
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = torch.optim.lr_scheduler.CyclicLR(optimizer, base_lr=0.01, max_lr=0.1)
data_loader = torch.utils.data.DataLoader(...)
for epoch in range(10):
    for batch in data_loader:
        train_batch(...)
        scheduler.step()

6. CosineAnnealingWarmRestarts(self, optimizer, T_0, T_mult=1, eta_min=0, last_epoch=-1)

Stochastic Gradient Descent with Warm Restarts一个周期性的余弦下降策略。每经过T_{0}次重启一下。

\eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})(1 + \cos(\frac{T_{cur}}{T_{i}}\pi))

  • T_0:重启周期
  • T_mult:T_0增加的因子,每次重启之后周期增加。
  • eta_min:LR的最小值。

Others

函数图像以及剩下的函数如下表:

Class NameParametersNoteFigure
LambdaLR
StepLR
MultiStepLRoptimizer, milestones, gamma=0.1, last_epoch=-1上述StepLR的拓展,区别为Step_size不固定,Milestones为递增的数列,每经过一个Milestone衰减一次。
ExponentialLRoptimizer, gamma, last_epoch=-1指数衰减,每Step一次LR衰减Gamma
CosineAnnealingLRoptimizer, T_max, eta_min=0, last_epoch=-1余弦退火算法衰减的简化版。 \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})(1 + \cos(\frac{T_{cur}}{T_{max}}\pi))\eta_{max}是初始化LR,T_{max}是指多少个epoch循环重启一次。
ReduceLROnPlateau
CyclicLR
CosineAnnealingWarmRestarts

https://www.jianshu.com/p/424d9a1e5ced

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论