一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler

一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler

torch.optim.lr_scheduler提供了三种根据epoch训练数来调整学习率(learning rate)的方法。具体方法如下:

一、有序调整:

1.等间隔调整(Step):torch.optim.lr_scheduler.StepLR

n e w − l r = i n i t i a l − l r ∗ γ e p o c h s t e p − s i z e new_-lr=initial_-lr*\gamma^{\frac{epoch}{step_-size}} newlr=initiallrγstepsizeepoch

更新策略:
每过step_size个epoch,学习率进行一次更新

n e w − l r new_-lr newlr:新得到的学习率。
i n i t i a l − l r initial_-lr initiallr:初始学习率。
γ \gamma γ:参数gamma,更新 l r lr lr的乘法因子。
s t e p − s i z e step_-size stepsize:每训练step_size个epoch,更新一次 l r lr lr
l a s t − e p o c h last_-epoch lastepoch:最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为-1表示从头开始训练,即从epoch=1开始。

代码如下:

import matplotlib.pyplot as plt
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
from torchvision.models import AlexNet

num_epochs = 100

#定义2分类网络
model = AlexNet(num_classes=2)
optimizer = optim.SGD(params=model.parameters(), lr=0.05)

scheduler = StepLR(
    optimizer=optimizer,
    step_size=20,  # 设定调整的间隔数
    gamma=0.5,  # 系数
    last_epoch=-1
)
# 迭代训练
lrs, epochs = [], []
for epoch in range(num_epochs):
    lrs.append(scheduler.get_lr())  #.get_lr()获取当前学习率
    epochs.append(epoch)

    pass  # 在这里进行迭代训练
    #学习率更新
    scheduler.step()
    
# visualize
plt.figure()
plt.legend()
plt.plot(epochs, lrs, label='StepLR')
plt.show()

一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler_第1张图片

2.按需调整学习率(MultiStep):

torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)
n e w − l r = i n i t i a l − l r ∗ γ b i s e c t − r i g h t ( m i l e s t o n e s , e p o c h ) new_-lr=initial_-lr*\gamma ^{bisect_-right(milestones,epoch)} newlr=initiallrγbisectright(milestones,epoch)
更新策略:
每次遇到milestones中的epoch,学习率做一次更新。

n e w − l r new_-lr newlr:新得到的学习率。
i n i t i a l − l r initial_-lr initiallr:初始学习率。
γ \gamma γ:参数gamma,更新 l r lr lr的乘法因子。
m i l e s t o n e s milestones milestones:递增的list,存放需要更新 l r lr lr的epoch。
l a s t − e p o c h last_-epoch lastepoch:最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为-1表示从头开始训练,即从epoch=1开始。
b i s e c t − r i g h t ( m i l e s t o n e s , e p o c h ) bisect_-right(milestones,epoch) bisectright(milestones,epoch)bisect模块中的bisect_right函数,返回值是把epoch插入排序好的列表milestones式的位置。

代码如下:

import matplotlib.pyplot as plt
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import MultiStepLR
from torchvision.models import AlexNet

num_epochs = 100

#定义2分类网络
model = AlexNet(num_classes=2)
optimizer = optim.SGD(params=model.parameters(), lr=0.05)

scheduler = MultiStepLR(
    optimizer=optimizer,
    milestones=[10, 20, 40],  # 设定调整的间隔数
    gamma=0.5,  # 系数
    last_epoch=-1 
)

# train-like iteration
lrs, epochs = [], []
for epoch in range(num_epochs):
    lrs.append(scheduler.get_lr())  #.get_lr()获取当前学习率
    epochs.append(epoch)

    pass  # 在这里进行迭代训练
    #学习率更新
    scheduler.step()

# visualize
plt.figure()
plt.legend()
plt.plot(epochs, lrs, label='MultiStepLR')
plt.show()

其中最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为-1表示从头开始训练,即从epoch=1开始。
一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler_第2张图片

3.指数衰减调整(Exponential):torch.optim.lr_scheduler.ExponentialLR
n e w − l r = i n i t i a l − l r ∗ γ e p o c h new_-lr=initial_-lr*\gamma ^{epoch} newlr=initiallrγepoch

import matplotlib.pyplot as plt
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import ExponentialLR
from torchvision.models import AlexNet
import seaborn as sns

num_epochs = 100

#定义2分类网络
model = AlexNet(num_classes=2)
optimizer = optim.SGD(params=model.parameters(), lr=0.05)

scheduler = ExponentialLR(
    optimizer=optimizer,
    gamma=0.5,  # 系数
    last_epoch=-1
)

# train-like iteration
lrs, epochs = [], []
for epoch in range(num_epochs):
    lrs.append(scheduler.get_lr())  #.get_lr()获取当前学习率
    epochs.append(epoch)

    pass  # 在这里进行迭代训练
    #学习率更新
    scheduler.step()

# visualize
plt.figure()
plt.plot(epochs, lrs, label='ExponentialLR')
plt.legend()
plt.show()

一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler_第3张图片

