pytorch框架自动调整学习率的几种方式

本文详细介绍了PyTorch中动态调整学习率的多种策略,包括指数衰减(ExponentialLR)、多步调整(MultiStepLR)、余弦周期调整(CosineAnnealingLR)和监控指标调整(ReduceLRonPlateau)。通过实例展示了这些策略如何影响网络训练过程,如学习率变化曲线和损失曲线。同时,文章还提到了自定义函数调整学习率(LambdaLR)的方法及其效果。

一、前言

  学习率要在收敛和收敛速度中做出权衡,合适的学习率能以最快速度逼近最优解同时使得损失不断下降。在复杂网络中,固定的学习率一般无法得到网络的最优解,动态调整学习率或对模型不同部分设置不同的学习率已成为一种训练模型的趋势趋势。

二、Pytorch中自动调整学习率的几种方式

 2.1 ExponentialLR-指数衰减方式

torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma,last_epoch=-1)

    其中,optimizer为指定的优化器, γ \gamma γ为指数的底数,通常将 γ \gamma γ设置为接近于1的数。
    学习率更新公式如下所示:
l r n e w = l r i n i t ∗ γ e p o c h lr_{new}=lr_{init}*\gamma^{epoch} lrnew=lrinitγepoch    其中, l r i n i t lr_{init} lrinit为初始学习率, l r n e w lr_new lrnew为更新后的学习率, e p o c h epoch epoch为当前训练迭代次数。

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from torch.optim.lr_scheduler import ExponentialLR
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
plt.rcParams['font.sans-serif'] = 'SimHei'         # 显示中文
plt.rcParams['axes.unicode_minus'] = False         # 显示负号
SEED = 40                                          # 设置随机种子,使得每次运行时产生的随机数一致


# 构建网络
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.linear = nn.Linear(50, 100)
        self.leakrelu = nn.LeakyReLU(0.001)
        self.linear1 = nn.Linear(100, 50)
    # 前向传播
    def forward(self, input):
        x = self.leakrelu(self.linear(input))
        output = self.leakrelu(self.linear1(x))
        return output

lr = []                              # 保存每个epoch的学习率
epochTrainLoss = []                  # 保存每个epoch的训练损失
epochValLoss = []                    # 保存每个epoch的校验损失
maxepoch = 50
torch.manual_seed(SEED)
if torch.cuda.is_available():
    torch.cuda.manual_seed(SEED)

# 产生训练所需数据
input_train = torch.randn(10, 50)      # 训练输入数据
target_train = torch.randn(10, 50)     # 训练标签
input_val = torch.randn(10, 50)        # 校验输入数据
target_val = torch.randn(10, 50)       # 校验所用标签

net = Net()                          # 初始化网络
optimizer = torch.optim.Adam(net.parameters(), lr=0.01)   # 初始化优化器-Adam
scheduler = ExponentialLR(optimizer, gamma=0.9)          # 以指数方式调整学习率
loss_fn = torch.nn.MSELoss()         # 初始化损失函数
loss_fn.to(DEVICE)


# 训练模型
for epoch in range(maxepoch):
    lr.append(scheduler.get_last_lr()[0])
    print(epoch, scheduler.get_last_lr()[0])
    # 将训和校验数据和模型加载到device中
    net = net.to(DEVICE)
    input_train = input_train.to(DEVICE)
    target_train = target_train.to(DEVICE)
    input_val = input_val.to(DEVICE)
    target_val = target_val.to(DEVICE)

    net.train()                 # 进入训练模式
    net.zero_grad()             # 将上一次训练保存的梯度清零
    output = net(input_train)   # 将输入数据输入到模型中
    trainLoss = loss_fn(output, target_train)         # 计算训练损失
    trainLoss.backward()        # 反向传播
    epochTrainLoss.append(trainLoss.cpu().detach().numpy())
    optimizer.step()            # 更新模型参数
    scheduler.step()            # 更新学习率

    net.eval()                  # 进入测试模式
    with torch.no_grad():       # 不考虑梯度
        output_val = net(input_val)
        valLoss = loss_fn(output_val, target_val)     # 校验损失
        epochValLoss.append(valLoss.cpu().detach().numpy())
    print("epoch = %02d  trainLoss = %.4f valLoss = %.4f" % (epoch, trainLoss, valLoss))

# 绘制学习率变化曲线图
plt.figure()
x = list(range(maxepoch))
plt.plot(x, lr)
plt.xlabel('epochs')
plt.ylabel('lr')
plt.show()

# 绘制损失曲线图
plt.figure()
plt.plot(x, epochTrainLoss)
plt.plot(x, epochValLoss)
plt.legend(['trainLoss','valLoss'])
plt.xlabel('epochs')
plt.ylabel('Loss')
plt.show()

 2.2 ExponentialLR方式对网络训练的影响

   (1) 学习率按照ExponentialLR方式衰减,初始参数如下所示:
     1) 初始学习率 l r i n i t = 0.1 lr_{init}=0.1 lrinit=0.1
     2) ExponentialLR参数 γ = 0.9 \gamma=0.9 γ=0.9

   (2) 学习率为固定常数
     1) 初始学习率 l r i n i t = 0.01 lr_{init}=0.01 lrinit=0.01
     2) ExponentialLR参数 γ = 1 \gamma=1 γ=1

 2.3 MultiStepLR-按给定间隔调整学习率

torch.optim.lr_scheduler.MultiStepLR(optimizer,milestones,gamma,last_epoch=-1)

    其中,optimizer为指定的优化器,milestones为指定衰减区间, γ \gamma γ为指数的底数,通常将 γ \gamma γ设置为接近于1的数。当 m i l e s t o n e s = [ x 1 , x 2 ] milestones=[x_{1}, x_{2}] milestones=[x1,

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值