Pytorch应用训练好的模型

  • 1.保存训练好的模型:torch.save方法
  • 2.加载之前保存的模型:torch.load方法
  • 3.对于分类问题的补充
  • 4.CPU训练完整代码
  • 5.GPU训练方法一
  • 6.GPU训练方法二
  • 7.GPU训练过程的细节优化
  • 8.验证模型

1.保存训练好的模型:torch.save方法

保存训练好的模型有两种方式,第一种保存模型结构且保存模型参数,第一种方式存在一种陷阱,也就是每次加载模型都得把类定义,或者访问类所在的包。保存方式为:

torch.save(模型名, 以pth为后缀的文件)

第二种保存方式只保存模型参数,不保存模型结构,这样可以面对较大的网络模型,可以节省空间,是官方推荐的保存方式,具体为:

torch.save(模型名.state_dict(), 以pth为后缀的文件)

第一个参数,模型名.state_dict()意为只取模型的参数,且以字典方式存储;第二个参数存储模型的地址,一般都用以pth结尾的文件。
代码如下:

import torch
import torchvision
from torch import nnvgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1,模型结构+模型参数
torch.save(vgg16, "vgg16_method1.pth")# 保存方式2,模型参数(官方推荐)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")# 陷阱
class test_Model(nn.Module):def __init__(self):super(test_Model, self).__init__()self.conv1 = nn.Conv2d(3, 64, kernel_size=3)def forward(self, x):x = self.conv1(x)return xtest_model = test_Model()
torch.save(test_model, "test_model_method1.pth")

2.加载之前保存的模型:torch.load方法

对应两种不同的保存模型的方式,也相应地有两种加载模型的方式,第一种方式为:

读取出的模型名 = torch.load(之前保存的模型文件名)

第二种方式为:

读取出的模型名 = torchvision.models.vgg16(pretrained=False)
读取出的模型名.load_state_dict(torch.load(之前保存的模型文件名))

因为第二种方法没有保存模型结构,所以我们要先设计一个模型结构,本例中用的是直接下载VGG16模型结构;然后第二条语句用于将保存的参数值传入到模型结构中。代码如下:

import torch
from model_save import *
import torchvision
from torch import nn# 方式1-》保存方式1,加载模型
model = torch.load("vgg16_method1.pth")
# print(model)# 方式2,加载模型
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
# 只读取参数
# model = torch.load("vgg16_method2.pth")
# print(vgg16)# 方式1,陷阱
# class test_Model(nn.Module):
#     def __init__(self):
#         super(test_Model, self).__init__()
#         self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
#
#     def forward(self, x):
#         x = self.conv1(x)
#         return x
model = torch.load('test_model_method1.pth')
print(model)

3.对于分类问题的补充

对于图像分类、目标检测或是语义分割等各种问题而言,单靠loss曲线还无法完全表现出模型的优劣,而在图像分类问题中,我们常用acc,即在测试集上的正确率来表示模型的训练情况及优劣。

在分类问题中,例如CIFAR10中,某张图片进入模型后的输出结果是形如([0.2, 0.1, 0.4, 0.6, 0.4, 0.4, 0.7, 0.2, 0.5, 0.1]),而targets是类似(5)这样的某个整型数字,表明该图片属于第5类。那么如和将输出结果与targets之间进行计算,产生正确率呢,我们采用argmax函数,该函数会找到数组中最大值并输出最大值的序号,那么如此一来,将输出结果的最大值序号和targets相比较,如果一致则说明该图像识别正确。代码如下:

import torchoutput = torch.tensor([[0.2, 0.3],[0.1, 0.5]])
# 纵向比较
print(output.argmax(0))
# 横向比较
print(output.argmax(1))pred = output.argmax(1)
targets = torch.tensor([0, 1])
print(pred == targets)
# 输出正确的个数
print((pred == targets).sum())

注:因在验证过程中,因为不是一张图片,而是batch_size张图片验证,那么output应是二维数组,第二维的数目是batchsize个,此例中设为2个,相应的targets应是一个一维数组,数组中的每个数表示每张图对应的正确类别是哪类。另外,argmax(0)表示传入的数据纵向进行比较,在本例中是0.2和0.1比,0.3和0.5比;而argmax(1)表示传入的数据横向进行比较,在本例中是0.2和0.3比,0.1和0.5比,毫无疑问,运用在计算准确率中,我们应该使用的是argmax(1),那么记录所有output和targets相吻合的项的和除以总项数即可获得该batch_size的准确率。

