深度学习 warmup 策略

本文深入探讨Warmup学习率策略,解释其在深度学习训练中的应用与优势。Warmup策略通过逐步增加学习率帮助模型更好地理解数据分布,避免早期过拟合,提升训练稳定性。文章还分析了Warmup对模型最终收敛点的影响,并提供了TensorFlow和PyTorch的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、介绍

     warmup顾名思义就是热身,在刚刚开始训练时以很小的学习率进行训练,使得网络熟悉数据,随着训练的进行学习率慢慢变大,到了一定程度,以设置的初始学习率进行训练,接着过了一些inter后,学习率再慢慢变小;学习率变化:上升——平稳——下降;

具体步骤:

        启用warm up,设置warm up setp(一般等于epoch*inter_per_epoch),当step小于warm up setp时,学习率等于基础学习率×(当前step/warmup_step),由于后者是一个小于1的数值,因此在整个warm up的过程中,学习率是一个递增的过程!当warm up结束后,学习率以基础学习率进行训练,再学习率开始递减

二、使用场景

1、当网络非常容易nan时候,采用warm up进行训练,可使得网络正常训练;

2、如果训练集损失很低,准确率高,但测试集损失大,准确率低,可用warm up;具体可看:https://blog.csdn.net/u011995719/article/details/77884728

三、有效原因

这个问题目前还没有被充分证明,目前效果有:

  • 有助于减缓模型在初始阶段对mini-batch的提前过拟合现象,保持分布的平稳
  • 有助于保持模型深层的稳定性

在训练期间有如下情况:

     1、在训练的开始阶段,模型权重迅速改变

      2、mini-batch size较小,样本方差较大

        第一种因为刚刚开始的时候,模型对数据的“分布”理解为零,或者是说“均匀分布”(初始化一般都是以均匀分布来初始化);

在第一轮训练的时候,每个数据对模型来说都是新的,随着训练模型会很快地进行数据分布修正,这时候学习率就很大,很有可能在刚刚开始就会导致过拟合,后期需要要通过多轮训练才能拉回来。当训练了一段时间(比如两轮、三轮)后,模型已经对每个数据过几遍了,或者说对当前的batch而言有了一些正确的先验,较大的学习率就不那么容易会使模型学偏,所以可以适当调大学习率。这个过程就也就是warmup。

        那后期为什么学习率又要减小呢?这就是我们正常训练时候,学习率降低有助于更好的收敛,当模型学习到一定的 程度,模型的分布就学习的比较稳定了。如果还用较大的学习率,就会破坏这种稳定性,导致网络波动比较大,现在已经十分接近了最优了,为了靠近这个最优点,我就就要很小的学习率

第二原因:如果有mini-batch内的数据分布方差特别大,这就会导致模型学习剧烈波动,使其学得的权重很不稳定,这在训练初期最为明显,最后期较为缓解

所以由于上面这两个原因,我们不能随便成倍减少学习率;

在resnet文章中,有说到如果一开始就用大的学习率,虽然最终会收敛,但之后测试准确率还是不会提高;如果用了warmup,在收敛后还能有所提高。也就是说,用warm up和不用warm up达到的收敛点,对之后模型能够达到最优点有影响。这说明不用warm up收敛到的点比用warm up收敛到的点更差。这也说明,如果刚刚开始学偏了的权重后面都拉不回来;

那么为什么以前神经网络没用warm up技巧呢?

主要原因是:

    1、y以前网络不够大、不够深

     2、数据集普遍较小

 

四、部分实现代码

1、tensorflow

if warmup:
    warmup_steps = int(batches_per_epoch * 5)
    warmup_lr = (initial_learning_rate * tf.cast(global_step, tf.float32) / tf.cast(warmup_steps, tf.float32))
    return tf.cond(global_step < warmup_steps, lambda: warmup_lr, lambda: lr)

或者 ,看代码来理解,这是摘抄的;

with tf.name_scope('learn_rate'):
    self.global_step = tf.Variable(1.0, dtype=tf.float64, trainable=False, name='global_step')
    warmup_steps = tf.constant(self.warmup_periods * self.steps_per_period,
                               dtype=tf.float64, name='warmup_steps') # warmup_periods epochs
    train_steps = tf.constant((self.first_stage_epochs + self.second_stage_epochs) * self.steps_per_period,
                              dtype=tf.float64, name='train_steps')
    self.learn_rate = tf.cond(
        pred=self.global_step < warmup_steps,
        true_fn=lambda: self.global_step / warmup_steps * self.learn_rate_init,
        false_fn=lambda: self.learn_rate_end + 0.5 * (self.learn_rate_init - self.learn_rate_end) * (
                    1 + tf.cos((self.global_step - warmup_steps) / (train_steps - warmup_steps) * np.pi)))
    global_step_update = tf.assign_add(self.global_step, 1.0)
    """
    训练分为两个阶段,第一阶段里前面又划分出一段作为“热身阶段”:
    热身阶段:learn_rate = (global_step / warmup_steps) * learn_rate_init
    其他阶段:learn_rate_end + 0.5 * (learn_rate_init - learn_rate_end) * (
                    1 + tf.cos((global_step - warmup_steps) / (train_steps - warmup_steps) * np.pi))

2、pytorch

该项目中有pytorch实现

https://github.com/ruinmessi/ASFF/issues/65

 

PyTorchwarmup深度学习中是一种常用的优化技巧,用于在训练初期对学习率进行逐渐增加的过程,以帮助模型更好地收敛。 在深度学习中,学习率是一个重要的超参数,它决定了模型在每次参数更新时调整的步长大小。传统的学习率调度方法,如固定学习率或按照一定的策略进行衰减,可能会导致模型在初始阶段收敛缓慢。 而warmup则是通过在训练初期将学习率从较小的值逐渐增加到设定的初始学习率,然后再按照设定的策略进行衰减。这种策略可以帮助模型在训练初期更快地找到一个较好的参数空间,并进一步提高训练效果。 在PyTorch中,可以使用torch.optim.lr_scheduler模块中的LambdaLR或StepLR等调度器来实现warmup。具体操作是通过设置一个warmup_steps参数来指定预热的步数,在每个训练步骤中计算当前的学习率,并将其应用于优化器。 下面是一个示例代码片段,展示了如何使用PyTorch实现warmup: ```python import torch from torch.optim.lr_scheduler import LambdaLR # 定义优化器和模型 optimizer = torch.optim.SGD(model.parameters(), lr=0.1) scheduler = LambdaLR(optimizer, lr_lambda=lambda step: warmup_factor(step, warmup_steps)) def warmup_factor(step, warmup_steps): if step >= warmup_steps: return 1.0 else: return float(step) / float(warmup_steps) # 训练循环 for epoch in range(num_epochs): for step, (inputs, labels) in enumerate(train_loader): # 前向传播和反向传播 optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # 更新学习率 scheduler.step() ``` 在上述示例中,我们通过定义一个warmup_factor函数来计算当前的学习率缩放因子。在每个训练步骤中,我们使用scheduler.step()来更新学习率,并在优化器中应用新的学习率。 需要注意的是,warmup_steps的具体取值需要根据具体的任务和模型进行调整,通常可以根据实验结果进行调优。 希望这个简单的解释对你有帮助!如果还有其他问题,请随时提问。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值