zoukankan      html  css  js  c++  java
  • [pytorch]动态调整学习率

    问题描述

    在深度学习的过程中,会需要有调节学习率的需求,一种方式是直接通过手动的方式进行调节,即每次都保存一个checkpoint,但这种方式的缺点是需要盯着训练过程,会很浪费时间。因此需要设定自动更新学习率的方法,让模型自适应地调整学习率。

    解决思路

    1. 通过epoch来动态调整,比如每10次学习率为原来的0.1

    实现示例:

    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 // 10))
        for param_group in optimizer.param_groups:
            param_group['lr'] = lr
    

    调用示例:

    optimizer = torch.optim.SGD(model.parameters(),lr = args.lr,momentum = 0.9)
    for epoch in range(10):
        adjust_learning_rate(optimizer,epoch)
        train(...)
        validate(...)
    

    但这种方法的缺点是,你必须事先知道大概多久才能调整一次学习率,假如设置的过快,那么网络将很快就进入到不学习的状态,如果设置的过慢,很可能很长时间都学习不到东西。

    1. 对模型的不同层设置不同的学习率

    在迁移学习中,往往会使用ImageNet上的预训练模型,那么实际上Conv层和FC层将具有不同的学习率,比如,可以将Conv层的学习率设置为0.0001,将全连接层的学习率设置为0.1,这样特征提取层的权值还是使用的原有ImageNet的预训练权重,模型将更容易收敛。

    model = torchvision.models.resne50(pretrained=True)
    large_lr_layers = list(map(id,model.fc.parameters()))
    small_lr_layers = filter(lambda p:id(p) not in large_lr_layers,model.parameters())
    optimizer = torch.optim.SGD([
                {"params":large_lr_layers},
                {"params":small_lr_layers,"lr":1e-4}
                ],lr = 0.1,momenum=0.9)
    
    1. 根据训练指标的变化来调整学习率

    有时候需要根据准确率来调整学习率,比如n次准确率都没有提升的情况下降低准确率,对应类为:

    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)
    

    以 acc 为例,当 mode 设置为 “max” 时,如果 acc 在给定 patience 内没有提升,则以 factor 的倍率降低 lr。

    optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9, factor=0.1)
    scheduler = ReduceLROnPlateau(optimizer, mode='max',verbose=1,patience=3)
    for epoch in range(10):
        train(...)
        val_acc = validate(...)
        # 降低学习率需要在给出 val_acc 之后
        scheduler.step(val_acc)
    

    上述代码在3次内准确率都没有提升,则改变学习率为之前的0.1

    1. 通过手动的方式来分段学习率
    def adjust_learning_rate(optimizer, lr):
        for param_group in optimizer.param_groups:
            param_group['lr'] = lr
    
    for epoch in range(60):        
        lr = 30e-5
        if epoch > 25:
            lr = 15e-5
        if epoch > 30:
            lr = 7.5e-5
        if epoch > 35:
            lr = 3e-5
        if epoch > 40:
            lr = 1e-5
        adjust_learning_rate(optimizer, lr)
    
    1. 通过余弦退火的方式来减少学习率

    相关论文:SGDR: Stochastic Gradient Descent with Warm Restarts

    epochs = 60
    optimizer = optim.SGD(model.parameters(),lr = config.lr,momentum=0.9,weight_decay=1e-4) 
    scheduler = lr_scheduler.CosineAnnealingLR(optimizer,T_max = (epochs // 9) + 1)
    for epoch in range(epochs):
        scheduler.step(epoch)
    

    常用的就这么几个,其他更加奇怪的用法,可以看官方how-to-adjust-learning-rate

    引用

  • 相关阅读:
    笔记手动排序
    笔记手动分页
    Spring定时任务Quartz配置之手动设置
    java 日期处理
    SQL Case when 的使用方法
    Hibernate八大类HQL查询集合
    Spring定时任务Quartz配置
    各个浏览器显示版本(IE,火狐)
    js转译html标签
    定时备份SQL SERVER的数据库并且把备份文件复制到另外一台服务器
  • 原文地址:https://www.cnblogs.com/wildkid1024/p/12860134.html
Copyright © 2011-2022 走看看