动态调整Learning Rate:TORCH.OPTIM.LR_SCHEDULER
pytorch提供的动态调整LR的策略。
GitHub源码
在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
通过设置函数更新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
这个规定了一个特殊的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
当模型的指标停止增加的时候,可以适当降低LR,在Patience时间内模型没有改进的时候,LR会降低。
- mode:指指标的模型是’min‘还是’max‘,‘min’的时候不降低会减少LR,‘max’则相反。
- factor:LR降低的速率,。
- patience:多少个epoch没有改善之后更新LR。
- verbose:每次更新的时候是否打印信息。
- threshold:判定为新的最优值的门槛,当新的最优值增加了threshold才会更新。
- threshold_mode:‘rel’:(’max‘), 'abs‘:(‘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
上述的方法都是每次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
一个周期性的余弦下降策略。每经过次重启一下。
Stochastic Gradient Descent with Warm Restarts
- T_0:重启周期
- T_mult:T_0增加的因子,每次重启之后周期增加。
- eta_min:LR的最小值。
Others
函数图像以及剩下的函数如下表:
Class Name | Parameters | Note | Figure |
---|---|---|---|
LambdaLR | optimizer,lr_lambda,last_epoch=-1 | ||
StepLR | optimizer, step_size, gamma=0.1, last_epoch=-1 | ||
MultiStepLR | optimizer, milestones, gamma=0.1, last_epoch=-1 | 上述StepLR的拓展,区别为Step_size不固定,Milestones为递增的数列,每经过一个Milestone衰减一次。 | |
ExponentialLR | optimizer, gamma, last_epoch=-1 | 指数衰减,每Step一次LR衰减Gamma | |
CosineAnnealingLR | optimizer, T_max, eta_min=0, last_epoch=-1 | 余弦退火算法衰减的简化版。 ,是初始化LR,是指多少个epoch循环重启一次。 | |
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 | ||
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 | ||
CosineAnnealingWarmRestarts | optimizer, T_0, T_mult=1, eta_min=0, last_epoch=-1 |