pytorch学习率设置——optimizer.param_groups、对不同层设置学习率、动态调整学习率

系列文章目录

pytorch优化器——add_param_group()介绍及示例、Yolov7 优化器代码示例
pytorch学习率设置——optimizer.param_groups、对不同层设置学习率、动态调整学习率
PyTorch学习——关于tensor、Variable、nn.Parameter()、叶子节点、非叶子节点、detach()函数、查看网络层参数
PyTorch model 返回函数总结——model.state_dict(),model.modules(),model.children(),model.parameters()
PyTorch模型参数初始化(weights_init)——torch.nn.init、加载预权重


文章目录

  • 系列文章目录
  • 前言
    • 1、关于optimizer.param_groups
    • 2、设置学习率
    • 3、optim 提供的优化器


前言

我的需求:我需要在yolov7中更改其中一层的学习率,但yolov7的学习率是随着eporch的变化动态变化的。


1、关于optimizer.param_groups

“param_groups” 是 Pytorch 中优化器 Optimizer 的一个属性,它是一个列表,其中的每个元素都是一个字典,表示优化的参数组。每个字典都包含了一组参数的各种信息,如当前的学习率、动量等。这个属性可以用来获取优化器中当前管理的参数组的信息,也可以用来修改优化器的参数设置。
param_groups中的一些参数介绍:
[‘param’,‘lr’,‘momentum’,‘dampening’,‘weight_decay’,‘nesterov’]
params(iterable)—待优化参数w、b 或者定义了参数组的dict
lr(float,可选)—学习率
momentum(float,可选,默认0)—动量因子
weight_decay(float,可选,默认0)—权重衰减
dampening (float, 可选) – 动量的抑制因子(默认:0)
nesterov (bool, 可选) – 使用Nesterov动量(默认:False)

2、设置学习率

查看优化器完整参数:

print(optimizer.state_dict()["param_groups"])

查看学习率:

print("Lr:{}".format(optimizer.state_dict()['param_groups'][0]['lr']))

以下是我测试的网络模型:

class resnet18(torch.nn.Module):def __init__(self):super(resnet18, self).__init__()self.block1 = torch.nn.Sequential(torch.nn.Conv2d(1, 10, 5),torch.nn.MaxPool2d(2),torch.nn.ReLU(True),torch.nn.BatchNorm2d(10),)self.block2 = torch.nn.Sequential(torch.nn.Conv2d(10, 20, 5),torch.nn.MaxPool2d(2),torch.nn.ReLU(True),torch.nn.BatchNorm2d(20),)self.fc = torch.nn.Sequential(torch.nn.Flatten(),torch.nn.Linear(320, 10))def forward(self, x):x = self.block1(x)x = self.block2(x)x = self.fc(x)return xmodel = resnet18()

设置优化器、学习率:

optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.5)

对网络的不同块设置学习率:

optimizer = torch.optim.SGD([{"params":model.block1.parameters()},{"params":model.block2.parameters(),"lr":0.08},{"params":model.fc.parameters(),"lr":0.09},],lr=0.1, #默认参数)

对网络的不同层设置学习率:

# 提取指定层对象
special_layers = torch.nn.ModuleList([model.block1[0], model.block2[3]])
# 获取指定层参数id
special_layers_params = list(map(id, special_layers.parameters()))
# 获取非指定层的参数id
base_params = filter(lambda p: id(p) not in special_layers_params, model.parameters())optimizer = torch.optim.SGD([{'params': base_params},{'params': special_layers.parameters(), 'lr': 0.1}], lr=0.11)

动态调整学习率:

动态调整学习率 模型学习率必须为以全局的(也就是模型的学习率只能有一个比如全局设为0.5)

def adjust_learning_rate(optimizer, epoch, start_lr):lr = start_lr * (0.9 ** (epoch // 1))    # 每1个eporch学习率改变为上一个eporch的 0.9倍for param_group in optimizer.param_groups:param_group['lr'] = lr

动态调整学习率 网络模型学习率可以有多个

start_lr = [0.11,0.1]  # 不同层的初始学习率
def adjust_learning_rate(optimizer, epoch, start_lr):for index, param_group in enumerate(optimizer.param_groups):lr = start_lr[index] * (0.9 ** (epoch // 1))    # 每1个eporch学习率改变为上一个eporch的 0.9倍param_group['lr'] = lr

以上两个函数需要放在eporch的for循环中进行迭代,每一个eporch调整一次。如下我放在了train函数里。
在这里插入图片描述
以上的总代码:
代码是以resnet18分类手写数字体识别mini数据集为例,分别对不同的层设置了学习率,带动态调整,每经过一个eporch,学习率调整为上一个eporch的0.9倍。

import torch
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision import transforms
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np
import os  # 添加代码①
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"  # 添加代码②batch_size = 256    #设置batch大小
transform = transforms.Compose([transforms.ToTensor(),                        #转换为张量transforms.Normalize((0.1307,), (0.3081,))    #设定标准化值
])
#训练集
train_dataset = datasets.MNIST(root='../data/mnist',train=True,transform=transform,download=True)
#测试集
test_dataset = datasets.MNIST(root='../data/mnist',train=False,transform=transform,download=True)#训练集加载器
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size,shuffle=True)
#测试集加载器
test_loader = DataLoader(dataset=test_dataset,batch_size=batch_size, shuffle=False)class resnet18(torch.nn.Module):def __init__(self):super(resnet18, self).__init__()self.block1 = torch.nn.Sequential(torch.nn.Conv2d(1, 10, 5),torch.nn.MaxPool2d(2),torch.nn.ReLU(True),torch.nn.BatchNorm2d(10),)self.block2 = torch.nn.Sequential(torch.nn.Conv2d(10, 20, 5),torch.nn.MaxPool2d(2),torch.nn.ReLU(True),torch.nn.BatchNorm2d(20),)self.fc = torch.nn.Sequential(torch.nn.Flatten(),torch.nn.Linear(320, 10))def forward(self, x):x = self.block1(x)x = self.block2(x)x = self.fc(x)return xmodel = resnet18()device=torch.device("cuda:0"if torch.cuda.is_available()else"cpu")#使用GPU进行计算
model.to(device)#把model模型放进去
#---------------------------------------------------------------------# 
# 构造损失函数和优化函数
# 损失
criterion = torch.nn.CrossEntropyLoss()
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
# 运行时,以下几个optimizer留一个就好# 设置学习率 全局学习率0.1
#optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.5)# 分块设置学习率
# optimizer = torch.optim.SGD([
#         {"params":model.block1.parameters()},
#         {"params":model.block2.parameters(),"lr":0.08},
#         {"params":model.fc.parameters(),"lr":0.09},],
#         lr=0.1, #默认参数
#     )# 对不同层设置学习率
special_layers = torch.nn.ModuleList([model.block1[0], model.block2[3]]) # 提取指定层对象
special_layers_params = list(map(id, special_layers.parameters())) # 获取指定层参数id
base_params = filter(lambda p: id(p) not in special_layers_params, model.parameters()) # 获取非指定层的参数id
optimizer = torch.optim.SGD([{'params': base_params},{'params': special_layers.parameters(), 'lr': 0.1}], lr=0.11)#---------------------------------------------------------------------# 
# 动态调整学习率 模型学习率必须为以全局的(也就是模型的学习率只能有一个比如全局设为0.5# def adjust_learning_rate(optimizer, epoch, start_lr):
#     lr = start_lr * (0.9 ** (epoch // 1))    # 每1个eporch学习率改变为上一个eporch的 0.9倍
#     for param_group in optimizer.param_groups:
#         param_group['lr'] = lr# 动态调整学习率 网络模型学习率可以有多个
start_lr = [0.11,0.1]  # 不同层的初始学习率
def adjust_learning_rate(optimizer, epoch, start_lr):for index, param_group in enumerate(optimizer.param_groups):lr = start_lr[index] * (0.9 ** (epoch // 1))    # 每1个eporch学习率改变为上一个eporch的 0.9倍param_group['lr'] = lr
#---------------------------------------------------------------------#
def train(epoch):adjust_learning_rate(optimizer, epoch, start_lr)  # 动态调整学习率print("Lr:{}".format(optimizer.state_dict()['param_groups'][0]['lr']))  # 查看学习率print("Lr:{}".format(optimizer.state_dict()['param_groups'][1]['lr']))
#     print("Lr:{}".format(optimizer.state_dict()['param_groups'][2]['lr']))
#     print(optimizer.state_dict()["param_groups"])  # 查看优化器完整参数running_loss = 0.0        #每一轮训练重新记录损失值for batch_idx, data in enumerate(train_loader, 0):    #提取训练集中每一个样本inputs, target = data        inputs, target = inputs.to(device), target.to(device)  # 这里的数据(原数据)也要迁移过去# outputs输出为0-9的概率  256*10outputs = model(inputs)              #代入模型loss = criterion(outputs, target)    #计算损失值loss.backward()                      #反向传播计算得到每个参数的梯度值optimizer.step()                     #梯度下降参数更新optimizer.zero_grad()                #将梯度归零running_loss += loss.item()          #损失值累加if batch_idx % 300 == 299:           #每300个样本输出一下结果print('[%d,%5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))running_loss = 0.0          # (训练轮次,  该轮的样本次,  平均损失值)return running_lossdef test():correct = 0total = 0with torch.no_grad():            #执行计算,但不希望在反向传播中被记录for data in test_loader:     #提取测试集中每一个样本images, labels = dataimages, labels = images.to(device), labels.to(device)# outputs输出为0-9的概率  256*10outputs = model(images)  #带入模型# torch.max()这个函数返回的是两个值,第一个值是具体的value(我们用下划线_表示)# 第二个值是value所在的index(也就是predicted)_, pred = torch.max(outputs.data, dim=1)    #获得结果中的最大值total += labels.size(0)                     #测试数++correct += (pred == labels).sum().item()    #将预测结果pred与标签labels对比,相同则正确数++print('%d %%' % (100 * correct / total))    #输出正确率if __name__ == '__main__':# 这两个数组主要是为了画图lossy = []        #定义存放纵轴数据(损失值)的列表epochx = []       #定义存放横轴数据(训练轮数)的列表for epoch in range(10):    #训练10轮epochx.append(epoch)   #将本轮轮次存入epochy列表lossy.append(train(epoch))  #执行训练,将返回值loss存入lossy列表  test()                 #每轮训练完都测试一下正确率path = "D:/code/text/model2.pth"#torch.save(model,path)torch.save(model.state_dict(),path)   # 保存模型model = torch.load("D:/code/text/model2.pth")  # 加载模型#可视化一下训练过程plt.plot(epochx, lossy)plt.grid()plt.show()

结果如下:学习率正常缩小。
在这里插入图片描述

3、optim 提供的优化器

例如:

torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch = -1)

这篇博客总结的很全:http://t.csdn.cn/wXU18



本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部