- 本文为365天深度学习训练营 中的学习记录博客
- 参考文章:365天深度学习训练营-第P5周:运动鞋识别
- 原作者:K同学啊|接辅导、项目定制
本次实战主要学习内容:
编写一段代码用来调整模型优化器中学习率的函数。它接受三个参数:优化器(optimizer)、当前的 epoch 数量(epoch)以及初始学习率(start_lr)。
将 lr 设置为 start_lr 乘以 0.92 的 epoch//2 次方,表示每两个 epoch 学习率都会降低到原来的 0.92 倍。
def adjust_learning_rate(optimizer, epoch, start_lr):
# 每 2 个 epoch 将学习率衰减到原来的 0.92
lr = start_lr * (0.92 ** (epoch // 2))
# 遍历优化器中的所有参数组,并将学习率设置为新的值
for param_group in optimizer.param_groups:
param_group['lr'] = lr
# 初始学习率设为1e-4
learn_rate = 1e-4
# 使用 SGD 优化器,并传入初始学习率作为参数
optimizer = torch.optim.SGD(model.parameters(), lr=learn_rate)
使用PyTorch中的学习率调度器来动态地调整模型训练时的学习率。
首先,定义了一个lambda函数lambda1
,该函数将每个epoch(训练时对数据集遍历一次称为一个epoch)作为输入,返回一个新的学习率。在这里,新学习率是原学习率(learn_rate)的0.92的(epoch//2)次方。这意味着每过两个epoch,学习率将降低为原来的0.92倍。
接下来,创建了一个SGD优化器(Stochastic Gradient Descent,随机梯度下降),用于更新模型中的参数,并将初始学习率传递给它。
然后,使用LambdaLR类创建了一个学习率调度器对象scheduler。LambdaLR接受两个参数:优化器对象和一个lr_lambda函数。在这里,我们将之前定义的lambda函数传递给它,以便在每个epoch结束时调整学习率。
最后,可以通过optimizer.param_groups[0][‘lr’]来查看当前学习率的值。
与上面方法是等价的
# 调用官方动态学习率接口时使用
lambda1 = lambda epoch: 0.92 ** (epoch // 2)
optimizer = torch.optim.SGD(model.parameters(), lr=learn_rate)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1) #选定调整方法
# 更新学习率
adjust_learning_rate(optimizer, epoch, learn_rate)
# 更新学习率
scheduler.step()
torch.optim.lr_scheduler.StepLR
,它可以根据给定的步长和衰减因子来动态地调整优化器的学习率。具体来说,每经过一个指定的步数后,学习率就会按照衰减因子进行乘法运算,从而使得学习率不断降低。
下面是StepLR
的使用方法:
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma, last_epoch=-1)
其中,参数含义如下:
optimizer(Optimizer)
: 是之前定义好的需要优化的优化器的实例名。step_size(int)
: 是学习率衰减的周期,每经过每个epoch,做一次学习率decay;学习率调整的步长,即经过多少次迭代之后才对学习率进行调整,默认值为1。gamma(float)
: 学习率衰减的乘法因子,学习率下降的倍数,即每次调整后学习率都会乘以这个倍数,默认值为0.1。last_epoch
: 上一次调整学习率发生的迭代次数,如果不指定则默认为-1,表示当前没有完成任何一次迭代。等间隔动态调整方法,每经过step_size个epoch,做一次学习率decay,以gamma值为缩小倍数。
当调用StepLR.step()
方法时,该调度器会将优化器的学习率进行更新。例如,假设我们想要每10个epoch将学习率降低为原来的0.1倍,那么代码如下:
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
for epoch in range(100):
train(...)
test(...)
# 调整学习率
scheduler.step()
上述代码中,scheduler.step()
会在每个epoch结束后被调用一次,从而对优化器的学习率进行更新。
需要注意的是,StepLR
还有一个可选参数verbose
,可以用来控制是否打印学习率的更新信息。当verbose=True
时,每次调用StepLR.step()
方法时都会打印出当前的学习率。
用法示例:
optimizer = torch.optim.SGD(net.parameters(), lr=0.001 )
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
torch.optim.lr_scheduler.LambdaLR
,它允许用户通过传递一个函数来自定义学习率衰减方式。该函数接受当前epoch作为输入,返回一个学习率因子,将其应用于初始学习率以获得每个epoch的新学习率。
下面是LambdaLR的构造函数:
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1, verbose=False)
其中,参数说明如下:
optimizer(Optimizer)
:需要进行学习率调度的优化器对象。lr_lambda(function)
:更新学习率的函数,它接受当前epoch作为输入,返回一个新的学习率因子。例如,如果我们想将学习率按照指数方式衰减,则可以这样定义lr_lambda
函数:lambda epoch: 0.95 ** epoch
。last_epoch
:用于指定上一次调用step()
方法时的epoch数,当last_epoch
和当前epoch相同时,表明已经调用过step()
方法了。下面是一个例子,展示如何使用LambdaLR对优化器的学习率进行指数衰减:
import torch.optim as optim
from torch.optim.lr_scheduler import LambdaLR
# 定义优化器和学习率衰减函数
model = ... # 模型定义
optimizer = optim.SGD(model.parameters(), lr=0.1)
lr_decay = LambdaLR(optimizer, lr_lambda=lambda epoch: 0.95 ** epoch)
# 在每个epoch后调用step()方法
for epoch in range(num_epochs):
train(...)
lr_decay.step()
在上面的例子中,学习率将按照指数方式衰减,每个epoch的学习率为前一个epoch学习率的0.95次方。在每个epoch结束时,需要调用lr_decay.step()
方法来更新优化器的学习率。
LambdaLR还可以与其他学习率调度器结合使用,例如StepLR、MultiStepLR等,以实现更复杂的学习率调度策略。
根据自己定义的函数更新学习率。
用法示例:
lambda1 = lambda epoch: (0.92 ** (epoch // 2) # 第二组参数的调整方法
optimizer = torch.optim.SGD(model.parameters(), lr=learn_rate)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1) #选定调整方法
torch.optim.lr_scheduler.MultiStepLR
是 PyTorch 中的一个学习率调整策略,它在训练过程中按照指定的里程碑(milestones)调整学习率。具体地,每当当前训练 epoch 数量等于里程碑中的某个值时,就将学习率乘以 gamma 的值。
下面是 MultiStepLR
的构造函数签名及参数说明:
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1, verbose=False)
optimizer(Optimizer)
:是之前定义好的需要优化的优化器的实例名。milestones(list)
:是一个关于epoch数值的list,表示在达到哪个epoch范围内开始变化,必须是升序排列;由递增整数构成的列表,表示要在哪些 epoch 时降低学习率。例如,如果设置为 [30, 80]
,则在第 30 和第 80 个 epoch 时学习率会被降低。gamma
:乘法因子,用于计算新的学习率。默认值为 0.1。last_epoch
:上一个 epoch 的索引。默认为 -1,表示初始学习率为初始 lr。verbose
:如果为 True
,则会打印出有关调整学习率的详细信息。默认为 False
。使用 MultiStepLR
可以很容易地实现学习率的衰减,例如:
import torch.optim as optim
import torch.optim.lr_scheduler as lr_scheduler
# 构建优化器和 MultiStepLR 学习率衰减策略
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
milestones = [30, 80]
scheduler = lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1)
for epoch in range(100):
# 训练模型
train(...)
# 更新学习率
scheduler.step()
# 验证模型
validate(...)
这里,使用 optim.SGD
构建了一个随机梯度下降优化器,并将其传递给 MultiStepLR
。然后,定义了里程碑 [30, 80]
和乘法因子 0.1,并将它们传递给 MultiStepLR
的构造函数。在训练过程中,先进行模型训练,然后调用 scheduler.step()
方法更新学习率。因为设置了里程碑为 30 和 80,所以当 epoch 数量分别为 30 和 80 时,学习率会被乘以 0.1。
在特定的 epoch 中调整学习率
用法示例:
optimizer = torch.optim.SGD(net.parameters(), lr=0.001 )
scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,
milestones=[2,6,15], #调整学习率的epoch数
gamma=0.1)
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler = ExponentialLR(optimizer, gamma=0.9)
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()
scheduler.step()
更多的官方动态学习率设置方式可参考:https://pytorch.org/docs/stable/optim.html