文章目录

  • 写在前面
  • 实战
    • 分析结构:
    • 代码实现
    • 完善补充1
    • 完善补充2
  • 使用GPU来训练网络
  • 测试模型

写在前面

本系列笔记为pytorch入门学习,所以主要学习使用pytorch框架进行神经网络的实现过程,对于神经网络的基本原理可能不会做过多解释,主要着重于用法。
传送门:
PyTorch入门(一)数据集的一些基础操作
PyTorch入门(二)从零开始搭建一个神经网络
PyTorch入门(三)损失函数与反向传播

实战

那么,现在我们以CIFAR10的网络模型为例子,尝试写一个完整的神经网络
网络架构如图:(这个架构我们在第二篇文章中其实已经写过了,但是这次写的更加完整一些)

分析结构:

有了前面的基础,那么现在我们已经了解了构建网络的步骤了:

  • 准备数据: dataset
  • 加载数据: dataloader
  • 准备模型: 写好网络模型,引入进来
  • 设置损失函数:分类问题一般用交叉熵
  • 设置优化器:
  • 开始训练
  • 验证训练进度:每训练一轮就到测试集上去试试效果
  • 模型保存: 每一轮的训练结果都保存下来

代码实现

这代码都是严格按照上面说的步骤写的,注释也给的很详细。
这就是完整的神经网络训练过程

