学习率调整策略,学习率预热(warmup)和学习率衰减(Learning Rate Decay)

学习率策略:学习率预热(warmup)和学习率衰减(Learning Rate Decay)

学习率的 warm-up 是指在训练的初期,逐渐增加学习率的过程,以帮助模型更好地收敛到最优解。以下是一种常用的学习率 warm-up 设置方法:

  1. 初始学习率设置:选择一个较小的初始学习率,通常为你预设的基础学习率的一小部分(如 0.1 或 0.01)。
  2. Warm-up 阶段长度:决定需要进行 warm-up 的迭代次数或训练轮数。这个值可以根据数据集和模型复杂度进行调节,通常在几百到几千个迭代之间。
  3. Warm-up 学习率计算方式:使用一个线性函数来逐步增加学习率,使其从初始学习率线性地增加到你预设的基础学习率。例如,在第一个迭代中,学习率可能只是初始学习率的十分之一;在第二个迭代中,学习率可能是初始学习率的五分之一,依此类推,直到达到基础学习率。
  4. 完成 warm-up 后:当达到预设的 warm-up 迭代次数后,可以将学习率恢复到基础学习率,并按照原始的训练策略进行优化。

通过这样的学习率预热机制,可以使模型在训练初期更好地适应数据,提高训练的稳定性和性能。根据实际需求,可以根据预热阶段的迭代次数、初始学习率和最终学习率来调整预热效果。

需要注意的是,学习率 warm-up 的设置可以根据实际情况进行调整。如果初始学习率过大或 warm-up 过短,可能会导致模型训练不稳定或出现梯度爆炸的问题;而如果初始学习率过小或 warm-up 过长,可能会导致模型训练速度过慢。因此,建议根据具体任务和模型特点进行实验和调优,找到适合的学习率 warm-up 设置。

pytorch代码示例

学习率预热是在训练开始阶段逐渐增加学习率,以帮助模型更好地收敛。预热阶段通常在训练的前几个epoch中进行,随后再根据预定义的衰减策略进行学习率衰减。

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义优化器和学习率调度器
model = YourModel()
optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.1)

# 学习率预热参数
warmup_epochs = 5
warmup_lr_init = 0.01
warmup_lr_end = 0.1

# 在训练循环中更新学习率
for epoch in range(warmup_epochs):
    # 计算当前预热阶段的学习率
    warmup_lr = warmup_lr_init + (warmup_lr_end - warmup_lr_init) * epoch / warmup_epochs
    
    # 设置当前阶段的学习率
    for param_group in optimizer.param_groups:
        param_group['lr'] = warmup_lr
    
    # 训练模型的代码
    
    # 更新学习率调度器
    scheduler.step()

# 正常训练阶段,学习率衰减
for epoch in range(warmup_epochs, num_epochs):
    # 训练模型的代码
    
    # 更新学习率调度器
    scheduler.step()
  1. 在上述示例中,我们首先定义了一个模型和一个优化器,然后创建了一个学习率调度器(这里使用了StepLR作为示例)。接下来,我们设置了学习率预热的参数,包括预热阶段的迭代次数(warmup_epochs)以及初始学习率(warmup_lr_init)和最终学习率(warmup_lr_end)。
  2. 在训练循环的前warmup_epochs个迭代中,我们逐渐增加学习率,从warmup_lr_init线性地增加到warmup_lr_end。在每个迭代中,我们根据当前的学习率更新优化器的参数组。
  3. 之后,我们进入正常的训练阶段,使用学习率调度器进行学习率衰减(StepLR的示例中,每个epoch后学习率会按照设置的gamma进行衰减)。

自己实现

