Press "Enter" to skip to content

深度学习训练过程中的学习率衰减策略及pytorch实现

学习率是深度学习中的一个重要超参数,选择合适的学习率能够帮助模型更好地收敛。

 

本文主要介绍深度学习训练过程中的6种学习率衰减策略以及相应的Pytorch实现。

 

1. StepLR

按固定的训练epoch数进行学习率衰减。
举例说明:

# lr = 0.05 if epoch < 30

 

# lr = 0.005 if 30 <= epoch < 60

 

# lr = 0.0005 if 60 <= epoch < 90

 

在上述例子中,每30个epochs衰减十倍学习率。

计算公式和pytorch计算代码如下:

 

def _get_closed_form_lr(self):
    return [base_lr * self.gamma ** (self.last_epoch // self.step_size)
            for base_lr in self.base_lrs]

pytorch调用及相关参数:

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

 

optimizer:表示使用的优化器;

 

step_size:表示学习率调整步长;

 

gamma:表示学习率衰减乘法因子,默认:0.1;

 

last_epoch:表示上一个epoch数,默认:-1,此时学习率的值为初始学习率;

 

verbose:表示是否每次更新都输出一次学习率的值,默认:False。

代码示例及结果展示:

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

 

设置10个epoch时,输出训练过程中的学习率如下:

 

 

2. MultiStepLR

当epoch数达到固定数值进行学习率衰减。
举例说明:

# milestones = [ 30 , 80 ]

 

# lr = 0.05 if epoch < 30

 

# lr = 0.005 if 30 <= epoch < 80

 

# lr = 0.0005 if epoch >= 80

 

在上述例子中,当epoch达到milestones中的数值时进行学习率衰减。

计算公式和pytorch计算代码如下:

 

其中bisect_right函数表示epoch数插入milestones中列表的位置,

 

例如:milstones=[2,5,8]

 

last_epoch==1→bisect_right(milestones,last_epoch)=0;

 

last_epoch==3→bisect_right(milestones,last_epoch)=1;

 

last_epoch==6→bisect_right(milestones,last_epoch)=2;

 

def _get_closed_form_lr(self):
        milestones = list(sorted(self.milestones.elements()))
        return [base_lr * self.gamma ** bisect_right(milestones, self.last_epoch)
                for base_lr in self.base_lrs]

pytorch调用及相关参数:

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

 

milestones:一个关于epoch索引的列表,当epoch值达到列表中的数值时进行学习率衰减。

 

其他参数相同。

代码示例及结果展示:

lr_scheduler=torch.optim.lr_scheduler.MultiStepLR(optimizer,milestones=[2,5,8],gamma=0.1,last_epoch=-1)

 

 

3. ExponentialLR

根据当前epoch进行学习率衰减

计算公式和pytorch计算代码如下:

 

def _get_closed_form_lr(self):
      return [base_lr * self.gamma ** self.last_epoch
              for base_lr in self.base_lrs]

pytorch调用及相关参数:

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

代码示例及结果展示:

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

 


4. linearLR

在epoch数达到total_iters数值之前,使用线性改变乘法因子衰减学习率。

计算公式和pytorch计算代码如下:

 

def _get_closed_form_lr(self):
        return [base_lr * (self.start_factor +
                (self.end_factor - self.start_factor) * min(self.total_iters, self.last_epoch) / self.total_iters)
                for base_lr in self.base_lrs]

pytorch调用及相关参数:

torch.optim.lr_scheduler.LinearLR(optimizer, start_factor=0.3333333333333333, end_factor=1.0, total_iters=5, last_epoch=- 1, verbose=False)

 

start_factor: 在第一个epoch中乘以base_lr的数值,默认1/3;
end_factor:在线性变化过程结束时乘以base_lr的数值,默认:1;
total_iters:乘法因子达到1的迭代次数,默认:5。

举例说明:

lr_scheduler = LinearLR(optimizer, start_factor=0.5, total_iters=4)
base_lr=0.05
# epoch == 0→lr = base_lr * start_factor = 0.05 * 0.5=0.025;
# epoch == 1→lr = 0.05 * (0.5 + 0.5 * 0.25) = 0.3125;
......
# epoch ≥ 4→lr = base_lr * end_factor = 0.05(当epoch数等于total_iters时,min(self.total_iters, self.last_epoch) / self.total_iters = 1)

 

5. ConstantLR

在epoch数达到total_iters数值之前,使用常数因子衰减学习率。
计算公式和pytorch计算代码如下:

 

    def _get_closed_form_lr(self):
        return [base_lr * (self.factor + (self.last_epoch >= self.total_iters) * (1 - self.factor))
                for base_lr in self.base_lrs]

pytorch调用及相关参数:

torch.optim.lr_scheduler.ConstantLR(optimizer, factor=0.3333333333333333, total_iters=5, last_epoch=- 1, verbose=False)

 

factor:在epoch达到total_iters之前,学习率乘以的常数因子,默认1/3;

 

total_iters:衰减学习率的步数。

举例说明:

lr_scheduler = ConstantLR(self.opt, factor=0.5, total_iters=4)

 

base_lr = 0.05

 

# epoch == 0 → lr = base_lr * (factor + 0 * (1-factor)) = 0.05 *  0.5 = 0.025

 

……

 

# epoch == 4 → lr = base_lr * (factor + 1 – factor) = 0.05

 

6. LambdaLR

使用lambda定义的函数衰减学习率。
计算公式和pytorch计算代码如下:

 

    def get_lr(self):
        if not self._get_lr_called_within_step:
            warnings.warn("To get the last learning rate computed by the scheduler, "
                          "please use `get_last_lr()`.")
        return [base_lr * lmbda(self.last_epoch)
                for lmbda, base_lr in zip(self.lr_lambdas, self.base_lrs)]

pytorch调用及相关参数:

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

 

lr_lambda:当给定epoch数,计算乘法因子的函数(可以自己定义)

代码示例及结果展示:

lr_scheduler=torch.optim.lr_scheduler.LambdaLR(optimizer,lr_lambda=lambda epoch:epoch/30 )

 

 

7. MultiplicativeLR

同样是使用了与epoch有关的lambda函数,与LambdaLR不同的地方在于,它是对old_lr更新。
计算公式和pytorch计算代码如下:

 

def get_lr(self):
        if not self._get_lr_called_within_step:
            warnings.warn("To get the last learning rate computed by the scheduler, "
                          "please use `get_last_lr()`.", UserWarning)
        if self.last_epoch > 0:
            return [group['lr'] * lmbda(self.last_epoch)
                    for lmbda, group in zip(self.lr_lambdas, self.optimizer.param_groups)]
        else:
            return [group['lr'] for group in self.optimizer.param_groups]

pytorch调用及相关参数:

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

 

8.CosineAnnealingLR

模拟余弦退火曲线调整学习率
计算公式和pytorch计算代码如下:

 

def _get_closed_form_lr(self):
     return [self.eta_min + (base_lr - self.eta_min) *
           (1 + math.cos(math.pi * self.last_epoch / self.T_max)) / 2
                for base_lr in self.base_lrs]

pytorch调用及相关参数:

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

 

T_max:最大迭代次数,一次学习率周期的迭代次数。

 

eta_min:最小学习率,默认:0。

代码示例及结果展示:

lr_scheduler=torch.optim.lr_scheduler.CosineAnnealingLR(optimizer,T_max=3,eta_min=0)

 

base_lr=0.01

 

 

当epoch是T_max的奇数倍时,学习率会下降到最小值eta_min。

 

9. ChainedScheduler

可以调用其他学习率调整策略。
pytorch调用及相关参数:

torch.optim.lr_scheduler.ChainedScheduler(schedulers)

 

schedules:设置的其他学习率调整策略,可以是一个包含多个学习率调整策略的列表 。

代码示例及结果:

scheduler1 = ConstantLR(self.opt, factor=0.1, total_iters=2)
scheduler2 = ExponentialLR(self.opt, gamma=0.9)
lr_scheduler = ChainedScheduler([scheduler1, scheduler2])

 

schedules里的学习率调整策略同时使用

 

base_lr = 1

 

# lr = 0.09 if epoch == 0 (先使用scheduler2策略得到lr = 0.9;再使用scheduler1策略得到最终new_lr = 0.09)

 

# lr = 0.081 if epoch == 1

 

# lr = 0.729 if epoch == 2

 

# lr = 0.6561 if epoch == 3

 

# lr = 0.59049 if epoch >= 4

 

10.SequentialLR

与ChainedScheduler在每一个epoch中同时调用schedules中的学习率策略不同的是,SequentialLR针对epoch按顺序调用schedules中的学习率策略。
pytorch调用及相关参数:

torch.optim.lr_scheduler.SequentialLR(optimizer, schedulers, milestones, last_epoch=- 1, verbose=False)

代码示例及结果:

scheduler1 = ConstantLR(self.opt, factor=0.1, total_iters=2)
scheduler2 = ExponentialLR(self.opt, gamma=0.9)
lr_scheduler = SequentialLR(optimizer, schedulers=[scheduler1, scheduler2], milestones=[2])

 

base_lr = 1

 

# lr = 0.1 if epoch == 0

 

# lr = 0.1 if epoch == 1

 

# lr = 0.9 if epoch == 2

 

# lr = 0.81 if epoch == 3

 

# lr = 0.729 if epoch == 4

 

epoch<milestones,调用scheduler1学习率调整策略,epoch≥milestones,调用scheduler2学习率调整策略。

 

11.ReduceLROnPlateau

当训练指标不再改进时,调整学习率。
pytorch调用及相关参数:

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两种模式,在 min 模式下,当指标的数量停止减少时(如loss),学习率将减少; 在max模式下,当指标的数量停止增加时(如accuracy),学习率将减少,默认值:min;

 

factor:学习率减少的倍数,new_lr = old_lr * factor,默认:0.1;

 

patience:指标没有提升的epoch数,之后降低学习率。例如,patience = 2,会忽略前 2 个没有改善的 epoch,并且只有在第 3 个 epoch 之后指标仍然没有改善的情况下降低 学习率。 默认值:10。

 

threshold:衡量新的最佳阈值,只关注重大变化。 默认值:1e-4。

 

threshold_mode:有rel、abs两种模式,

 

cooldown:在 学习率减少后恢复正常操作之前要等待的 epoch 数。 默认值:0。

 

min_lr:标量或标量列表。学习率的下限。 默认值:0。

 

eps:应用于 学习率的最小衰减。 如果新旧 学习率之间的差异小于 eps,则忽略更新。 默认值:1e-8。

代码示例及结果:

lr_scheduler=torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer,mode='min',patience=2,cooldown=2)

 

 

