pytorch从头搭建并训练一个神经网络模型(图像分类cnn)(代码片段)

Rainbowman0 Rainbowman0     2023-02-20     197

关键词:

0. 前言

之前用过一些很厉害的模型,图像分类领域的VGG16,目标检测领域的YoloV5,实例分割领域的Yolact等。但只是会配置好环境之后训练,最多稍微修改下源码的接口满足自己的需求。还从来没有用PyTorch从头搭建并训练一个模型出来。

正好最近在较为系统地学PyTorch,就总结一下如何从头搭建并训练一个神经网络模型。

1. 使用torchvision加载数据集并做预处理

我们使用的数据集是CIFAR10,该数据集有10个类别,图像尺寸为3 x 32 x 32,如下所示:

代码如下,重要地方代码中有注释

import torch
import cv2
import numpy as np
from torchvision import datasets, transforms
import torchvision

# 1. 使用torchvision加载数据集并做预处理
transform = transforms.Compose([transforms.ToTensor(),  # 把图像转换为tensor
                                transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5)),  # 归一化处理
                              ])
# 加载训练集和测试集
trainset = torchvision.datasets.CIFAR10(root='E:\\\\Machine Learning\\\\PyTorch\\\\CIFAR10', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='E:\\\\Machine Learning\\\\PyTorch\\\\CIFAR10', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)

2. 定义(搭建)自己的神经网络

代码及注释如下,整个结构很简单,就是两个卷积层,两个最大池化层,最后连接三个全连接层。

# 2. 定义卷积神经网络
import torch.nn as nn
import torch.nn.functional as F

class MyModel(nn.Module):  #  继承nn.Module
    # 定义网络结构
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv1 = nn.Conv2d(3,6,5)
        self.pool = nn.MaxPool2d(2,2)
        self.conv2 = nn.Conv2d(6,16,5)
        self.fc1 = nn.Linear(16*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    # 定义前向传播过程
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16*5*5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)

        return x

Net = MyModel()

3. 定义损失函数(Loss Function)和优化器(Optimizer)

神经网络的反向传播需要损失函数,因为是多分类问题,所以我们用交叉熵损失函数:

# 3. 定义损失函数和优化器
import torch.optim as optim

criterion = nn.CrossEntropyLoss()  # 多分类问题,用交叉熵损失函数
optimizer = optim.SGD(Net.parameters(), lr=0.001, momentum=0.9)  # 用SGD优化器

4. 训练神经网络

接着开始训练我们的模型,共训练2个epoch,batch_size=4,先用CPU训练,看看时间如何。

# 4. 训练神经网络
epochs = 2  # 训练两个epoch,batch_size = 4 (batch_size的大小定义在第一步torch.utils.data.DataLoader中)
e1 = cv2.getTickCount()  # 记录训练时间
for epoch in range(epochs):
    total_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # 得到inputs
        inputs, labels = data
        optimizer.zero_grad()
        # forward + backward + optimize
        # 前向传播+反向传播+更新参数
        outputs = Net(inputs)  # 前向传播,得到outputs
        loss = criterion(outputs, labels)  # 得到损失函数
        loss.backward()  # 后向传播
        optimizer.step()  # 更新参数

        # 输出训练过程
        total_loss += loss.item()
        if (i+1) % 1000 == 0:  # 每1000次(就是4000张图像)输出一次loss
            print('第个epoch:第:5d次:目前的训练损失loss为::.3f'.format(epoch+1, i+1, total_loss/1000))
            total_loss = 0.0