4.CPU训练完整代码

CPU训练就是之前介绍的搭建模型和应用模型相结合,内容都是之前所讲,完整代码如下:

import torchvision
from torch.utils.tensorboard import SummaryWriterfrom model import *
# 准备数据集
from torch import nn
from torch.utils.data import DataLoadertrain_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(),download=True)# length 长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)# 创建网络模型
tudui = Tudui()# 损失函数
loss_fn = nn.CrossEntropyLoss()# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10# 添加tensorboard
writer = SummaryWriter("../logs_train")for i in range(epoch):print("-------第 {} 轮训练开始-------".format(i+1))# 训练步骤开始# 这句话在训练开始时调用,在有Dropout层和层起作用,在本例中可不写,但建议写,较为规范tudui.train()for data in train_dataloader:imgs, targets = dataoutputs = tudui(imgs)loss = loss_fn(outputs, targets)# 优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1if total_train_step % 100 == 0:print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))writer.add_scalar("train_loss", loss.item(), total_train_step)# 测试步骤开始# 这句话在测试开始时调用,在有Dropout层和层起作用,在本例中可不写,但建议写,较为规范tudui.eval()total_test_loss = 0# 整体正确个数total_accuracy = 0# 设置测试模型不改变梯度with torch.no_grad():for data in test_dataloader:imgs, targets = dataoutputs = tudui(imgs)loss = loss_fn(outputs, targets)total_test_loss = total_test_loss + loss.item()# 计算正确个数accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的Loss: {}".format(total_test_loss))print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step = total_test_step + 1#此处用的模型保存方式为方式一,建议使用方式二torch.save(tudui, "tudui_{}.pth".format(i))print("模型已保存")writer.close()

5.GPU训练方法一

GPU训练大部分代码与CPU训练一致,调用GPU的方法有两种,第一种方式是在网络模型、损失函数、训练输入数据、测试输入数据四处加入自己 = 自己.cuda即可,即在不同的地方加入以下四句语句:

if torch.cuda.is_available():tudui = tudui.cuda()
if torch.cuda.is_available():loss_fn = loss_fn.cuda()
if torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()
        if torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()
        if torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()

因此第一种GPU训练的完整代码为:

