Pytorch 动态调整学习率

Pytorch 动态调整学习率

前言

今天新人加入博客,希望从今天开始能培养自己一个好习惯,记录一些编程过程中解决的问题,日积月累。

正文

今天刚好在用PyTorch 做deep learning的实验,所以在看关于动态调整学习率自衰减的代码,很荣幸它成为了我第一篇博文。详细内容来源于这个链接中的内容:http://www.spytensor.com/index.php/archives/32/

1. 自定义根据 epoch 改变学习率。

这种方法在开源代码中常见,此处引用 pytorch 官方实例中的代码 adjust_lr。

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

值得注意的是,在调用此函数时需要输入所用的 optimizer 以及对应的 epoch ,并且 args.lr 作为初始化的学习率也需要给出。所以需要正常的定义optimizer和初始化的学习率并带入函数,然后在学习过程中调用函数让学习率自衰减。

使用代码示例:

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

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

当我们在使用预训练的模型时,需要对分类层进行单独修改并进行初始化,其他层的参数采用预训练的模型参数进行初始化,这个时候我们希望在进行训练过程中,除分类层以外的层只进行微调,不需要过多改变参数,因此需要设置较小的学习率。而改正后的分类层则需要以较大的步子去收敛,学习率往往要设置大一点以 resnet101 为例,分层设置学习率。

model = torchvision.models.resnet101(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 = 1e-2,momenum=0.9)

值得注意的是,large_lr_layers 学习率为 1e-2,small_lr_layers 学习率为 1e-4,两部分参数共用一个 momenum。所以large_lr_layers指向的是optimizer中定义的参数lr,small_lr_layers中lr是直接定义的。

3. 根据具体需要改变 lr

以前使用 keras 的时候比较喜欢 ReduceLROnPlateau 可以根据 损失或者 准确度的变化来改变 lr。最近发现 pytorch 也实现了这一个功能。

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)
scheduler = ReduceLROnPlateau(optimizer, 'max',verbose=1,patience=3)
for epoch in range(10):
    train(...)
    val_acc = validate(...)
    # 降低学习率需要在给出 val_acc 之后
    scheduler.step(val_acc)

4. 手动设置 lr 衰减区间

使用方法示例:

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)

值得注意的是,此方法和“自定义根据epoch调整学习率”基本一致,只不过根据epoch分段进行具体的lr的设置。

5. 余弦退火

论文: 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)

总结:

以上是目前常见的方法,根据难易程度可能会先做“自定义根据epoch调整学习率”进行自衰减。希望实验可以成功。

更新:(16/Jul/2020)

更新一下今天的新知识,根据pytorch官方的定义,可以直接用lambda表达式定义衰减率,然后用官方的lambdaLR()定义scheduler调整学习率。原文链接:https://pytorch.org/docs/master/optim.html#how-to-adjust-learning-rate

原文中的学习率lr需要用args来获取模型参数,但是有时候并不需要argparse获取模型参数,这样会导致报错找不到变量args。

代码如下:

lambda2 = lambda epoch: 0.95 ** (epoch // 200)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda = lambda2)

官方例子中lr_lambda = [lambda1, lambda2]会导致报错,因为我们只需要一个lambda即可。例子中是给出了两种定义方法所以让我们任选其一。

今天又是元气满满的一天。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值