目录
一、使用最优模型
1、什么是最优模型
在深度学习中,最优模型指的是在给定的任务上具有最好性能的模型。最优模型通常通过最小化损失函数来确定,该损失函数能够衡量模型在训练数据上的预测结果与真实结果之间的差异。
最优模型具有较低的训练误差和有效的泛化能力,能够在未见过的测试数据上表现良好。为了找到最优模型,通常会使用优化算法,如梯度下降算法,来更新模型的参数,直到找到损失函数的最小值。最优模型的选择通常基于多个因素,如训练数据的质量和数量,模型的复杂性和计算资源的限制。
2、如实使用最优模型
上节课我们已经通过寻找最优模型得到了当前训练的最优参数的模型,然后将这个模型保存在pt、pth、t7文件中,如下所示:
1)读取参数方法
model = CNN().to(device)
model.load_state_dict(torch.load("best.path")) # 调用仅包含权重参数和偏置的模型
2)调用完整模型方法
# 2、读取完整模型的方法,无需提前创建model
# model = CNN().to(device) # 将模型传入GPU,device为前面判断的
model = torch.load('best.pt') # 调用前面保存的完整模型
3)实例
依旧是上节课的数据,如下所示,代码只需小改一下即可
完整代码:
import numpy as np
from torch.utils.data import Dataset,DataLoader
import torch
import torch.nn as nn
from PIL import Image
from torchvision import transforms
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
from torch import nn
class CNN(nn.Module):
def __init__(self):
super(CNN,self).__init__()
self.conv1=nn.Sequential(nn.Conv2d(in_channels=3,
out_channels=16,
kernel_size=5,
stride=1,
padding=2)
,nn.ReLU()
,nn.MaxPool2d(kernel_size=2)
)
self.conv2=nn.Sequential(
nn.Conv2d(16,32,5,1,2),
nn.ReLU(),
nn.Conv2d(32, 32, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.conv3=nn.Sequential(
nn.Conv2d(32,64,5,1,2),
nn.ReLU())
self.out = nn.Linear(64*64*64,20)
def forward(self,x):
x = self.conv1(x)
x = self.conv2(x)
x = self.conv3(x)
x = x.view(x.size(0),-1)
output = self.out(x)
# output = torch.sigmoid(x)
return output
# model = CNN().to(device)
# 提取模型的两种方法
# 1、读取参数的方法
# model = CNN().to(device)
# model.load_state_dict(torch.load("best.path")) # 调用仅包含权重参数和偏置的模型
# 2、读取完整模型的方法,无需提前创建model
# model = CNN().to(device) # 将模型传入GPU,device为前面判断的
model = torch.load('best.pt') # 调用前面保存的完整模型
model.eval() # 固定模型参数和数据,防止后面被修改
# 数据增强
data_transforms={
'train':transforms.Compose([
transforms.Resize([256,256]),
transforms.RandomRotation(45),#随机旋转,-45到45度
# transforms.CenterCrop(256),#从中心裁剪240*240
transforms.RandomHorizontalFlip(p=0.5),#随机水平翻转
transforms.RandomVerticalFlip(p=0.5),#随机垂直翻转
transforms.ColorJitter(brightness=0.2,contrast=0.1,saturation=0.1,hue=0.1),
transforms.RandomGrayscale(p=0.1),#转换为灰度图
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])
]),
'valid':transforms.Compose([
transforms.Resize([256,256]),
transforms.ToTensor(),
transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
}
# 取出数据
class food_dataset(Dataset): # food_dataset是自己创建的类名称,可以改变你需要的名称
def __init__(self,file_path,transform=None):
self.file_path=file_path
self.imgs=[]
self.labels=[]
self.transform=transform
with open(self.file_path) as f:
samples=[x.strip().split(' ') for x in f.readlines()]
for sample in samples:
self.imgs.append(sample[0])
self.labels.append(sample[1:])
def __len__(self):
return len(self.imgs)
def __getitem__(self, idx):
image=Image.open(self.imgs[idx])
if self.transform:
image=self.transform(image)
label=self.labels[idx]
label=torch.from_numpy(np.array(label,dtype=np.float64))
return image,label
# 取出图片数据后对其进行打包
test_data = food_dataset(file_path='./testda.txt',transform = data_transforms['valid'])
test_dataloader = DataLoader(test_data,batch_size=1,shuffle=True)
#
result=[] # 保存的预测结果
labels=[] # 真实结果
def test_true(dataloader,model):
with torch.no_grad(): # 上下文管理器,关闭梯度运算
for x,y in dataloader: # 遍历打包好的图片及其标签
x,y = x.to(device),y.to(device) # 将其传入GPU
pred = model.forward(x) # 前向传播
result.append(pred.argmax(1).item()) # 将预测值的结果转换成python变量然后增加到列表
labels.append(y.item()) # 同时将真实值的标签转变成python标量然后存入labels列表
test_true(test_dataloader,model) # 导入数据和模型
print('预测值:\t',result)
print('真实值:\t',labels)
打印结果:
二、调整学习率
1、什么是调整学习率
学习率是优化算法中一个重要的超参数,用于控制模型参数在每次更新时的调整幅度。学习率决定了模型在参数空间中搜索的步长大小。调整学习率是指在训练过程中根据需要改变学习率的值。
常用的学习率有0.1、0.01以及0.001等,学习率越大则权重更新越快。一般来说,我们希望在训练初期学习率大一些,使得网络收敛迅速,在训练后期学习率小一些,使得网络更好的收敛到最优解。
2、目的
调整学习率的目的是为了能够更好地优化模型,避免训练过程中出现的一些问题,如梯度爆炸或梯度消失、训练过程陷入局部极小值等
3、调整学习率的方法
PyTorch学习率调整策略通过torch.optim.lr_sheduler接口实现,下图可发现不同方法调整学习率所对应的横轴epoch值与纵轴学习率的关系
1)有序调整
等间隔调整step、多间隔调整MultiStep、指数衰减Exponential、余弦退火CosineAnnealing
"""等间隔调整"""
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1)
# optimizer: 神经网络训练中使用的优化器,
# 如optimizer = torch.optim.Adam(model.parameters(),lr=0.001)
# step_size(int): 学习率下降间隔数,单位是epoch,而不是iteration.
# gamma(float):学习率调整倍数,默认为0.1
# 每训练step_size个epoch,学习率调整为lr=lr*gamma.
"""多间隔调整调整"""
torch.optim.lr_shceduler.MultiStepLR(optimizer, milestones, gamma=0.1)
# milestone(list): 一个列表参数,表示多个学习率需要调整的epoch值,
# 如milestones=[10, 30, 80],即10轮时将gamma乘以学习率lr,30轮时、80轮时、、
"""指数衰减"""
torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma)
# gamma(float):学习率调整倍数的底数,指数为epoch,初始值我lr, 倍数为γepoch,每一轮都调整
"""余弦退火"""
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0)
# Tmax(int):学习率下降到最小值时的epoch数,即当epoch=T_max时,学习率下降到余弦函数最小值,# 当epoch>T_max时,学习率将增大;
# etamin: 学习率调整的最小值,即epoch=Tmax时,lrmin=etamin, 默认为0.
2)自适应调整
依训练状况伺机而变,通过检测某个指标的变化情况(如loss、accuracy),当该指标不怎么变化时,就是调整学习率的时机。
"""根据指标调整学习率"""
torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1,patience=10,verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
参数解析
- optimizer:是优化器,例如SGD、Adam等。
- mode:用于指示评估指标的变化方向。"min"表示评估指标越小越好,"max"表示评估指标越大越好。
- factor:学习率缩放因子,每次调整学习率时,将学习率乘以factor。
- patience:在模型没有显著改善时,经过多少个epoch才进行调整。
- verbose:是否打印每次学习率调整的信息。
- threshold:评估指标的变化阈值,控制何时进行学习率调整。
- threshold_mode:用于指示threshold是"rel"相对于最好的评估指标还是"abs"绝对值。
- cooldown:在学习率调整之后,经过多少个epoch才恢复正常操作。
- min_lr:学习率的下限,不会再低于该值。
- eps:一个很小的值,用于避免除以零错误。
3)自定义调整
通过自定义关于epoch的lambda函数调整学习率lambdaLR
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda)
# lr_lambda(function or list): 自定义计算学习率调整倍数的函数,通常时epoch的函数,当有多个参数组时,设为list.
4、案例使用
只需将上节课中训练模型的代码拿过来更改最后一小部分即可,首先在创建交叉熵损失函数下再创建一个更改学习率的接口,然后在进行每轮的训练时插入这个接口即可。
loss_fn = nn.CrossEntropyLoss() # 创建交叉熵损失雨数对象
optimizer = torch.optim.Adam(model.parameters(),lr=0.001) #创建一个优化器,一开始lr可以大一些
scheduler = torch.optim.lr_scheduler.StepLR(optimizer,step_size=5,gamma=0.5) # 调整学习率
"""optimizer是一个PyTorch优化器对象
step_size表示学习率调整的步长
gamma表示学习率的衰减因子,即每次调整后将当前学习率乘以gamma
"""
"""训练模型"""
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)
epochs = 80
acc_s = []
loss_s = []
for t in range(epochs):
print(f"Epoch {t+1}\n---------------------------")
train(train_dataloader,model,loss_fn,optimizer)
test(test_dataloader, model, loss_fn)
scheduler.step()
print(bast_acc)
前面部分的代码可以参考之前的博客,如下链接
标签:卷积,self,torch,学习,神经网络,lr,model,模型 From: https://blog.csdn.net/qq_64603703/article/details/142514756