第一个epoch是初始学习率;

 

设置patience = 2,即指标在经历3个epoch后仍然没有提升,衰减学习率,new_lr = old_lr * factor(0.1),如图中第4个epoch时开始衰减学习率;

 

设置cooldown = 2,即衰减学习率后有2个epoch的cooldown时期(5、6epoch),在cooldown时期不进行patience阶段的epoch计数;

 

cooldown时期结束恢复patience阶段epoch计数(图中从第7个epoch开始计数,在第10个epoch学习率衰减)。

 

12.CyclicLR

根据循环学习策略设置学习率。(每训练一个batch,更新一次学习率)
在《 Cyclical Learning Rates for Training Neural Networks》这篇文章中有详细描述。
pytorch调用及相关参数:

torch.optim.lr_scheduler.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, verbose=False)

 

base_lr:初始学习率,循环中的学习率下边界;

 

max_lr:每个参数组在循环中的上层学习率边界。从功能上讲,它定义了周期幅度 (max_lr – base_lr)。任何周期的 lr 是 base_lr 和一些幅度缩放的总和;因此 max_lr 实际上可能无法达到,具体取决于缩放函数。

 

step_size_up:在一个周期增加的一半中训练迭代的次数。默认值:2000;

 

step_size_down:循环减半中的训练迭代次数。如果 step_size_down 为 None,则设置为 step_size_up。默认值:None;

 

