torch.optim.lr_scheduler 提供了动态调整学习率的方法。在使用的时, Learning Rate Scheduler 一般在优化器的更新参数之后调用。另外,我们也可以在程序中使用多个 scheduler 来调整学习率,如下代码所示:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler1 = ExponentialLR(optimizer, gamma=0.9)
scheduler2 = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
# 参数更新
optimizer.step()
# 在优化器更新之后使用学习率调整
# 可以同时使用多个学习率调整策略
scheduler1.step()
scheduler2.step()
接下来,介绍 PyTorch 官网提供的几种学习率优化策略。主要包含以下几种:
lr_scheduler.LambdaLRlr_scheduler.MultiplicativeLRlr_scheduler.StepLRlr_scheduler.MultiStepLRlr_scheduler.ConstantLRlr_scheduler.LinearLRlr_scheduler.ExponentialLR
1. LambdaLR
LambdaLR 每个 step 后,lr 调整为上一个时刻的 lr_lambda,例如:lr_lambda=0.9,则 lambda step: 0.9 ** step。
LambdaLR(optimizer, lr_lambda, last_epoch=- 1, verbose=False)
示例代码:
import torch
from torch.optim.lr_scheduler import LambdaLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.Adam(parameter, lr=0.1)
# 调度器
scheduler = LambdaLR(optimizer=optimizer,
lr_lambda=lambda step: 0.9 ** step)
learning_rates = [0.1]
for _ in range(10):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
learning_rates.append(scheduler.get_last_lr()[0])
print('%.5f' % scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(11), learning_rates, 'ro-')
plt.title('LambdaLR')
plt.grid()
plt.show()

2. MultiplicativeLR
MultiplicativeLR 与 LambdaLR 区别如下:

LambdaLR 是由初始学习率乘以 lambda 函数的返回值,而 MultiplicativeLR 则是使用上一个学习率乘以 lambda 函数的返回值。
MultiplicativeLR(optimizer, lr_lambda, last_epoch=- 1, verbose=False)
示例代码:
import torch
from torch.optim.lr_scheduler import MultiplicativeLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.Adam(parameter, lr=0.1)
# 调度器
scheduler = MultiplicativeLR(optimizer=optimizer,
lr_lambda=lambda step: 0.9)
learning_rates = [0.1]
for _ in range(10):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
learning_rates.append(scheduler.get_last_lr()[0])
print('%.5f' % scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(11), learning_rates, 'ro-')
plt.title('MultiplicativeLR')
plt.grid()
plt.show()

3. StepLR
StepLR 可以实现迭代固定多少 epoch 时,对学习率进行衰减。
StepLR(optimizer, step_size, gamma=0.1, last_epoch=- 1, verbose=False)
- gamma 就是衰减的系数。假设:gamma=0.1,则学习率衰减为上一个学习率的 0.1
- step_size 表示经过多少个 step 对学习率进行一次衰减
比如:我们每 5 个 epoch,就把学习修改为上一个学习率的 0.5,如下代码所示:
import torch
from torch.optim.lr_scheduler import StepLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.SGD(parameter, lr=0.1)
# 调度器
scheduler = StepLR(optimizer=optimizer, step_size=5, gamma=0.5)
learning_rates = [0.1]
for _ in range(100):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
print('%.5f' % scheduler.get_last_lr()[0])
learning_rates.append(scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(101), learning_rates)
plt.title('StepLR')
plt.grid()
plt.show()

4. MultiStepLR
MultiStepLR 和 StepLR 的区别是,前者可以自定义多个 step 点来进行学习率衰减,而后者只能根据固定的间隔来衰减学习率。
MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=- 1, verbose=False)
参数中 milestones 是列表类型,用来设置需要进行学习率衰减的 epoch 点。例如,我们总共进行 100 epoch,设置 [10, 40, 50, 80] 这 4 个 epoch 点来衰减学习率。
import torch
from torch.optim.lr_scheduler import MultiStepLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.SGD(parameter, lr=0.1)
# 调度器
scheduler = MultiStepLR(optimizer=optimizer, gamma=0.5, milestones=[10, 40, 50, 80])
learning_rates = [0.1]
for _ in range(100):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
print('%.5f' % scheduler.get_last_lr()[0])
learning_rates.append(scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(101), learning_rates)
plt.title('MultiStepLR')
plt.grid()
plt.show()

5. ConstantLR
我们希望训练开始时,使用较小的学习率训练多个 step,然后再使用大的学习率继续训练。在这里,小学习率和大学习率都是固定的。ConstantLR 可以做这样的工作。
ConstantLR(optimizer, factor=0.33, total_iters=5, last_epoch=- 1, verbose=False)
factor 用来指定小学习率,total_iters 指定使用该小学习率训练多少 step,在 total_iters 轮次结束之后,学习率会回到我们在 optimizer 里设置的初始学习率。
import torch
from torch.optim.lr_scheduler import ConstantLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
parameter = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.Adam(parameter, lr=1)
# 调度器
scheduler = ConstantLR(optimizer=optimizer, factor=0.1, total_iters=5)
learning_rates = [0.1]
for _ in range(10):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
learning_rates.append(scheduler.get_last_lr()[0])
print('%.5f' % scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(11), learning_rates, 'ro-')
plt.title('ConstantLR')
plt.grid()
plt.show()

6. LinearLR
LinearLR(optimizer, start_factor=0.33, end_factor=1.0, total_iters=5, last_epoch=- 1, verbose=False)
学习率经过 total_iters 个 step 从 lr * start_factor 到 lr * end_factor,然后恒定保持不变, lr 为优化器指定。
import torch
from torch.optim.lr_scheduler import LinearLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
model_parameters = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.SGD(model_parameters, lr=0.1)
# 调度器
scheduler = LinearLR(optimizer=optimizer, start_factor=0.001, end_factor=0.10, total_iters=50)
learning_rates = []
for _ in range(100):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
print('%.5f' % scheduler.get_last_lr()[0])
learning_rates.append(scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(100), learning_rates)
plt.title('LinearLR')
plt.grid()
plt.show()

7. ExponentialLR
ExponentialLR 表示学习率每个 epoch 是 epoch-1 学习率的 0.9(gamma=0.9)。
ExponentialLR(optimizer, gamma, last_epoch=- 1, verbose=False)
import torch
from torch.optim.lr_scheduler import ExponentialLR
import torch.optim as optim
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 模型参数
model_parameters = [nn.Parameter(torch.tensor([1, 2, 3], dtype=torch.float32))]
# 优化器
optimizer = optim.SGD(model_parameters, lr=0.1)
# 调度器
scheduler = ExponentialLR(optimizer=optimizer, gamma=0.9)
learning_rates = []
for _ in range(100):
# 先优化器更新
optimizer.step()
# 再调度器更新
scheduler.step()
# 存储学习率
print('%.5f' % scheduler.get_last_lr()[0])
learning_rates.append(scheduler.get_last_lr()[0])
# 绘制学习率变化
plt.plot(range(100), learning_rates)
plt.title('ExponentialLR')
plt.grid()
plt.show()
输出结果:
0.09000 # 0.1000 * 0.9 0.08100 # 0.9000 * 0.9 0.07290 # 0.0810 * 0.9 0.06561 # 0.7290 * 0.9 # 后面以此类推


冀公网安备13050302001966号