美文网首页
聊一聊学习率预热linear warmup

聊一聊学习率预热linear warmup

作者: 致Great | 来源:发表于2022-01-01 21:23 被阅读0次

    什么是warmup

    warmup是针对学习率learning rate优化的一种策略,主要过程是,在预热期间,学习率从0线性(也可非线性)增加到优化器中的初始预设lr,之后使其学习率从优化器中的初始lr线性降低到0。如下图所示:


    image

    warmup的作用

    由于刚开始训练时,模型的权重(weights)是随机初始化的,此时若选择一个较大的学习率,可能带来模型的不稳定(振荡),选择Warmup预热学习率的方式,可以使得开始训练的几个epoch或者一些step内学习率较小,在预热的小学习率下,模型可以慢慢趋于稳定,等模型相对稳定后再选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。

    为什么warmup有效

    这个问题目前还没有被充分证明,下面是来自知乎的回答解释:

    https://www.zhihu.com/question/338066667
    从理论层面上可以解释为:

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

    从训练效果可以体现为:

    • 一开始神经网络输出比较random,loss比较大,容易不收敛,因此用小点的学习率, 学一丢丢,慢慢涨上去。
    • 梯度偏离真正较优的方向可能性比较大,那就走短一点错了还可以掰回来。

    如何使用warmup

    • 实例1:warm_up_ratio 设置预热步数
    from transformers import AdanW, get_linear_schedule_with_warmup
    
    optimizer = AdamW(model.parameters(), lr=lr, eps=adam_epsilon)
    len_dataset = 3821 # 可以根据pytorch中的len(Dataset)计算
    epoch = 30
    batch_size = 32
    total_steps = (len_dataset // batch_size) * epoch if len_dataset % batch_size = 0 else (len_dataset // batch_size + 1) * epoch # 每一个epoch中有多少个step可以根据len(DataLoader)计算:total_steps = len(DataLoader) * epoch
    
    warm_up_ratio = 0.1 # 定义要预热的step
    scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps = warm_up_ratio * total_steps, num_training_steps = total_steps)
    ......
    optimizer.step()
    scheduler.step()
    optimizer.zero_grad()
    
    • 实例1:num_warmup_steps 设置预热步数
    # training steps 的数量: [number of batches] x [number of epochs].
    total_steps = len(train_dataloader) * epochs
     
    # 设计 learning rate scheduler
    scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps = 50, 
                                                num_training_steps = total_steps)
    

    经验参数选择

    一般可取训练steps的10%,参考BERT。这里可以根据具体任务进行调整,主要需要通过warmup来使得学习率可以适应不同的训练集合,另外我们也可以通过训练误差观察loss抖动的关键位置,找出合适的学习率

    其他非线性warmp策略

    def _get_scheduler(optimizer, scheduler: str, warmup_steps: int, t_total: int):
            """
            Returns the correct learning rate scheduler. Available scheduler: constantlr, warmupconstant, warmuplinear, warmupcosine, warmupcosinewithhardrestarts
            """
            scheduler = scheduler.lower()
            if scheduler == 'constantlr':
                return transformers.get_constant_schedule(optimizer)
            elif scheduler == 'warmupconstant':
                return transformers.get_constant_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps)
            elif scheduler == 'warmuplinear':
                return transformers.get_linear_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps, num_training_steps=t_total)
            elif scheduler == 'warmupcosine':
                return transformers.get_cosine_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps, num_training_steps=t_total)
            elif scheduler == 'warmupcosinewithhardrestarts':
                return transformers.get_cosine_with_hard_restarts_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps, num_training_steps=t_total)
            else:
                raise ValueError("Unknown scheduler {}".format(scheduler))
    

    参考资料

    相关文章

      网友评论

          本文标题:聊一聊学习率预热linear warmup

          本文链接:https://www.haomeiwen.com/subject/gijaqrtx.html