def adjust_learning_rate(optimizer, epoch):
    """Sets the learning rate to the initial LR decayed by 10 every 30 epochs"""
    lr = args.lr * (0.1 ** (epoch // 30))
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

学习率衰减(Learning Rate Decay)在训练神经网络时起到调整学习率的作用。它的主要意义包括以下几点:

  1. 收敛性:较大的学习率可能导致优化过程不稳定,难以达到最优解。通过逐渐降低学习率,可以使模型更好地收敛到全局最优解或局部最优解。
  2. 精细调节:初始阶段使用较高的学习率可以快速接近最优解,而后续阶段采用较小的学习率进行微调。学习率衰减使得模型能够在训练初期进行较大的权重调整,并在接近最优解时进行更精细的参数调节。
  3. 防止震荡:学习率衰减有助于减少优化过程中的震荡现象。较大的学习率可能引起模型权重的剧烈波动,而逐渐减小学习率可以使优化过程更加平稳,避免过度调整和剧烈震荡。
  4. 避免过拟合:较大的学习率可能导致模型过度拟合训练数据,而较小的学习率在一定程度上可以减少过拟合的发生。通过衰减学习率,模型可以更充分地探索参数空间,提高对新数据的泛化能力。

常用的学习率衰减策略包括按照固定时间间隔衰减、按照验证集上的性能进行动态衰减或根据训练损失的变化情况自适应调整学习率等。选择合适的学习率衰减策略取决于具体问题和数据集的特点,以及模型训练的需求。

pytorch学习率衰减策略

常见的学习率衰减方法包括:

  • 常数衰减:按照人工预定义的衰减频率或衰减步骤进行衰减
  • 自适应衰减:通过监测某一指标(如loss)的变化情况,当该指标不变化或者变化较小时,调整学习率;
  • 自定义衰减:Lambda方法提供的调整策略十分灵活,我们可以为不同的层设定不同的学习率调整方法,这在fine-tune中十分有用,我们不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略。

1、StepLR 学习率衰减(按固定步长衰减)

函数定义:

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

功能:

等间隔调整学习率,调整倍数为gamma倍,调整间隔为step_size。间隔单位是step。需要注意的是,step通常是指epoch,而不是iteration。

参数:

  • step_size(int):学习率下降间隔数,若为30,则会在30、60、90…个epoch时,将学习率调整为lr*gamma。
  • gamma(float): 学习率调整倍数,默认为0.1倍,即下降10倍。
  • last_epoch(int):上一个epoch数,这个变量用来指示学习率是否需要调整。当last_epoch符合设定的间隔时,就会对学习率进行调整。当为-1时,学习率设置为初始值。

实例代码:

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义优化器和学习率调度器
optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)

# 在训练循环中更新学习率
for epoch in range(num_epochs):
    # 训练模型的代码
    
    # 更新学习率
    scheduler.step()

2、MultiStepLR 学习率衰减

函数定义:

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

功能:

在指定的epoch处衰减

参数:

  • milestones(list): 一个list,每一个元素代表何时调整学习率,list元素必须是递增的。如 milestones=[30,90,120]
  • gamma(float):学习率调整倍数,默认为0.1倍,即下降10倍。
  • last_epoch(int) :同上

实例代码:

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义优化器和学习率调度器
optimizer = optim.SGD(model.parameters(), lr=0.1)
milestones = [30, 90, 120]  # 里程碑(epoch)列表
scheduler = lr_scheduler.MultiStepLR(optimizer, milestones=milestones, gamma=0.1)

# 在训练循环中更新学习率
for epoch in range(num_epochs):
    # 训练模型的代码
    
    # 更新学习率
    scheduler.step()

3、CosineAnnealingLR 学习率衰减(余弦退火衰减)

函数定义:

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

功能:

  • 以余弦函数为周期,并在每个周期最大值时重新设置学习率。衰减的原理是将学习率从一个较大的初始值逐渐减小到一个较小的最小值,然后再逐渐增加回初始值。在每个周期(设定的epoch数)内,学习率都会按照余弦函数的形式进行调整,使得学习率在训练过程中逐渐变化。
  • 具体来说,CosineAnnealingLR 方法根据给定的周期数(T_max)和最小学习率(eta_min),在每个周期内计算学习率的更新值。学习率在每个周期的前半段呈现余弦递减的趋势,后半段则逐渐增加回初始值。每个周期结束后,学习率都会重置为初始值。

参数:

  • T_max(int): 一次学习率周期的迭代次数,即T_max个epoch之后重新设置学习率。
  • eta_min(float): 最小学习率,即在一个周期中,学习率最小会下降到eta_min,默认值为0

实例代码:

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义模型和优化器
model = YourModel()
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 定义学习率调度器
T_max = 10  # 周期数
eta_min = 0.01  # 最小学习率
scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=T_max, eta_min=eta_min)

# 在训练循环中更新学习率
for epoch in range(num_epochs):
    # 训练模型的代码
    
    # 更新学习率调度器
    scheduler.step()

4、ExponentialLR 学习率衰减(按指数衰减)

函数定义:

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

功能:

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

参数:

  • gamma: 学习率调整倍数的底,指数为epoch,即 gamma**epoch
  • last_epoch(int):同上