mode:包含三种{triangular, triangular2, exp_range} ,如果 scale_fn 不是 None,则忽略此参数。默认值:“triangular”;

 

gamma:‘exp_range’ 缩放函数中的常数:gamma**(cycle iterations)默认值:1.0;

 

scale_fn:由单个参数 lambda 函数定义的自定义缩放策略,其中 0 <= scale_fn(x) <= 1 for all x >= 0。如果指定,则忽略“mode”。默认值:None;

 

scale_mode:{‘cycle’, ‘iterations’}。定义是否在cycle number或 cycle iterations (training iterations since start of cycle) 上评估 scale_fn。默认值:cycle;

 

cycle_momentum:如果为真,则动量与“base_momentum”和“max_momentum”之间的学习率成反比。默认值:True;

 

base_momentum: 循环中的动量下边界,默认值:0.8;

 

max_monmentum:循环中的动量上边界,默认值:0.9;

官方代码及示例:

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

 

13.OneCycleLR

根据循环学习策略设置学习率。(每训练一个batch,更新一次学习率)
相关文章《Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates》
pytorch调用及相关参数:

torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr, total_steps=None, epochs=None, steps_per_epoch=None, pct_start=0.3, anneal_strategy='cos', cycle_momentum=True, base_momentum=0.85, max_momentum=0.95, div_factor=25.0, final_div_factor=10000.0, three_phase=False, last_epoch=- 1, verbose=False)

 