import torch
import torchvision
from model import * # 引入我们写好的神经网络
from torch import nn
from torch.utils.data import DataLoader
# 全局取消证书验证
import ssl
ssl._create_default_https_context = ssl._create_unverified_context# 准备训练数据集
train_data = torchvision.datasets.CIFAR10("../dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
# 准备测试数据集
test_data = torchvision.datasets.CIFAR10("../dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
# 输出数据集的长度
train_data_size = len(train_data)
test_data_siez = len(test_data)
print("训练数据集的长度:{}".format(train_data_size))
print("测试数据集的长度:{}".format(test_data_siez))# 加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)# 创建网络模型
# 这个网络模型是我们提前写好的 写在model.py文件里面 所以from model import *
test = Network()# 创建损失函数
loss_fn = nn.CrossEntropyLoss()# 构造优化器
# 这里我们选择的优化器是SGD 随机梯度下降 传入模型参数和学习速率
learning_rate = 0.01
optimizer = torch.optim.SGD(test.parameters(),lr=learning_rate)# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 记录训练的轮数
epoch = 10# 开始训练
for i in range(epoch):print("开始第{}轮训练".format(i+1))# 遍历训练集for data in train_dataloader:imgs,targets = data # 取出图像和targetoutputs = test(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))# 当一次训练结束之后 我们就让他在测试数据集上验证一下# 这样就知道模型是否训练好了 是否符合我们的要求了# 测试步骤total_test_loss = 0 # 用来记录模型在全部测试数据上的loss之和with torch.no_grad():"""在使用pytorch时,并不是所有的操作都需要进行计算图的生成(计算过程的构建,以便梯度反向传播等操作)。而对于tensor的计算操作,默认是要进行计算图的构建的,在这种情况下,可以使用 with torch.no_grad():,强制之后的内容不进行计算图构建。"""for data in test_dataloader:imgs,targets = dataoutputs = test(imgs)loss = loss_fn(outputs,targets)total_test_loss = total_test_loss + lossprint("测试集上的loss:{}".format(total_test_loss))# 把每一轮训练得到的结果保存下来torch.save(test,"result_model_{}.pth".format(i))print("模型已保存")

这里面引入的神经网络,是我们提前写好的,放在moudel.py文件里面

import torch
from torch import nn# 搭建神经网络
class Network(nn.Module):def __init__(self):super(Network, self).__init__()self.model1 = nn.Sequential(nn.Conv2d(3, 32, 5, padding=2),# 卷积层nn.MaxPool2d(2), # 池化层nn.Conv2d(32, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10),)def forward(self,x):x = self.model1(x)return xif __name__ == '__main__':# 实例化这个网络test = Network()# 测试一下网络 查看输出结果是否符合要求input = torch.ones((64,3,32,32))output = test(input)print(output.shape)

完善补充1

我们在训练的过程中,每一轮都进行了测试,看看训练结果在测试集上的loss表现。不过呢,我们这是一个分类网络,目的是为了识别图像类别,那么其实我们可以把识别率这个指标也展示出来。之所以上面没写,是因为这不是所有网络都需要的步骤,不同的任务我们做出不同的操作,对于这个分类任务,我们可以在验证的时候,给出识别率来,这样更加清晰。
如何得到准确率呢?
需要用到几个函数:

import torchoutputs = torch.tensor([[0.2,0.5],[0.3,0.4]])
print(outputs.argmax(1)) # 横着看
print(outputs.argmax(0)) # 竖着看

输出结果:tensor([1, 1])
tensor([1, 0])

这个函数argmax的意思就是:找出最大的值的下标,当设置为1的时候,就是横着找出这一排的最大值,输出下标(下标从0开始),设置为0的时候,就是竖着找出最大值,输出下标。
那么我们网络训练出来的,最终得到的一些值,比如十分类问题就是十个值,我们其实就是选出最大的那个,就认为网络识别的图像为这一类。
然后再拿我们运算出来的结果和真实的target做运算,就可以求出分类准确的数量了,所以准确率就出来了。

import torch
outputs = torch.tensor([[0.2,0.5],[0.3,0.4]])
# print(outputs.argmax(1)) # 横着看
# print(outputs.argmax(0)) # 竖着看
preds = outputs.argmax(1)
targets = torch.tensor([0,1])
print(preds == targets)
print((preds == targets).sum())

输出结果:tensor([False, True])
tensor(1)
所以,我们只需要在我们的代码里简单修改几处,即可显示测试的准确率

# 开始训练
for i in range(epoch):print("开始第{}轮训练".format(i+1))# 遍历训练集for data in train_dataloader:imgs,targets = data outputs = test(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))# 测试步骤total_test_loss = 0 # 用来记录模型在全部测试数据上的loss之和total_accuracy = 0 #用来记录准确的数量with torch.no_grad():for data in test_dataloader:imgs,targets = dataoutputs = test(imgs)loss = loss_fn(outputs,targets)total_test_loss = total_test_loss + lossaccuracy = (outputs.argmax(1) == targets).sum()  # 求得准确的数量total_accuracy = total_accuracy + accuracy # 每次累加print("测试集上的loss:{}".format(total_test_loss))print("整体测试集上的准确率为:{}".format(total_accuracy/test_data_size))# 把每一轮训练得到的结果保存下来torch.save(test,"result_model_{}.pth".format(i))print("模型已保存")

运行结果:

保存的模型:

完善补充2

还有两处需要强调一下:
在网络开始训练之前和开始测试之前,你可能看别人的代码会看到两句话


其实这个的作用呢,我们可以看下官网

可以看到,调用这个就是把网络设置为了训练模式,但是我们之前没写这个,我们的网络也没啥问题,原因就是因为,这个模式也就对一些网络层有影响,图上指示的那块。之前我们写的网络没用到这些,所以写这行代码也可,不写也可。eval同理

使用GPU来训练网络

其实使用GPU很简单,只需要改动几行代码。
我们只需要找到三种模块,使用他们的CUDA方法即可:网络模型、数据、损失函数
那我们分别找到这三部分,进行修改
网络模型

# 创建网络模型
test = Network()
if torch.cuda.is_available():test = test.cuda()

数据
训练集和测试集都可以用,取数据的时候调用

 # 遍历训练集for data in train_dataloader:imgs,targets = data if torch.cuda.is_available(): # 如果cuda可用 就调用cudaimgs = imgs.cuda()targets = targets.cuda()outputs = test(imgs) loss = loss_fn(outputs,targets) optimizer.zero_grad() loss.backward() optimizer.step()

损失函数

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()
if torch.cuda.is_available():loss_fn = loss_fn.cuda()

除了这种方式,还有另一种方式使用GPU训练:
提前定义好训练的设备:
device = torch.device("cuda")
如果你电脑上只有一张显卡的话,那么下面这两种写法都是指定这个显卡
device = torch.device("cuda")
device = torch.device("cuda:0")
如果有多个显卡,那就指定你想指定的显卡
device = torch.device("cuda:1")
然后代码里面,调用To即可

# 创建网络模型
test = Network()
test = test.to(device)

损失函数和数据也是一样的方式,通过这样来调用GPU

测试模型

那么,模型训练好了,接下来我们测试一下效果
其实就是输入一个图片,看一下这个模型能不能完成任务
我们写一个test.py文件
我们找一张狗的图片:路径写好

import torchimport torchvision
from PIL import Imageimage_path = "../dataset/dog.png"
image = Image.open(image_path)
print(image)
image = image.convert('RGB') # 确保其颜色通道为RGB
# 设置对图像的处理(调整大小、转换tensor)
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),torchvision.transforms.ToTensor()])
# 对图像处理
image = transform(image)
# batch size
image = torch.reshape(image,(1,3,32,32))# 加载模型
model = torch.load("result_model_0.pth",map_location=torch.device('cpu'))
print(model)
# 把模型转换为测试类型
model.eval()with torch.no_grad():output = model(image)
print(output)
print(output.argmax(1)) # 输出结果值最大的那个下标

运行它,试一下,输出结果:tensor([[-0.3786, 0.3839, 0.2930, 0.3845, -0.3165, 0.4834, -0.3922, -0.2882, 0.0089, -0.3664]])
tensor([5])
可以看到,值最高的是0.4834,这是第5个(从0开始数)
也就是说,网络认为这是第5类。那么我们看下数据集的类别,第五类是dog,说明预测正确了。

当然了,你这里预测错误也是很有可能的,因为我使用的模型是训练了一轮得到的模型,准确率并不高。我们可以使用训练多轮的模型试试,准确率会有所提升。
ps:注意一个问题
假如你运行代码,报错如下
RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same or input should be a MKLDNN tensor and weight is a dense tensor
这个多半是因为,你使用的模型是你用GPU训练出来的,但是呢现在测试,你是使用cpu跑的,所以提示你这个
解决办法就是加载模型的时候,添加这么一个参数:map_location=torch.device(‘cpu’)
做一个映射