实例代码:

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义优化器和学习率调度器
optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = lr_scheduler.ExponentialLR(optimizer, gamma=0.95)

# 在训练循环中更新学习率
for epoch in range(num_epochs):
    # 训练模型的代码
    
    # 更新学习率
    scheduler.step()

5、ReduceLROnPlateau 学习率衰减(基于指标的变化)

函数定义:

class torch.optim.lr_scheduler.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)

功能:

当某指标不再变化(下降或升高),调整学习率,这是非常实用的学习率调整策略。例如,当验证集的loss不再下降时,进行学习率调整;或者监测验证集的accuracy,当accuracy不再上升时,则调整学习率。

参数:

  • mode(str): 模式选择,有 min和max两种模式,min表示当指标不再降低(如监测loss),max表示当指标不再升高(如监测accuracy)。

  • factor(float): 学习率调整倍数(等同于其它方法的gamma),即学习率更新为 lr = lr * factor patience(int)- 直译——“耐心”,即忍受该指标多少个step不变化,当忍无可忍时,调整学习率。注,可以不是连续5次。

  • verbose(bool)-:是否打印学习率信息

  • threshold(float): Threshold for measuring the new optimum,配合threshold_mode使用,默认值1e-4。作用是用来控制当前指标与best指标的差异。

  • threshold_mode(str): 选择判断指标是否达最优的模式,有两种模式,rel和abs。
    当threshold_mode = rel,并且mode = max时,dynamic_threshold = best * ( 1 + threshold ); 当threshold_mode = rel,并且mode = min时,dynamic_threshold = best * ( 1 - threshold ); 当threshold_mode = abs,并且mode = max时,dynamic_threshold = best + threshold ; 当threshold_mode = rel,并且mode = max时,dynamic_threshold = best - threshold

  • cooldown(int): “冷却时间“,当调整学习率之后,让学习率调整策略冷静一下,让模型再训练一段时间,再重启监测模式。

  • min_lr(float or list):学习率下限,可为float,或者list,当有多个参数组时,可用list进行设置。

  • eps(float): 学习率衰减的最小值,当学习率变化小于eps时,则不调整学习率。

实例代码:

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义优化器和学习率调度器
optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=5)

# 在训练循环中更新学习率
for epoch in range(num_epochs):
    # 训练模型的代码
    
    # 计算损失
    loss = ...

    # 更新学习率
    scheduler.step(loss)

6、LambdaLR 学习率衰减(使用自定义的衰减函数)

函数定义:

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

功能:

  • 为不同参数组设定不同学习率调整策略。
    调整规则为,lr = base_lr * lambda(self.last_epoch) 。
  • 它允许根据自定义的衰减函数动态地调整学习率。LambdaLR 提供了一种灵活的方式来定义学习率的变化规律,可以根据训练的进程或其他自定义条件来调整学习率。
  • 在 LambdaLR 中,我们需要定义一个衰减函数 lambda_fn,该函数接受当前训练的 epoch 数作为输入,并返回一个学习率的缩放因子。缩放因子会与初始学习率相乘,从而得到调整后的学习率。

参数:

  • lr_lambda(function or list): 一个计算学习率调整倍数的函数,输入通常为step,当有多个参数组时,设为list。
  • last_epoch(int):同上

实例代码:

import torch
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler

# 定义模型和优化器
model = YourModel()
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 定义学习率调度器
lambda_fn = lambda epoch: 0.5 ** epoch  # 自定义衰减函数
scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda_fn)

# 在训练循环中更新学习率
for epoch in range(num_epochs):
    # 训练模型的代码
    
    # 更新学习率调度器
    scheduler.step()

在上述示例中,我们定义了一个模型和一个优化器,并创建了一个 LambdaLR 的学习率调度器。我们使用 lambda_fn 函数作为衰减函数,它以当前 epoch 数作为输入,并返回一个缩放因子。在每个 epoch 结束后,我们调用 scheduler.step() 方法来更新学习率。

通过使用 LambdaLR,我们可以根据自定义的衰减函数灵活地调整学习率。在示例中,我们使用指数衰减函数,每个 epoch 学习率减半,但你可以根据需要定义其他衰减规则。

需要注意的是,使用 LambdaLR 时,衰减函数的设计很关键。确保衰减函数能够合理地调整学习率,以便在训练过程中获得更好的收敛效果。可以根据具体问题和实验结果来调整衰减函数的形式和参数。

  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

githubcurry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值