当前位置: 代码迷 >> 综合 >> 【trick 5】warmup —— 一种学习率调优方法
  详细解决方案

【trick 5】warmup —— 一种学习率调优方法

热度:30   发布时间:2023-12-14 09:38:53.0

目录

  • 一、warmup定义
  • 二、为什么使用warmup
    • 2.1、理性分析
    • 2.2、感性分析
  • 三、常用的warmup
    • 3.1、Constant Warmup
    • 3.2、Linner Warmup
    • 3.3、Cosine Warmup
    • 3.4、Warmup的改进:gradual warmup
  • 四、PyTorch实现
  • 总结
  • Reference

学习率是模型训练中最重要的超参之一,针对学习率的优化有很多种方法,而warmup是其中重要的一种。

一、warmup定义

在模型训练之初选用较小的学习率,训练一段时间之后(如:10epoches或10000steps)使用预设的学习率进行训练。

二、为什么使用warmup

2.1、理性分析

  1. 因为模型的weights是随机初始化的,可以理解为训练之初模型对数据的“理解程度”为0(即:没有任何先验知识),在第一个epoches中,每个batch的数据对模型来说都是新的,模型会根据输入的数据进行快速调参,此时如果采用较大的学习率的话,有很大的可能使模型对于数据“过拟合”(“学偏”),后续需要更多的轮次才能“拉回来”;
  2. 当模型训练一段时间之后(如:10epoches或10000steps),模型对数据具有一定的先验知识,此时使用较大的学习率模型就不容易学“偏”,可以使用较大的学习率加速模型收敛;
  3. 当模型使用较大的学习率训练一段时间之后,模型的分布相对比较稳定,此时不宜从数据中再学到新特点,如果仍使用较大的学习率会破坏模型的稳定性,而使用小学习率更容易获取local optima。

2.2、感性分析

  1. 刚开始模型对数据完全不了解,这个时候步子太大,容易扯着dan,此时需要使用小学习率摸着石头过河;
  2. 对数据了解了一段时间之后,可以使用大学习率朝着目标大步向前;
  3. 快接近目标时,使用小学习率进行探索,此时步子太大,容易错过最近点;

三、常用的warmup

3.1、Constant Warmup

学习率从非常小的数值线性增加到预设值之后保持不变,其学习率的系数如下图所示:
在这里插入图片描述

3.2、Linner Warmup

学习率从非常小的数值线性增加到预设值之后,然后再线性减小。其学习率的系数如下图所示:
在这里插入图片描述

3.3、Cosine Warmup

学习率先从很小的数值线性增加到预设学习率,然后按照cos函数值进行衰减。其学习率系数如下图所示:
在这里插入图片描述

3.4、Warmup的改进:gradual warmup

constant warmup的不足之处在于从一个很小的学习率一下变为比较大的学习率可能会导致训练误差突然增大。于是18年Facebook提出了gradual warmup来解决这个问题,即从最初的小学习率开始,每个step增大一点点,直到达到最初设置的比较大的学习率时,采用最初设置的学习率进行训练。
gradual warmup的实现模拟代码如下:

""" Implements gradual warmup, if train_steps < warmup_steps, the learning rate will be `train_steps/warmup_steps * init_lr`. Args:warmup_steps:warmup步长阈值,即train_steps<warmup_steps,使用预热学习率,否则使用预设值学习率train_steps:训练了的步长数init_lr:预设置学习率 """
import numpy as np
warmup_steps = 2500
init_lr = 0.1  
# 模拟训练15000步
max_steps = 15000
for train_steps in range(max_steps):if warmup_steps and train_steps < warmup_steps:warmup_percent_done = train_steps / warmup_stepswarmup_learning_rate = init_lr * warmup_percent_done  #gradual warmup_lrlearning_rate = warmup_learning_rateelse:#learning_rate = np.sin(learning_rate) #预热学习率结束后,学习率呈sin衰减learning_rate = learning_rate**1.0001 #预热学习率结束后,学习率呈指数衰减(近似模拟指数衰减)if (train_steps+1) % 100 == 0:print("train_steps:%.3f--warmup_steps:%.3f--learning_rate:%.3f" % (train_steps+1,warmup_steps,learning_rate))

四、PyTorch实现

以下是yolov3的PyTorch实现Constant Warmup的部分代码:

# 模型训练开始第一轮采用warmup训练 慢慢训练
lr_scheduler = None
if epoch == 1 and warmup is True:  # 当训练第一轮(epoch=1)时,启用warmup训练方式,可理解为热身训练warmup_factor = 1.0 / 1000warmup_iters = min(1000, len(data_loader) - 1)lr_scheduler = utils.warmup_lr_scheduler(optimizer, warmup_iters, warmup_factor)accumulate = 1  # 慢慢训练,每个batch都改变img大小,每个batch都改变权重

utils.warmup_lr_scheduler:

def warmup_lr_scheduler(optimizer, warmup_iters, warmup_factor):def f(x):"""根据step数返回一个学习率倍率因子 Constant Warmup"""if x >= warmup_iters:  # 当迭代数大于给定的warmup_iters时,倍率因子为1return 1alpha = float(x) / warmup_iters# 迭代过程中倍率因子从warmup_factor -> 1return warmup_factor * (1 - alpha) + alphareturn torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=f)

总结

很有用的调优方法,可以在yolo4中试试。

Reference

  1. 链接1: 原理.
  2. 链接2: 代码.
  相关解决方案