import timeimport torch
import torchvision
from torch.utils.tensorboard import SummaryWriter# from model import *
# 准备数据集
from torch import nn
from torch.utils.data import DataLoadertrain_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(),download=True)# length 长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)# 创建网络模型
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.model = nn.Sequential(nn.Conv2d(3, 32, 5, 1, 2),nn.MaxPool2d(2),nn.Conv2d(32, 32, 5, 1, 2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, 1, 2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(64*4*4, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return x
tudui = Tudui()
if torch.cuda.is_available():print("成功调用GPU")tudui = tudui.cuda()# 损失函数
loss_fn = nn.CrossEntropyLoss()
if torch.cuda.is_available():loss_fn = loss_fn.cuda()
# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10# 添加tensorboard
writer = SummaryWriter("../logs_train")
# 记录最初时间
start_time = time.time()for i in range(epoch):print("-------第 {} 轮训练开始-------".format(i+1))# 训练步骤开始tudui.train()for data in train_dataloader:imgs, targets = dataif torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()outputs = tudui(imgs)loss = loss_fn(outputs, targets)# 优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1if total_train_step % 100 == 0:# 记录结束时间end_time = time.time()print("每100次训练花费时间为:{}秒".format(end_time - start_time))# 重置开始时间start_time = time.time()print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))writer.add_scalar("train_loss", loss.item(), total_train_step)# 测试步骤开始tudui.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs, targets = dataif torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()outputs = tudui(imgs)loss = loss_fn(outputs, targets)total_test_loss = total_test_loss + loss.item()accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的Loss: {}".format(total_test_loss))print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step = total_test_step + 1torch.save(tudui, "tudui_{}.pth".format(i))print("模型已保存")writer.close()

6.GPU训练方法二

GPU第二种训练方式是先定义一个训练的设备,语句为device = torch.device(“cuda”),如果有多张显卡则语句为device = torch.device(“cuda:0”)代表用第0张显卡,要调用其它显卡则将0改成其它数字,然后将训练方法一中的.cuda改为.to(device),例如:

if torch.cuda.is_available():tudui = tudui.cuda()

则完整代码为:

import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter# from model import *
# 准备数据集
from torch import nn
from torch.utils.data import DataLoader# 定义训练的设备
device = torch.device("cuda")train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(),download=True)# length 长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)# 创建网络模型
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.model = nn.Sequential(nn.Conv2d(3, 32, 5, 1, 2),nn.MaxPool2d(2),nn.Conv2d(32, 32, 5, 1, 2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, 1, 2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(64*4*4, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return x
tudui = Tudui()
tudui = tudui.to(device)# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10# 添加tensorboard
writer = SummaryWriter("../logs_train")for i in range(epoch):print("-------第 {} 轮训练开始-------".format(i+1))# 训练步骤开始tudui.train()for data in train_dataloader:imgs, targets = dataimgs = imgs.to(device)targets = targets.to(device)outputs = tudui(imgs)loss = loss_fn(outputs, targets)# 优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1if total_train_step % 100 == 0:print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))writer.add_scalar("train_loss", loss.item(), total_train_step)# 测试步骤开始tudui.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs, targets = dataimgs = imgs.to(device)targets = targets.to(device)outputs = tudui(imgs)loss = loss_fn(outputs, targets)total_test_loss = total_test_loss + loss.item()accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的Loss: {}".format(total_test_loss))print("整体测试集上的正确率: {}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step = total_test_step + 1torch.save(tudui, "tudui_{}.pth".format(i))print("模型已保存")writer.close()

7.GPU训练过程的细节优化

首先,对于网络模型和损失函数,不需要对其重新赋值,也就是说以下代码:

tudui = tudui.to(device)
loss_fn = loss_fn.to(device)
tudui = tudui.cuda()
loss_fn = loss_fn.cuda()

可以直接写为:

tudui.to(device)
loss_fn.to(device)
tudui.cuda()
loss_fn.cuda()

但imgs和targets不能省略前面的赋值。

其次,在方法二中可能出现没有GPU或是GPU未能成功调用,所以可以将代码:

device = torch.device("cuda")

改为:

device = torch.device("cuda" if torch.cuda.isavailable() else "CPU")

如此一来,如果无法调用GPU则会调用CPU训练,而不会报错。

8.验证模型

在训练并测试完之后,如果想要验证模型,类似与测试集的操作,可对某张特定图片或某些图片进行验证,观察其输出是否正确,代码如下:

import torch
import torchvision
from PIL import Image
from torch import nnimage_path = "../imgs/airplane.png"
image = Image.open(image_path)
print(image)
# 该语句是因为不是所有类型的图片都是三通道的,通过这句代码可以将所有类型的通篇都转化成3通道
image = image.convert('RGB')
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),torchvision.transforms.ToTensor()])image = transform(image)
print(image.shape)class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.model = nn.Sequential(nn.Conv2d(3, 32, 5, 1, 2),nn.MaxPool2d(2),nn.Conv2d(32, 32, 5, 1, 2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, 1, 2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(64*4*4, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return x# map_location属性是在,当保存的模型是GPU训练的,而现在我们要用CPU验证时需要添加这样一句话
model = torch.load("tudui_29_gpu.pth", map_location=torch.device('cpu'))
print(model)
image = torch.reshape(image, (1, 3, 32, 32))
model.eval()
with torch.no_grad():output = model(image)
print(output)print(output.argmax(1))

注:因为训练是我们采用是第一种方式保存模型,所有加载模型时我们需要将模型的类再写一次,或者调用定义了模型类的文件;另外注意image = image.convert(‘RGB’)将各种不同的图片转化为三通道;最后注意如果保存的模型是GPU训练的,而现在我们要用CPU验证时需要添加这样一句话model = torch.load(“tudui_29_gpu.pth”, map_location=torch.device(‘cpu’))。

Pytorch应用训练好的模型相关推荐

  1. Pytorch完成基础的模型-线性回归

    Pytorch完成基础的模型-线性回归 1. Pytorch完成模型常用API 在前一部分博文中,实现了通过torch的相关方法完成反向传播和参数更新,在pytorch中预设了一些更加灵活简单的对象, ...

  2. PyTorch | 保存和加载模型教程

    点击上方"算法猿的成长",选择"加为星标" 第一时间关注 AI 和 Python 知识 图片来自 Unsplash,作者: Jenny Caywood 2019 ...

  3. 动手学深度学习(PyTorch实现)(七)--LeNet模型

    LeNet模型 1. LeNet模型 2. PyTorch实现 2.1 模型实现 2.2 获取数据与训练 1. LeNet模型 LeNet分为卷积层块和全连接层块两个部分.下面我们分别介绍这两个模块. ...

  4. Pytorch搭建自己的模型

    前言 PyTorch.TensorFlow都是主流的深度学习框架,今天主要讲解一下如何快速使用pytorch搭建自己的模型.至于为什么选择讲解pytorch,这里我就简单说明一下自己的使用感受(相对T ...

  5. 速成pytorch学习——7天模型层layers

    深度学习模型一般由各种模型层组合而成. torch.nn中内置了非常丰富的各种模型层.它们都属于nn.Module的子类,具备参数管理功能. 例如: nn.Linear, nn.Flatten, nn ...

  6. pytorch多卡并行模型的保存与载入

    pytorch多卡并行模型的保存与载入 当模型是在数据并行方式在多卡上进行训练的训练和保存,那么载入的时候也是一样需要是多卡.并且,load_state_dict()函数的调用要放在DataParal ...

  7. PyTorch的生态和模型部署

    PyTorch的生态和模型部署 1. PyTorch生态 前几章,我们学习了PyTorch的基本使用.能够定义和修改自己的模型.常用的训练技巧和PyTorch的可视化. PyTorch的强大,跟PyT ...

  8. PyTorch参数模型转换为PT模型

    当PyTorch模型需要部署到服务时,为了提升访问速度,需要转换为TRT模型,再进行部署.在转换为TRT模型之前,需要将PyTorch参数模型(如pth.tar)转换为pt模型,使用jit形式.pt模 ...

  9. pytorch从hdfs载入模型、从二进制字符串载入模型

    1,问题描述 离线用torch训练了一个简单的双塔模型,存到了hdfs上,希望可以在spark离线任务中使用.但spark离线任务要载入这个模型,就无法像pytorch官方的模型载入方式(这里:tor ...

最新文章

  1. BZOJ2002 [HNOI2010] 弹飞绵羊
  2. struts基本概念(1)
  3. 在图像中截取小图并保存
  4. P2639 [USACO09OCT]Bessie的体重问题 【背包问题】
  5. 全网首发:麒麟平台更新时提示错误:无法解析域名“archive.kylinos.cn”
  6. linkedin android,如何在android中登录linkedin?
  7. 小程序源码:全新外卖侠cps5.6全套微信小程序源码下载-多玩法安装简单
  8. 解码2022中国网安强星丨构建企业第一重“安全感”,联软科技以零信任重塑网络安全边界
  9. 城市生态规划关键技术方法之六:情景分析方法
  10. html怎么用2个caption不换行,caption怎么用
  11. C# - 获取工程里资源(图片、图标等)
  12. 解决问题(七)——jsf+spring+hibernate整合(一)
  13. Matlab学习——曲柄滑块的运动仿真
  14. 利用抖音Cookie充值接口提取支付链接,调起原生微信h5支付宝h5支付
  15. service mysql k8s_Kubernetes/K8S基础使用方法总结【五】——Service
  16. python输出计算结果_Python学习--02输入和输出、运算符
  17. 8.linux 重定向详解,标准输入输出,输入重定向,输出重定向
  18. 手机短信中特殊字符导致链接失效的问题修复
  19. 威尼斯广场旅游攻略:探访威尼斯的文化中心
  20. 9.18meituan面试总结

热门文章

  1. 101规约单点遥信双点遥信区别
  2. android:gravity=quot;centerquot;,android:layout_gravity=bottom不起作用问题
  3. 如何使用Redis实现电商系统的库存扣减
  4. linux shell脚本编写 | 三角形 | 梯形 | 菱形 | 九九乘法表 | 矩形 | 超详细
  5. 删除 Windows 文件资源管理器左侧 OneDrive 图标
  6. 网络分析仪测试线损_求e5071c网络分析仪校50欧姆阻抗与线损方法,标准...
  7. 保存地理坐标信息的SLIC分割结果
  8. httpd离线安装(含依赖包下载地址)
  9. html5制作坦克大战
  10. linux复制并重命名文件