问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

PyTorch学习率调整策略详解与实战

创作时间:
作者:
@小白创作中心

PyTorch学习率调整策略详解与实战

引用
CSDN
1.
https://blog.csdn.net/samurais/article/details/145488189

在深度学习中,学习率是影响模型训练效果的重要参数之一。合理地调整学习率可以帮助模型更快地收敛到最优解。本文将介绍PyTorch中常见的学习率调整策略,包括学习率衰减、指数衰减、余弦学习率调节和预热等,并通过一个示例程序展示这些策略的效果。

常见的学习率调节器

学习率衰减

学习率衰减是一种常见的策略,通常在训练过程中逐渐降低学习率。这有助于在训练初期快速收敛,同时在后期进行更精细的调整。

指数衰减

指数衰减法通过一个衰减率来控制学习率的下降速度。每次迭代时,学习率都会乘上一个固定的衰减因子。

余弦学习率调节

余弦学习率调节通过余弦函数来控制学习率的变化。这种方法可以使学习率在训练过程中呈现出周期性的变化,有助于模型跳出局部最优解。

预热

预热策略在训练初期使用较小的学习率,随着训练的进行逐渐增加学习率。这有助于模型在初期更好地适应数据分布。

示例程序

下面以指数衰减调节器(ExponentialLR)为例,展示在相同数据条件下,不使用学习率调节器和使用学习率调节器两种情况下损失函数的收敛情况。

import torch
torch.manual_seed(777)
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
from torch.utils.data import random_split

# 生成数据
def f(x, y):
    return x**2 + 2*y**2

num_samples = 1000
X = torch.rand(num_samples)
Y = torch.rand(num_samples)
Z = f(X, Y) + 3 * torch.randn(num_samples)

dataset = torch.stack([X, Y, Z], dim=1)

train_size = int(0.7 * len(dataset))
test_size = len(dataset) - train_size
train_dataset, test_dataset = random_split(dataset=dataset, lengths=[train_size, test_size])

train_dataloader = DataLoader(TensorDataset(train_dataset.dataset.narrow(1, 0, 2), train_dataset.dataset.narrow(1, 2, 1)), batch_size=32, shuffle=False)
test_dataloader = DataLoader(TensorDataset(test_dataset.dataset.narrow(1, 0, 2), test_dataset.dataset.narrow(1, 2, 1)), batch_size=32, shuffle=False)

# 模型定义
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(2, 8)
        self.output = nn.Linear(8, 1)
        
    def forward(self, x):
        x = torch.relu(self.hidden(x))
        return self.output(x)

# 模型训练
num_epochs = 100
learning_rate = 0.1

loss_fn = nn.MSELoss()

for with_scheduler in [False, True]:
    train_losses = []
    test_losses = []
    
    model = Model()
    optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer=optimizer, gamma=0.99)
    
    for epoch in range(num_epochs):
        model.train()
        train_loss = 0
        
        for inputs, targets in train_dataloader:
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = loss_fn(outputs, targets)
            loss.backward()
            optimizer.step()
            
            train_loss += loss.item()
        train_loss /= len(train_dataloader)
        train_losses.append(train_loss)
        
        model.eval()
        test_loss = 0
        with torch.no_grad():
            for inputs, targets in test_dataloader:
                outputs = model(inputs)
                loss = loss_fn(outputs, targets)
                test_loss += loss.item()
            test_loss /= len(test_dataloader)
            test_losses.append(test_loss)
        
        if with_scheduler:
            scheduler.step()
    
    plt.figure(figsize=(8, 4))
    plt.plot(range(num_epochs), train_losses, label="Train")
    plt.plot(range(num_epochs), test_losses, label="Test")
    plt.title("{0} lr_scheduler".format("With " if with_scheduler else "Without"))
    plt.legend()
    plt.show()

执行结果

没有使用学习率自动调节时

使用了学习率自动调节

结论

使用学习率自动调节器可以显著提高模型的收敛速度。从实验结果可以看出,在使用指数衰减调节器的情况下,模型的训练误差和测试误差都比没有使用调节器时更快地收敛到较低的水平。

常见学习率调节器实现

  • 学习率衰减:每训练一定次数就将学习率降低为原来的一半

    scheduler = torch.optim.lr_scheduler.StepLR(optimizer=optimizer, step_size=100, gamma=0.5)
    
  • 指数衰减法:每次迭代将学习率乘上一个衰减率

    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer=optimizer, gamma=0.99)
    
  • 余弦学习率调节:optimizer 初始学习率为最大学习率,eta_min 是最小学习率,T_max 是最大的迭代次数

    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer=optimizer, T_max=100, eta_min=0.00001)
    
  • 自定义学习率:通过一个 lambda 函数自定义实现学习率调节器

    scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer=optimizer, lr_lambda=lambda epoch: 0.99 ** epoch)
    
  • 预热:在训练初期使用较小的学习率,逐渐增加

    warmup_steps = 20
    scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer=optimizer, lr_lambda=lambda t: min(t/warmup_steps, 0.001))
    
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号