# 加载模型
model = torch.load("result_model_0.pth",map_location=torch.device('cpu'))

PyTorch入门(四)搭建神经网络实战相关推荐

  1. pyTorch入门(六)——实战Android Minist OpenCV手写数字识别(附源码地址)

    学更好的别人, 做更好的自己. --<微卡智享> 本文长度为4239字,预计阅读12分钟 前言 前面几篇文章实现了pyTorch训练模型,然后在Windows平台用C++ OpenCV D ...

  2. pytorch深度学习和入门实战(四)神经网络的构建和训练

    目录 1.前言 2.神经网络概述 2.1 核心组件包括: 2.2 核心过程 3.构建神经网络模型 3.1构建网络层(Layer ➨ Model) 3.2 torch.nn.Sequential的3大使 ...

  3. PyTorch 入门实战(四)——利用Torch.nn构建卷积神经网络

    承接上一篇:PyTorch 入门实战(三)--Dataset和DataLoader PyTorch入门实战 1.博客:PyTorch 入门实战(一)--Tensor 2.博客:PyTorch 入门实战 ...

  4. Deep Learning:基于pytorch搭建神经网络的花朵种类识别项目(内涵完整文件和代码)—超详细完整实战教程

    基于pytorch的深度学习花朵种类识别项目完整教程(内涵完整文件和代码) 相关链接:: 超详细--CNN卷积神经网络教程(零基础到实战) 大白话pytorch基本知识点及语法+项目实战 文章目录 基 ...

  5. 【深度学习】:《PyTorch入门到项目实战》(十二)卷积神经网络:填充(padding)和步幅(stride)

    [深度学习]:<PyTorch入门到项目实战>(十二)填充(padding)和步幅(stride) ✨本文收录于[深度学习]:<PyTorch入门到项目实战>专栏,此专栏主要记 ...

  6. PyTorch 入门实战

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_36556893/article/ ...

  7. 网易云课程:深度学习与PyTorch入门实战

    网易云课程:深度学习与PyTorch入门实战 01 深度学习初见 1.1 深度学习框架简介 1.2 pytorch功能演示 2开发环境安装 3回归问题 3.1简单的回归问题(梯度下降算法) 3.3回归 ...

  8. PyTorch 入门实战(五)——2013kaggle比赛 猫狗大战的实现

    承接上一篇:PyTorch 入门实战(四)--利用Torch.nn构建卷积神经网络 PyTorch入门实战 1.博客:PyTorch 入门实战(一)--Tensor 2.博客:PyTorch 入门实战 ...

  9. Pytorch入门+实战系列七:图片风格迁移和GAN

    Pytorch官方文档:https://pytorch.org/docs/stable/torch.html? 1. 写在前面 今天开始,兼顾Pytorch学习, 如果刚刚接触深度学习并且想快速搭建神 ...

  10. 【深度学习】翻译:60分钟入门PyTorch(四)——训练一个分类器

    前言 原文翻译自:Deep Learning with PyTorch: A 60 Minute Blitz 翻译:林不清(https://www.zhihu.com/people/lu-guo-92 ...

最新文章

  1. 半年时间学linux,你学Linux入门用了多长时间?
  2. django_models_关系一对多
  3. 新赛题上线!2021CCF大数据与计算智能大赛全面开赛!
  4. 用python画图代码意思_Python科学画图代码分享
  5. mybatis--一对一、一对多、多对多(七)
  6. Google AI 的焦虑:拆分搜索和人工智能部门
  7. 【Computer Organization笔记06】浮点数的数据表示,浮点数加减运算
  8. 计算机网络课设--小型企业网络的规划与设计
  9. css鼠标滑过变大,css 鼠标移上去会变大(示例代码)
  10. 什么叫0day和Warez?
  11. 同济版《线性代数》引争议,从清华改用MIT数学课程看中美数学教育差距!
  12. LTE CQI优化提升方法
  13. win7连接惠普打印机p1108
  14. node.js 不能识别?.问号点运算符
  15. 前端上传文件,multipart-formdata,boundary的使用
  16. MyCat Catlet实现 详解
  17. java kit 9_Java SE Development Kit 9
  18. 【Aegisub】从零开始的ASS特效字幕学习之路
  19. 1维数组 2维数组
  20. 帆软报表开发学习笔记(八)

热门文章

  1. erlang 小程序:整数序列,搜索和为正的最长子序列
  2. C# string byte[] Base64 常用互相转换
  3. 【转】Bootloader之uBoot简介(转)
  4. Windows Server 2012 Backup安装
  5. Eclipse常用的一些设置
  6. [翻译]MVP(SC),MVP(PV),PM,MVVM 和 MVC 表现模式架构对比
  7. 根据 List 元素中的某个字段大小排序
  8. Airflow 重跑dag中部分失败的任务
  9. 网络管理常用命令(6/14) -netstat命令详解
  10. 2602 最短路径问题