e2 = cv2.getTickCount()
print('用CPU训练总共用时: s'.format((e2-e1)/cv2.getTickFrequency()))
# 输出结果:1个epoch:第 1000次:目前的训练损失loss为:2.2941个epoch:第 2000次:目前的训练损失loss为:2.0871个epoch:第 3000次:目前的训练损失loss为:1.9021个epoch:第 4000次:目前的训练损失loss为:1.7991个epoch:第 5000次:目前的训练损失loss为:1.7091个epoch:第 6000次:目前的训练损失loss为:1.6601个epoch:第 7000次:目前的训练损失loss为:1.6231个epoch:第 8000次:目前的训练损失loss为:1.5861个epoch:第 9000次:目前的训练损失loss为:1.5501个epoch:第10000次:目前的训练损失loss为:1.4971个epoch:第11000次:目前的训练损失loss为:1.4681个epoch:第12000次:目前的训练损失loss为:1.4692个epoch:第 1000次:目前的训练损失loss为:1.3922个epoch:第 2000次:目前的训练损失loss为:1.3822个epoch:第 3000次:目前的训练损失loss为:1.3642个epoch:第 4000次:目前的训练损失loss为:1.3612个epoch:第 5000次:目前的训练损失loss为:1.3442个epoch:第 6000次:目前的训练损失loss为:1.3492个epoch:第 7000次:目前的训练损失loss为:1.3132个epoch:第 8000次:目前的训练损失loss为:1.3272个epoch:第 9000次:目前的训练损失loss为:1.3062个epoch:第10000次:目前的训练损失loss为:1.3022个epoch:第11000次:目前的训练损失loss为:1.2752个epoch:第12000次:目前的训练损失loss为:1.288
用CPU训练总共用时:83.7945317 s

用时83.79秒。

5. 测试模型结果

# 5. 测试模型准确率如何

correct = 0
total = 0

e1 = cv2.getTickCount()  # 记录测试时间
with torch.no_grad():  # 不跟踪梯度
    for data in testloader:
        images, labels = data
        outputs = Net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
        
e2 = cv2.getTickCount()
print('用CPU测试总共用时: s'.format((e2-e1)/cv2.getTickFrequency()))
print('在测试集上的准确率为::.3f%'.format(correct*100/total))

我们来看看结果如何

# 结果
用CPU测试总共用时:5.3146039 s
在测试集上的准确率为:55.460%

准确率大概55%,虽然不高,但可以看出我们的模型确实学到了东西(因为10分类问题随机预测的话准确率在10%左右)。并且这个博客的目的在于梳理训练神经网络的大致流程,而非构建一个优秀的模型。

6. 嫌CPU太慢?换GPU训练并推测试试!

首先看看是否安装了对应版本的cuda和cudnn,具体安装步骤就不说了,csdn上很多优秀教程。

# 检测电脑上是否安装了对应版本的cuda
device = torch.device('cuda:0' if torch.cuda.is_available else 'cpu')
print('设备名称: ', device)
print('查看cuda版本: ', torch.version.cuda)
# 结果
设备名称:  cuda:0
查看cuda版本:  10.1

PyTorch使用GPU训练非常方便,相较于第4步用CPU训练,只需增加两行代码:
(1)把神经网络模型加载到cuda
(2)把数据加载到cuda

代码及注释如下:

# 6. 用GPU训练神经网络
######  第1处不一样   ########
Net.to(device)  # 把神经网络模型加载到cuda
epochs = 2  # 训练两个epoch,batch_size = 4 (batch_size的大小定义在第一步torch.utils.data.DataLoader中)
e1 = cv2.getTickCount()  # 记录训练时间
for epoch in range(epochs):
    total_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # 得到inputs
        inputs, labels = data
        ######  第2处不一样   ########
        inputs, labels = inputs.to(device), labels.to(device)  # 把数据加载到cuda
        optimizer.zero_grad()
        # forward + backward + optimize
        # 前向传播+反向传播+更新参数
        outputs = Net(inputs)  # 前向传播,得到outputs
        loss = criterion(outputs, labels)  # 得到损失函数
        loss.backward()  # 后向传播
        optimizer.step()  # 更新参数

        # 输出训练过程
        total_loss += loss.item()
        if (i+1) % 1000 == 0:  # 每1000次(就是4000张图像)输出一次loss
            print('第个epoch:第:5d次:目前的训练损失loss为::.3f'.format(epoch+1, i+1, total_loss/1000))
            total_loss = 0.0

e2 = cv2.getTickCount()
print('用CPU训练总共用时: s'.format((e2-e1)/cv2.getTickFrequency()))

看看结果如何:

# 结果1个epoch:第 1000次:目前的训练损失loss为:2.2311个epoch:第 2000次:目前的训练损失loss为:2.0321个epoch:第 3000次:目前的训练损失loss为:1.8721个epoch:第 4000次:目前的训练损失loss为:1.7451个epoch:第 5000次:目前的训练损失loss为:1.7021个epoch:第 6000次:目前的训练损失loss为:1.6341个epoch:第 7000次:目前的训练损失loss为:1.6031个epoch:第 8000次:目前的训练损失loss为:1.5481个epoch:第 9000次:目前的训练损失loss为:1.5131个epoch:第10000次:目前的训练损失loss为:1.4941个epoch:第11000次:目前的训练损失loss为:1.4591个epoch:第12000次:目前的训练损失loss为:1.4522个epoch:第 1000次:目前的训练损失loss为:1.3962个epoch:第 2000次:目前的训练损失loss为:1.3722个epoch:第 3000次:目前的训练损失loss为:1.3502个epoch:第 4000次:目前的训练损失loss为:1.3612个epoch:第 5000次:目前的训练损失loss为:1.3382个epoch:第 6000次:目前的训练损失loss为:1.3122个epoch:第 7000次:目前的训练损失loss为:1.3222个epoch:第 8000次:目前的训练损失loss为:1.2892个epoch:第 9000次:目前的训练损失loss为:1.2772个epoch:第10000次:目前的训练损失loss为:1.2692个epoch:第11000次:目前的训练损失loss为:1.2932个epoch:第12000次:目前的训练损失loss为:1.283
用CPU训练总共用时:74.0288839 s

相较于CPU的83秒,GPU用了74秒,快了一些,但提升不够明显。这是因为我们的网络很小,参数也很少。另外我的笔记本的GPU也挺老的,1050核显。

我们在试试用GPU推断会加速多少:

# 6. 使用GPU推断

correct = 0
total = 0
Net.to(device)  # 把神经网络模型加载到cuda

e1 = cv2.getTickCount()  # 记录测试时间
with torch.no_grad():  # 不跟踪梯度
    for data in testloader:
        images, labels = data
        images, labels = images.to(device), labels.to(device) # 把数据加载到cuda
        outputs = Net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
        
e2 = cv2.getTickCount()
print('用CPU测试总共用时: s'.format((e2-e1)/cv2.getTickFrequency()))
print('在测试集上的准确率为::.3f%'.format(correct*100/total))

看看结果如何

# 结果
用CPU测试总共用时:4.3125164 s
在测试集上的准确率为:54.090%

相较于CPU推断需要5.3秒,使用GPU推断需要4.3秒,速度也有提升。

4.使用预训练的pytorch网络进行图像分类(代码片段)

4.使用预训练的PyTorch网络进行图像分类这篇博客将介绍如何使用PyTorch预先训练的网络执行图像分类。利用这些网络只需几行代码就可以准确地对1000个常见对象类别进行分类。这些图像分类网络是开创性的、最先进的图像分类网... 查看详情

4.使用预训练的pytorch网络进行图像分类(代码片段)

4.使用预训练的PyTorch网络进行图像分类这篇博客将介绍如何使用PyTorch预先训练的网络执行图像分类。利用这些网络只需几行代码就可以准确地对1000个常见对象类别进行分类。这些图像分类网络是开创性的、最先进的图像分类网... 查看详情

pytorch定义并训练自己的数字数据集

这一篇主要讲解Pytorch搭建一个卷积神经网络识别自己的数字数据集基本流程。注:一开始接触很多教程都是直接加载datasets已有的MNIST等,如果想要训练自己的数据就可以采用这个方法。基本步骤:获取并读取数据-->定义网络... 查看详情

[深度学习][pytorch]pytorch实现一个简单得线性回归模型并训练

一个典型的神经网络的训练过程如下:定义具有学习参数(或权重)的神经网络迭代输入数据集根据神经网络对输入数据集进行运算计算损失(输出与真实结果的距离,损失越小说明模型越准确)将梯度反... 查看详情

从头开始微调/训练 HuggingFace 模型的正确方法 (PyTorch)

】从头开始微调/训练HuggingFace模型的正确方法(PyTorch)【英文标题】:CorrectWaytoFine-Tune/TrainHuggingFace\'sModelfromscratch(PyTorch)【发布时间】:2020-12-0805:57:18【问题描述】:例如,我想使用现有配置从头开始训练BERT模型。以下代码是正... 查看详情

在预训练的 pytorch 网络中加载单个图像

】在预训练的pytorch网络中加载单个图像【英文标题】:Loadasingleimageinapretrainedpytorchnet【发布时间】:2018-10-0808:45:29【问题描述】:这里的总新手,我正在使用thispytorchSegNet实现和一个“.pth”文件,其中包含来自50个epoch训练的权... 查看详情