4.余弦退火调整(CosineAnnealing):torch.optim.lr_sheduler.CosineAnnealingLR
n e w − l r = e t a − m i n + ( i n i t i a l − l r − e t a − m i n ) ∗ ( 1 + c o s ( e p o c h T − m a x ∗ π ) ) new_-lr=eta_-min+(initial_-lr-eta_-min)*(1+cos(\frac{epoch}{T_-max}*\pi )) newlr=etamin+(initiallretamin)(1+cos(Tmaxepochπ))
更新策略:
每次遇到milestones中的epoch,学习率做一次更新。

n e w − l r new_-lr newlr:新得到的学习率。
i n i t i a l − l r initial_-lr initiallr:初始学习率。
e t a − m i n eta_-min etamin:表示最小学习率。
T − m a x T_-max Tmax:代表1/2个cos周期所对应的epoch值,学习率下降到最小值时的epoch数,即当epoch=T_max时,学习率下降到余弦函数最小值,当epoch>T_max时,学习率将增大;
l a s t − e p o c h last_-epoch lastepoch:最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为-1表示从头开始训练,即从epoch=1开始。

import matplotlib.pyplot as plt
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import CosineAnnealingLR
from torchvision.models import AlexNet

num_epochs = 100

#定义2分类网络
model = AlexNet(num_classes=2)
optimizer = optim.SGD(params=model.parameters(), lr=0.05)

scheduler = CosineAnnealingLR(
    optimizer=optimizer,
    T_max=20,  # 设定调整的间隔数
    eta_min=0.005,  # 系数
    last_epoch=-1
)
# 迭代训练
lrs, epochs = [], []
for epoch in range(num_epochs):
    lrs.append(scheduler.get_lr())  #.get_lr()获取当前学习率
    epochs.append(epoch)

    pass  # 在这里进行迭代训练
    #学习率更新
    scheduler.step()
    
# visualize
plt.figure()
plt.legend()
plt.plot(epochs, lrs, label='CosineAnnealingLR')
plt.show()

一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler_第4张图片

二、自适应调整:
自适应调整学习率 ReduceLROnPlateau:torch.optim.lr_scheduler.ReduceLROnPlateau
n e w − l r = λ ∗ o l d − l r new_-lr=\lambda *old_-lr newlr=λoldlr

三、自定义调整:
自定义调整学习率 LambdaLR:torch.optim.lr_scheduler.LambdaLr(optimizer, lr_lambda, last_epoch=-1)

更新策略:
遇到模型不同的层参数时,根据该层参数的调整方式来调整学习率。

为不同参数组设定不同学习率调整策略,在fine-tune中特别有用,我们不仅可以为不同层设置不同的学习率,还可以为不同层设置不同的学习率调整策略。
n e w − l r = λ ∗ i n i t i a l − l r new_-lr=\lambda *initial_-lr newlr=λinitiallr
n e w − l r new_-lr newlr:新得到的学习率。
i n i t i a l − l r initial_-lr initiallr:初始学习率。
λ λ λ:通过参数lr_lambdaepoch得到的。
l r − l a m b d a lr_-lambda lrlambda:根据epoch计算λ的函数;或者是一个list的这样的function,分别计算各个parameter groups的学习率更新用到的λ;

import matplotlib.pyplot as plt
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import LambdaLR
from torchvision.models import AlexNet
import seaborn as sns

num_epochs = 100

#定义2分类网络
model = AlexNet(num_classes=2)


# optimizer parameter groups 设置了个优化组:权重,偏置,其他参数
pg0, pg1, pg2 = [], [], [] 
for k, v in model.named_parameters():
    v.requires_grad = True
    if '.bias' in k:
        pg2.append(v)  # biases
    elif '.weight' in k and '.bn' not in k:
        pg1.append(v)  # apply weight decay
    else:
        pg0.append(v)  # all else

optimizer = optim.SGD(pg1, lr=0.05)

#给optimizer管理的参数组中增加新的组参数,
#可为该组参数定制lr,momentum,weight_decay 等在finetune 中常用。
optimizer.add_param_group({
     'params': pg2})  # add pg2 (biases)

# 对于卷积层权重的学习率,每十轮调整为原来的 0.1 倍
pg1 = lambda epoch: 0.1 ** (epoch // 10)
# 对于偏置权重的学习率,每轮调整为原来的 0.94 倍
pg2 = lambda epoch: 0.94 ** epoch


scheduler = LambdaLR(
    optimizer=optimizer,
    lr_lambda=[pg1, pg2],  #传入一个函数或一个以函数为元素列表,作为学习率调整的策略
    last_epoch=-1
)

weight_lrs, bias_lrs, epochs = [], [], []
for epoch in range(num_epochs):
    weight_lrs.append(scheduler.get_lr()[0])
    bias_lrs.append(scheduler.get_lr()[1])
    epochs.append(epoch)

    pass  # iter and train here

    scheduler.step(epoch)

# visualize
plt.figure()
plt.plot(epochs, weight_lrs, label='step')
plt.plot(epochs, bias_lrs, label='exponential')
plt.legend()
plt.show()

一文搞懂pytorch中的学习率优化策略,torch.optim.lr_scheduler_第5张图片

你可能感兴趣的:(人工智能,深度学习,pytorch,神经网络,python)