max_lr:在循环中的上层学习率边界;

 

total_steps:循环总步数。如果此处未提供值,则必须通过提供 epochs 和 steps_per_epoch 的值来推断。默认值:None;

 

epochs:训练的epochs;

 

steps_per_epoch:每个 epoch 训练的步数;

 

pct_start:提高学习率所花费的周期百分比(in number of steps)。默认值:0.3;

 

anneal_strategy:{‘cos’, ‘linear’} 指定退火策略:“cos”表示余弦退火,“linear”表示线性退火。默认值:’cos’;

 

div_factor:通过 initial_lr = max_lr/div_factor 确定初始学习率 默认值:25;

 

final_div_factor:通过 min_lr = initial_lr/final_div_factor 确定最小学习率 默认值:1e4;

 

three_phase:如果为 True,则使用计划的第三阶段根据“final_div_factor”消除学习率,而不是修改第二阶段(前两个阶段将关于“pct_start”指示的步骤对称)。

官方代码及示例:

 data_loader = torch.utils.data.DataLoader(...)
     optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
     scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=0.01, steps_per_epoch=len(data_loader), epochs=10)
     for epoch in range(10):
         for batch in data_loader:
            train_batch(...)
            scheduler.step()

 

14.CosineAnnealingWarmRestarts

和余弦退火类似,多了warmrestart操作。
pytorch调用及相关参数:

torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0, T_mult=1, eta_min=0, last_epoch=- 1, verbose=False)

 

T_0:第一次restart的迭代次数;

 

T_mult:在一次restar后,因子增加:math:`T_{i};

 

eta_min:最小学习率,默认值:0。

官方代码及示例 :

 scheduler = CosineAnnealingWarmRestarts(optimizer, T_0, T_mult)
                 iters = len(dataloader)
                 for epoch in range(20):
                     for i, sample in enumerate(dataloader):
                         inputs, labels = sample['inputs'], sample['labels']
                         optimizer.zero_grad()
                         outputs = net(inputs)
                         loss = criterion(outputs, labels)
                         loss.backward()
                         optimizer.step()
                         scheduler.step(epoch + i / iters)

 

参考及引用:

 

1.https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate

 

2.https://zhuanlan.zhihu.com/p/352744991

 

3.https://blog.csdn.net/qyhaill/article/details/103043637

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注