Pytorch lr_scheduler 调整学习率
背景
在运行 VGG 代码的时候有这么几行代码:
# 定义模型进行训练
model = VGG16()
# model.load_state_dict(torch.load('./my-VGG16.pth'))
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=5e-3)
loss_func = nn.CrossEntropyLoss()
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.4, last_epoch=-1) # todo 了解这个操作!
定义优化器,损失函数我都知道要做,但是突然出现一个 scheduler 我就看不懂是什么了。
这里来了解一下
在PyTorch中,lr_scheduler
是用于调整学习率(Learning Rate)的一个模块,它可以在训练过程中动态地改变学习率,有助于改善模型的训练效果,避免陷入局部最优解,或者加速收敛过程。StepLR
是 lr_scheduler
模块中的一个类,它按照固定的步长(step_size
)来降低学习率。
在你给出的代码片段中:
python复制代码
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.4, last_epoch=-1)
optimizer
:这是你需要调整学习率的优化器对象。在你的例子中,它是通过optim.SGD
创建的,用于VGG16模型的参数优化。step_size
:这个参数定义了学习率更新的周期。在你的例子中,step_size=5
意味着每经过5个epoch(训练周期),学习率就会更新一次。gamma
:这个参数定义了学习率更新的乘法因子。在你的例子中,gamma=0.4
意味着每次学习率更新时,新的学习率将是旧学习率的0.4倍。这有助于在训练过程中逐渐减小学习率,以便在接近最优解时进行更细致的调整。last_epoch
:这个参数用于指示在调用scheduler.step()
之前,已经模拟了多少个epoch的更新。在初次设置时,如果希望从头开始计算(即从epoch 0开始),通常将其设置为-1
。这样,第一次调用scheduler.step()
时,将认为是从epoch 0结束后的状态开始,从而按照step_size
的设置来更新学习率。
在训练循环中,你需要在每个epoch结束后调用 scheduler.step()
来更新学习率。例如:
for epoch in range(num_epochs):
# 训练代码...
# 在每个epoch结束后更新学习率
scheduler.step()
通过这种方式,你可以根据训练过程的需要,灵活地调整学习率,以期获得更好的训练效果。
实际调用:
# 定义训练步骤
total_times = 40
total = 0
accuracy_rate = []
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
for epoch in range(total_times):
model.train()
model.to(device)
running_loss = 0.0
total_correct = 0
total_trainset = 0
print("epoch: ",epoch)
for i, (data,labels) in enumerate(train_loader):
data = data.to(device)
outputs = model(data).to(device)
labels = labels.to(device)
loss = loss_func(outputs,labels).to(device)
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss += loss.item()
_,pred = outputs.max(1)
correct = (pred == labels).sum().item()
total_correct += correct
total_trainset += data.shape[0]
if i % 100 == 0 and i > 0:
print(f"正在进行第{i}次训练, running_loss={running_loss}".format(i, running_loss))
running_loss = 0.0
test()
scheduler.step()
其他调整学习率的方法
在PyTorch中,除了StepLR
之外,还有多种其他方法用于调整学习率。这些方法可以帮助在训练过程中更灵活地控制学习率,以适应不同的训练需求和数据集特性。以下是一些常见的PyTorch学习率调整方法:
- MultiStepLR:
- 功能:按给定间隔调整学习率。
- 主要参数:
milestones
:一个列表,包含需要调整学习率的epoch数。在每个milestones
指定的epoch结束时,学习率会按照给定的gamma
进行调整。gamma
:调整系数,与StepLR
中的gamma
相同,用于计算新的学习率。
- 使用场景:当你知道在特定的epoch点需要调整学习率时,可以使用此方法。
- ExponentialLR:
- 功能:按指数衰减调整学习率。
- 主要参数:
gamma
:指数的底,通常设置为小于1的数(如0.9),用于计算学习率的衰减。
- 使用场景:当希望学习率随着训练的进行逐渐减小,且减小速度呈指数级变化时,可以使用此方法。
- CosineAnnealingLR:
- 功能:余弦周期调整学习率。
- 主要参数:
T_max
:下降周期,表示余弦周期的一半。学习率会在每个T_max
周期内按照余弦函数变化。eta_min
:学习率下限,学习率变化过程中不会低于此值。
- 使用场景:当希望学习率在一个周期内先下降后上升,模拟退火过程时,可以使用此方法。
- ReduceLROnPlateau:
- 功能:监控某个指标(如loss或accuracy),当指标不再改善时调整学习率。
- 主要参数:
mode
:'min'
或'max'
,表示监控的指标是应该最小化还是最大化。factor
:调整系数,用于计算新的学习率。patience
:“耐心”参数,表示在调整学习率之前,指标可以接受连续多少次不改善。cooldown
:“冷却时间”,在调整学习率后,暂停监控一段时间。min_lr
:学习率下限。
- 使用场景:当你想根据模型的实际表现(而非固定的epoch数)来调整学习率时,可以使用此方法。
- LambdaLR
- 功能:使用自定义的lambda函数来调整学习率。
- 主要参数:
lr_lambda
:一个函数或函数列表,用于计算新的学习率。如果传入函数列表,则列表中的每个函数都会独立地应用于每个参数组的学习率。
- 使用场景:当需要实现更复杂的学习率调整策略时,可以使用此方法。
- WarmupLR(注意:这不是PyTorch官方直接提供的一个类,但可以通过自定义实现):
- 功能:在训练初期逐渐增加学习率,以达到预热模型的效果。
- 实现方式:可以通过自定义一个
lr_scheduler
或使用LambdaLR
结合预热函数来实现。 - 使用场景:当模型在训练初期容易因为学习率过大而不稳定时,可以使用此方法。
这些学习率调整方法各有特点,适用于不同的训练场景和需求。在实际应用中,可以根据数据集的特性、模型的复杂度以及训练目标来选择合适的调整方法。