背景
深度炼丹如同炖排骨一般,需要先大火全局加热,紧接着中火炖出营养,最后转小火收汁。
本文给出炼丹中的 “火候控制器”-- 学习率的几种调节方法,框架基于 pytorch
1. 自定义根据 epoch 改变学习率。
这种方法在开源代码中常见,此处引用 pytorch 官方实例中的代码 adjust_lr
1. def adjust_learning_rate(optimizer, epoch): 2. """Sets the learning rate to the initial LR decayed by 10 every 30 epochs""" 3. lr = args.lr * (0.1 ** (epoch // 30)) 4. for param_group in optimizer.param_groups: 5. param_group['lr'] = lr
注释:在调用此函数时需要输入所用的 optimizer 以及对应的 epoch ,并且 args.lr 作为初始化的学习率也需要给出。
使用代码示例:
1. optimizer = torch.optim.SGD(model.parameters(),lr = args.lr,momentum = 0.9) 2. for epoch in range(10): 3. adjust_learning_rate(optimizer,epoch) 4. train(...) 5. validate(...)
2. 针对模型的不同层设置不同的学习率
当我们在使用预训练的模型时,需要对分类层进行单独修改并进行初始化,其他层的参数采用预训练的模型参数进行初始化,这个时候我们希望在进行训练过程中,除分类层以外的层只进行微调,不需要过多改变参数,因此需要设置较小的学习率。而改正后的分类层则需要以较大的步子去收敛,学习率往往要设置大一点以 resnet101 为例,分层设置学习率。
1. model = torchvision.models.resnet101(pretrained=True) 2. large_lr_layers = list(map(id,model.fc.parameters())) 3. small_lr_layers = filter(lambda p:id(p) not in large_lr_layers,model.parameters()) 4. optimizer = torch.optim.SGD([ 5. {"params":large_lr_layers}, 6. {"params":small_lr_layers,"lr":1e-4} 7. ],lr = 1e-2,momenum=0.9)
注:large_lr_layers 学习率为 1e-2,small_lr_layers 学习率为 1e-4,两部分参数共用一个 momenum
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。
使用方法示例:
1. optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9) 2. scheduler = ReduceLROnPlateau(optimizer, 'max',verbose=1,patience=3) 3. for epoch in range(10): 4. train(...) 5. val_acc = validate(...) 6. # 降低学习率需要在给出 val_acc 之后 7. scheduler.step(val_acc)
4. 手动设置 lr 衰减区间
使用方法示例
1. def adjust_learning_rate(optimizer, lr): 2. for param_group in optimizer.param_groups: 3. param_group['lr'] = lr 4. 5. for epoch in range(60): 6. lr = 30e-5 7. if epoch > 25: 8. lr = 15e-5 9. if epoch > 30: 10. lr = 7.5e-5 11. if epoch > 35: 12. lr = 3e-5 13. if epoch > 40: 14. lr = 1e-5 15. adjust_learning_rate(optimizer, lr)
5. 余弦退火
论文: SGDR: Stochastic Gradient Descent with Warm Restarts
使用方法示例
1. epochs = 60 2. optimizer = optim.SGD(model.parameters(),lr = config.lr,momentum=0.9,weight_decay=1e-4) 3. scheduler = lr_scheduler.CosineAnnealingLR(optimizer,T_max = (epochs // 9) + 1) 4. for epoch in range(epochs): 5. scheduler.step(epoch)
目前最常用的也就这么多了,当然也有很多其他类别,详情见 how-to-adjust-learning-rate