pytorch实践模型训练(torchvision)

...失函数的选择以及一些辅助的工具等,TorchVision是一个和PyTorch配合使用的Python包,包含很多图像处理工具PyTorch中的数据读取模型训练开始的第一步就是数据读取,PyTorch提 查看详情

「深度学习一遍过」必修5:从头训练自己的数据无从下手?来看看这10个pytorch自带的分类模型叭(代码片段)

...于深度学习的相关问题,并提供一些微不足道的人工神经网络模型设计思路。专栏地址:「深度学习一遍过」必修篇目录1CreateDataset2 CreateDataloader3TrainModel3.1最简单的模型3.1.1alexnet3.2 VGG系列3.2. 查看详情

使用python在gpu上构建和训练卷积神经网络

参考技术A我将对代码进行补充演练,以构建在数据集上训练的任何类型的图像分类器。在这个例子中,我将使用花卉数据集,其中包括102种不同类型的花。需要数据集和代码都可以私信我。Pytorch是机器学习和Python上的免费软件... 查看详情

pytorch深度学习实战|搭建卷积神经网络进行图像分类与图像风格迁移

...#xff0c;对新手非常友好。本文为实战篇,介绍搭建卷积神经网络进行图像分类与图像风格迁移。1、实验数据准备本文中准备使用MIT67数据集,这是一个标准的室内场景检测数据集,一共有67个室内场景,每类包括80... 查看详情

pytorch之基于经典网络架构训练图像分类模型(代码片段)

...型,并且直接用训练的好权重当做初始化参数2.参考pytorch官网例子3.设置哪些层需要训练4.优化器设置5.训练模块6.测试模型效果本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052一、模块简单介绍我们... 查看详情

如何入门pytorch之二:如何搭建实用神经网络(代码片段)

...。本节中,我们将介绍如何使用Pytorch来搭建一个实用的神经网络。搭建一个神经网络并训练,大致有这么四个部分:准备数据,搭建模型,评估函数,优化网络权重  1.数据准备  数据准备在上一篇中已讲过,这里... 查看详情

pytorch学习笔记第五篇——训练分类器(代码片段)

...练图像分类器2.1加载并标准化CIFAR102.2训练图像3.定义卷积神经网络、损失函数、优化器、训练网络和保存模型4.测试自己的模型5.在GPU上进行训练1.数据通常,当您必须处理图像,文本,音频或视频数据时,可以使... 查看详情

pytorch搭建cnn进行图像分类(代码片段)

...近抽出时间来亲身实践一下用PyTorch搭建一个简单的卷积神经网络进行图像分类。全流程主要分为数据读取与处理、网络设计、训练和测试四个部分。数据集处理数据集我采用的是UCMerced数据集,这是一个用于遥感图像分类的... 查看详情

pytorch搭建基本的gan模型及训练过程(代码片段)

...数绘图函数GAN的训练输出整体代码参考资料概述本文通过Pytorch搭建基本的GAN模型结构,并通过torchvision的MNIST数据集进行测试。对于GAN模型的基本结构及公式的理解可以看前一篇博客:GAN的理论知识及公式的理解下文的实... 查看详情

深度学习之pytorch实战——迁移学习

...正文:  我们在前三篇博客学会了使用自己搭建的卷积神经网络模型解决手写图片识别的问题,因为卷积神经网络在解决计算机视觉问题上有着独特的优势,所以采用简单的神经网络模型就能使手写图片识别的准确率达到很高... 查看详情

如何在一个模型中训练多个损失,并在 pytorch 中选择冻结网络的某些部分?

】如何在一个模型中训练多个损失,并在pytorch中选择冻结网络的某些部分?【英文标题】:Howtotrainmultiplelossesinonemodelwithfreezingsomepartofthenetworkoptionallyinpytorch?【发布时间】:2020-10-0911:49:20【问题描述】:我是pytorch的新手。我正... 查看详情

pytorch保存模型断点以及加载断点继续训练(代码片段)

   在训练神经网络时,用到的数据量可能很大,训练周期较长,如果半途中断了训练,下次从头训练就会很费时间,这时我们就想断点续训。一、神经网络模型的保存,基本两种方式:1.保存完整模型model, torch.sa... 查看详情