[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

引用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM