当前位置:   article > 正文

(从0-1带你了解)Pytorch之模型的读取_pytorch 读取模型

pytorch 读取模型

目录

简述

代码实现

导入所需要的库

数据预处理

加载图像数据和标签

GPU的检测

定义卷积神经网络

训练深度学习模型

测试模型的性能

保存最优模型的2种方

提取模型的2种方法

执行测试


简述

我们有时需要把训练好的模型部署到很多不同的设备。在这种情况下,我们可以把内存中训练好的模型参数存储在硬盘上供后续读取使用。

我们想要保存训练好的模型,等需要用来进行图像分类等任务的时候,不经训练,直接加载使用。
这时,可以采用torch.save(model, 'best.pt')保存模型。

代码实现

代码所需文件请点击此处免费下载

train.txt       test.txt

接下来用一个小案例来解释模型的读取

导入所需要的库

  1. import torch #这行代码引入了PyTorch库,可以用于张量计算和神经网络的构建。
  2. #从PyTorch库中引入了Dataset和DataLoader类。Dataset类是用于加载和预处理数据的,而DataLoader则是用于批量加载和打散数据
  3. from torch.utils.data import Dataset,DataLoader
  4. import numpy as np #用于处理数组
  5. from PIL import Image #引入了Pillow库中的Image模块,可以用于处理图像
  6. from torchvision import transforms #这个模块包含了很多用于图像预处理的函数,例如裁剪、旋转、翻转等

数据预处理

  1. data_transforms = {
  2. 'train': #训练集
  3. transforms.Compose([ #transforms.Compose对象的列表,该列表包含一系列的图像转换操作。
  4. transforms.Resize([300,300]), #是图像变换大小
  5. transforms.RandomRotation(45),#随机旋转,-45到45度之间随机选
  6. transforms.CenterCrop(256),#从中心开始裁剪
  7. transforms.RandomHorizontalFlip(p=0.5),#随机水平翻转 选择一个概率概率
  8. transforms.RandomVerticalFlip(p=0.5),#随机垂直翻转
  9. # transforms.ColorJitter(brightness=0.2, contrast=0.1, saturation=0.1, hue=0.1),#参数1为亮度,参数2为对比度,参数3为饱和度,参数4为色相
  10. transforms.RandomGrayscale(p=0.1),#概率转换成灰度率,3通道就是R=G=B
  11. transforms.ToTensor(),
  12. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])#归一化,均值,标准差
  13. ]),
  14. 'valid': #测试集
  15. transforms.Compose([
  16. transforms.Resize([256,256]),
  17. transforms.ToTensor(),
  18. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  19. ]),
  20. }

加载图像数据和标签

  1. class food_dataset(Dataset): #food_dataset是自己创建的类名称,可以改为你需要的名称
  2. ##file_path是包含图像文件路径和标签的文本文件的路径,transform是一个可选的图像转换操作,默认为None
  3. def __init__(self, file_path,transform=None):
  4. self.file_path = file_path
  5. self.imgs = [] #初始化两个空列表,用于存储图像文件路径和对应的标签
  6. self.labels = []
  7. self.transform = transform # 将传入的transform参数存储在类的实例变量transform中
  8. with open(self.file_path) as f:
  9. #读取文件的每一行,去除首尾空格并使用空格分割,形成一个列表。
  10. samples = [x.strip().split(' ') for x in f.readlines()]
  11. #遍历列表中的每个元素,其中img_path是图像文件的路径,label是对应的标签
  12. for img_path, label in samples:
  13. #将图像文件路径添加到self.imgs列表中
  14. self.imgs.append(img_path)
  15. #将标签添加到self.labels列表中
  16. self.labels.append(label)
  17. def __len__(self): #类实例化对象后,可以使用len函数测量对象的个数
  18. return len(self.imgs)
  19. def __getitem__(self, idx): #关键,可通过索引的形式获取每一个图片数据及标签
  20. image = Image.open(self.imgs[idx]) #使用PIL库的Image.open方法打开指定路径的图像文件
  21. if self.transform:
  22. image = self.transform(image)
  23. label = self.labels[idx] #获取与图像对应的标签
  24. #将标签转换为NumPy数组,然后使用torch.from_numpy将其转换为PyTorch张量,并指定数据类型为torch.int64。
  25. label = torch.from_numpy(np.array(label,dtype = np.int64))
  26. return image, label #返回图像和标签的元组
  27. #传入训练数据文件的路径和指定的图像转换操作
  28. training_data = food_dataset(file_path = './train.txt',transform = data_transforms['train'])
  29. #用于测试数据
  30. test_data = food_dataset(file_path = './test.txt',transform = data_transforms['valid'])

GPU的检测

目的:GPU检测的目的是充分利用可用的硬件资源,提高计算性能,并确保代码在不同环境中的稳定运行。这对于深度学习等需要大量计算的应用尤为重要。

  1. device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
  2. print(f"Using {device} device"

运行结果:

定义卷积神经网络

  1. from torch import nn
  2. class CNN(nn.Module):
  3. def __init__(self): # 输入大小 (3, 256, 256)
  4. super(CNN, self).__init__()
  5. self.conv1 = nn.Sequential( #将多个层组合成一起。
  6. nn.Conv2d( #2d一般用于图像,3d用于视频数据(多一个时间维度),1d一般用于结构化的序列数据
  7. in_channels=3, # 图像通道个数,1表示灰度图(确定了卷积核 组中的个数),
  8. out_channels=16,# 要得到几多少个特征图,卷积核的个数
  9. kernel_size=5, # 卷积核大小,5*5
  10. stride=1, # 步长
  11. padding=2, # 一般希望卷积核处理后的结果大小与处理前的数据大小相同,效果会比较好。那padding改如何设计呢?建议stride为1,kernel_size = 2*padding+1
  12. ), # 输出的特征图为 (16, 256, 256)
  13. nn.ReLU(), # relu层
  14. nn.MaxPool2d(kernel_size=2), # 进行池化操作(2x2 区域), 输出结果为: (16, 128, 128)
  15. )
  16. self.conv2 = nn.Sequential( #输入 (16, 128, 128)
  17. nn.Conv2d(16, 32, 5, 1, 2), # 输出 (32, 128, 128)
  18. nn.ReLU(), # relu层
  19. nn.Conv2d(32, 32, 5, 1, 2), # 输出 (32, 128, 128)
  20. nn.ReLU(),
  21. nn.MaxPool2d(2), # 输出 (32, 64, 64)
  22. )
  23. self.conv3 = nn.Sequential( #输入 (32, 64, 64)
  24. nn.Conv2d(32, 64, 5, 1, 2),
  25. nn.ReLU(), # 输出 (64, 64, 64)
  26. )
  27. self.out = nn.Linear(64 * 64 * 64, 20) # 全连接层得到的结果
  28. def forward(self, x):
  29. x = self.conv1(x)
  30. x = self.conv2(x)
  31. x = self.conv3(x)# 输出 (64,64, 32, 32)
  32. x = x.view(x.size(0), -1) # flatten操作,结果为:(batch_size, 64 * 32 * 32)
  33. output = self.out(x)
  34. return output
  35. model = CNN().to(device)
  36. loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
  37. optimizer = torch.optim.Adam(model.parameters(), lr=0.001)#创建一个优化器Adam

训练深度学习模型

  1. def train(dataloader,model,optimizer,loss_fn):
  2. model.train()
  3. for x,y in dataloader: #x,y 分别是图像和标签
  4. x,y = x.to(device),y.to(device) #将数据放入GPU,提高训练结果
  5. pred = model.forward(x) #对x进行前向传播,得到训练模型的预测结果
  6. loss = loss_fn(pred,y) #使用损失函数来计算预测值pred 和 真实标签y 之间的损失
  7. optimizer.zero_grad() # PyTorch 优化器的方法,用于将模型参数的梯度归零,以准备进行新一轮的反向传播。
  8. loss.backward() #执行反向传播,计算模型参数相对于损失的梯度
  9. optimizer.step() #PyTorch 优化器的方法,用于根据梯度更新模型参数,以减小损失

测试模型的性能

  1. best_acc = 0
  2. #dataloader(用于提供测试数据批次的数据加载器)、model(深度学习模型),和 loss_fn(损失函数,用于计算模型的预测与真实标签之间的损失)
  3. def test(dataloader, model, loss_fn):
  4. global best_acc #全局变量 best_acc
  5. size = len(dataloader.dataset) #获取测试数据集的大小,用于计算准确率
  6. num_batches = len(dataloader) #获取数据加载器中批次的数量,用于计算平均损失
  7. model.eval() #将模型设置为评估模式。在评估模式下,模型不会进行训练
  8. test_loss, correct = 0, 0 #初始化测试损失和正确分类的样本数
  9. with torch.no_grad(): #一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。这可以减少计算所用内存消耗。
  10. for X, y in dataloader: # 循环,用于迭代测试数据集中的批次。X 表示图像数据,y 表示标签
  11. X, y = X.to(device), y.to(device)
  12. pred = model.forward(X) #执行前向传播,将输入数据 X 通过深度学习模型 model,并得到模型的预测结果 pred
  13. test_loss += loss_fn(pred, y).item() #计算模型的预测结果 pred 和真实标签 y 之间的损失,并将其累加到 test_loss 变量中
  14. #使用 argmax 函数找到最大概率的类别)和真实标签 y,然后将匹配的结果转换为浮点数类型,累加到 correct 变量中
  15. correct += (pred.argmax(1) == y).type(torch.float).sum().item()
  16. test_loss /= num_batches #计算平均测试损失,将总测试损失除以批次的数量
  17. correct /= size #计算准确率,将正确分类的样本数除以测试数据集的总大小
  18. #印测试结果,包括准确率和平均损失
  19. print(f"Test result: \n Accuracy: {(100*correct)}%, Avg loss: {test_loss}")
  20. acc_s.append(correct)
  21. loss_s.append(test_loss)

保存最优模型的2种方

(模型的文件扩展名一般为:pt)

方法一:

  1. if correct > best_acc:
  2. best_acc = correct
  3. # (w, b) ) 通常用来表示模型的参数,具体指模型的权重 ( w ) 和偏置 ( b )。
  4. # 1、保存模型参数方法:torch.save(model.state_dict(), path)(w,b)
  5. print(model.state_dict().keys()) # 输出模型参数名称
  6. torch.save(model.state_dict(), "model_parameter.pt") #保存模型的参数到名为 "model_parameter.pt" 的文件中

方法二:

  1. # 2、保存完整模型(w,b,模型cnn),
  2. torch.save(model, 'best.pt')

提取模型的2种方法

这里我们不做深度的解析,(详解请点击此处

  1. acc_s = []
  2. loss_s = []
  3. # 提取模型的2种方法:
  4. # 1、读取参数的方法
  5. # model = CNN().to(device)
  6. # model.load_state_dict(torch.load("model_parameter.pt"))
  7. # 2、读取完整模型的方法,无需提前创建model
  8. model = torch.load('best.pt')

执行测试

  1. model.eval() #固定模型参数和数据,防止后面被修改
  2. test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)
  3. test(test_dataloader, model, loss_fn) #执行测试

输出结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/772766
推荐阅读
相关标签
  

闽ICP备14008679号