warmup lr 策略-一种学习率预热的方法

目的(效果):
模型初始训练时,模型的权重是随机初始化的,初始学习率太大,可能会导致模型的震荡(不稳定),选择学习率预热方法,在初始的几个epoch或者是steps内用一个比较小的学习率,训练完制定的epoch或者steps之后恢复设置的初始学习率

为了防止从较小学习率到指定的初始学习率变化较大引起误差增大。gradual warmup可以缓解这个问题,通过每个steps逐渐增大lr,知道达到指定的初始学习率后再开始学习率的下降。

在哪些场景带来的收益较大:
1.当网络非常容易出现nan时,采用warm up策略,可以使网络可以正常收敛
2.当训练集损失很低,但是测试集损失很大,准确率较低时

### 如何在余弦退火学习率调度器中实现学习率预热 #### 学习率预热的概念 学习率预热一种常见的优化技巧,在训练初期逐渐增加学习率,以便让模型更快地适应梯度变化并进入稳定状态。这种技术尤其适用于大规模数据集或复杂模型的场景。 #### PyTorch 中余弦退火学习率的基础 PyTorch 提供了 `CosineAnnealingLR` 调度器来实现余弦退火学习率策略[^3]。该调度器的核心思想是通过余弦函数控制学习率的变化范围,使其在一个周期内按照特定规律波动。然而,默认情况下,它并未提供学习率预热的功能。 为了结合学习率预热与余弦退火策略,可以采用自定义的方式实现这一目标。 --- #### 实现方式:组合线性增长与余弦退火 可以通过以下两种方法实现: 1. **手动编写自定义调度器** 创建一个新的类继承自 `_LRScheduler` 并重写其逻辑,使前几个 epoch 的学习率按线性增长,之后切换到余弦退火模式。 2. **使用两个调度器串联** 利用 `ChainedScheduler` 或者手动管理多个调度器的状态,先应用线性增长的学习率调度器(如 `LambdaLR`),再切换至 `CosineAnnealingLR`。 以下是具体代码示例: --- #### 方法一:手动编写自定义调度器 ```python import math from torch.optim.lr_scheduler import _LRScheduler class WarmupCosineAnnealingLR(_LRScheduler): def __init__(self, optimizer, warmup_epochs, total_epochs, max_lr, min_lr=0, last_epoch=-1): self.warmup_epochs = warmup_epochs self.total_epochs = total_epochs self.max_lr = max_lr self.min_lr = min_lr super(WarmupCosineAnnealingLR, self).__init__(optimizer, last_epoch) def get_lr(self): if self.last_epoch < self.warmup_epochs: # Linearly increase the learning rate during warm-up phase alpha = float(self.last_epoch) / self.warmup_epochs return [(base_lr * alpha) for base_lr in [self.max_lr]] else: # Apply cosine annealing after warm-up progress = (self.last_epoch - self.warmup_epochs) / (self.total_epochs - self.warmup_epochs) cos_val = 0.5 * (1 + math.cos(math.pi * progress)) return [ self.min_lr + (self.max_lr - self.min_lr) * cos_val for base_lr in [self.max_lr] ] ``` 此调度器实现了两阶段的行为: - 前 `warmup_epochs` 个 epoch 使用线性增长; - 后续部分遵循标准的余弦退火曲线。 --- #### 方法二:使用 LambdaLR 和 CosineAnnealingLR 组合 另一种更灵活的方法是利用现有的调度器功能,分别处理预热和退火过程。 ```python from torch.optim.lr_scheduler import LambdaLR, SequentialLR, CosineAnnealingLR def linear_warmup(epoch, warmup_epochs): """Linearly increases learning rate from 0 to 1 over given epochs.""" return min(1., epoch / warmup_epochs) # Example usage optimizer = ... # Define your optimizer here warmup_epochs = 5 total_epochs = 50 max_lr = 0.1 min_lr = 0.001 # Step 1: Create a scheduler for warm-up scheduler_warmup = LambdaLR(optimizer, lr_lambda=lambda epoch: linear_warmup(epoch, warmup_epochs)) # Step 2: Create a scheduler for cosine annealing scheduler_cosine = CosineAnnealingLR(optimizer, T_max=(total_epochs - warmup_epochs), eta_min=min_lr) # Step 3: Combine them using SequentialLR scheduler_combined = SequentialLR( optimizer, schedulers=[scheduler_warmup, scheduler_cosine], milestones=[warmup_epochs] ) ``` 这种方法的优势在于无需重新实现复杂的调度逻辑,而是直接复用了现有工具链中的组件。 --- #### 参数说明 | 参数名 | 描述 | |-----------------|----------------------------------------------------------------------------------------| | `warmup_epochs` | 预热期持续的时间长度(单位为 epoch)。 | | `total_epochs` | 整个训练过程的总时间长度(单位为 epoch)。 | | `max_lr` | 训练期间的最大学习率值。 | | `min_lr` | 训练结束后的最小学习率值。 | 这些参数的选择应基于具体的任务需求以及实验验证的结果[^1]。 --- #### 总结 无论是通过自定义调度器还是组合已有调度器,都可以有效地将学习率预热机制融入余弦退火策略之中。这两种方法各有优劣,前者提供了更高的灵活性,而后者则更加简洁易用。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值