基于小土堆入门教程的pytorch训练神经网络方法实现

成果展示

在学习吴恩达机器学习和小土堆入门教程的基础上,完成了该实验,目前可以实现标准数据集的加载、网络模型的搭建及训练、数据可视化、GPU加速功能,是机器学习理论的初步实践

import torch
import torchvision.datasets
from torch import nn
from torch.utils.data import DataLoader
import timefrom torch.utils.tensorboard import SummaryWriter# 获取训练集
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)
# 加载训练数据
train_dataloader = DataLoader(train_data, batch_size=16)
# 加载测试数据
test_dataloader = DataLoader(test_data, batch_size=16)train_data_size=len(train_data)
test_data_size=len(test_data)
# 搭建网络
class NetWork(nn.Module):def __init__(self):super(NetWork, self).__init__()# 网络模型构建self.module = 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):return self.module(x)# 实例化网络对象
NW = NetWork().cuda()       # cuda加速# 验证网络正确性,查看卷积后尺寸
# input = torch.ones((64, 3, 32, 32)).cuda()
# output = NW(input)
# print(output.shape)
# print(output.argmax(1))# 创建损失函数
loss_fn = nn.CrossEntropyLoss().cuda()  # cuda加速# 创建优化器
optimizer = torch.optim.SGD(NW.parameters(), lr=0.01)# 训练过程
NW.train() # 开启训练模式,但并不必要,仅对特定层起作用
epoch = 10  # 训练轮数for i in range(epoch):start_time = time.time()print("-------第", i + 1, "轮训练--------")for data in train_dataloader:img, target = data      # 分别获取图像和标签img=img.cuda()target=target.cuda()    # cuda加速output=NW(img)          # 输出为经过向前传播的图像# 调优过程loss=loss_fn(output,target)    # 根据预测和标签求损失函数optimizer.zero_grad()   # 梯度清零,避免干扰loss.backward()         # 反向传播,计算参数的梯度optimizer.step()        # 调整优化参数cost_time=time.time()-start_timeprint("第",i+1,"轮训练完成,训练用时:",cost_time,"s")# 测试步骤NW.eval()   # 验证模式with torch.no_grad():       # 模块下计算不用于梯度求导,即只测试,不调参total_test_loss=0total_accuracy=0    # 总正确率for data in test_dataloader:imgs,targets=dataimgs=imgs.cuda()targets=targets.cuda() # cuda加速output=NW(imgs)loss=loss_fn(output,targets)total_test_loss+=loss.item() # 将loss从tensor类型转为常规类型accuracy=(output.argmax(1)==targets).sum()  # 单次验证集的正确数量total_accuracy=total_accuracy+accuracy      # 总正确数量print("总损失为:",total_test_loss)print("正确率为:", total_accuracy.item()/test_data_size)

输出示例为:
网络输出

数据集

数据集加载

主要有标准数据集和自制数据两种方法,标准数据以目标检测为例,有VOCCOCO等,自制数据集方法见此处,本文主要介绍读取加载方法。

pytroch中提供DataSet基类用于获取内容和标签,可以重写该类用于读取自定义的数据,示例如下:

import torch
import torch.utils.data.dataset as Dataset
import numpy as np#创建子类
class New_Dataset(Dataset.Dataset):# 初始化内容和标签def __init__(self, Data, Label):self.Data = Dataself.Label = Label# 返回数据集大小def __len__(self):return len(self.Data)# 获取数据内容及标签并转为Tensor类型def __getitem__(self, index):data = torch.Tensor(self.Data[index])label = torch.Tensor(self.Label[index])return data, label

Dataloader用于打包数据,给网络提供不同形式的数据,使用方法为数据名=DataLoader(dataset数据集,batch_size=每批取的单元,drop_last=True舍去最后不足的数据,shuffle=True 随机选取)

标准数据集

本章使用标准数据集CIFAR10进行实验,使用方法为train_data = torchvision.datasets.CIFAR10(root="./data", train=True,download=True),将训练数据下载到当前目录的data文件夹下,没有文件时会自动下载,获取测试数据将train参数设置为False即可。

该数据集为60000张32×32的图像,其中50000张训练图像,10000张测试图像,使用该数据集的好处就是小,下载演示都比较方便,生产实践中真正搞得数据集动辄几十上百G,暂时还没这个需求。
数据集
对第一个加载数据读取情况如下:
读取加载内容

数据预处理

Transformor

主要用于图像预处理和相关变换,包含在torchvision.transforms 模块下,一些常用方法如下:

ToTensor:输入PIL的Image图像格式或 numpy.ndarray的数组,将其转化为包含反向传播所需参数的tensor类型,使用示例为t=transforms.ToTensor(Image.open(path))
ToPILImage:将tensor类型转回PIL的Image格式
Resize:拉伸压缩调整图像大小,而不分割,使用方法为tr=torchvision.transforms.Resize(size=(宽,高))若输入为一个数,则图像的短边将与此匹配,其他详细参数见该文章
Normalize:使用平均值和标准差对图像进行均一化处理,输入每个通道对应的均值和标准差作为参数,函数会利用这两个参数分别将每层标准化(使数据均值为0,方差为1)后输出。
Compose:组合多个变换,使用方法示例为transforms.Compose([ transforms.CenterCrop(10),transforms.PILToTensor(),transforms.ConvertImageDtype(torch.float) ])
RandomCrop:随机裁剪,输入大小,返回随机裁剪后的图像

Tensorboard

用于解析训练相关事件,将图像和训练信息可视化,库文件使用from torch.utils.tensorboard import SummaryWriter导入,创建实例writer=SummaryWriter(".\logs"),要显示图像使用writer.add_image(标题,tensor_img),最常用的绘图使用add_scaler(图标名称,纵坐标,横坐标),实例代码及效果如下:

for n_iter in range(100):writer.add_scalar('Loss/train', np.random.random(), n_iter)writer.add_scalar('Loss/test', np.random.random(), n_iter)writer.add_scalar('Accuracy/train', np.random.random(), n_iter)writer.add_scalar('Accuracy/test', np.random.random(), n_iter)

多个图像会自动根据标签字符归类,该方法常用于绘制学习曲线,绘制完成后在终端输入tensorboard --logdir="文件路径\logs --port=新端口",在弹出的链接出可查看。
折线图绘制
也可以使用该工具绘制模型,通过writer.add_graph(模型名,输入)
绘制模型
使用后必须使用Writer.close()将内容写入文件中,类似U盘和读写文件操作时的最后一步。

网络搭建

骨架—nn.Module

pytorch中的网络构建通过nn库实现,其中Module为骨架,作为容器组合隐藏层及输出层,示例代码如下:

import torch.nn as nn
import torch.nn.functional as Fclass Model(nn.Module):def __init__(self):super().__init__()self.conv1 = nn.Conv2d(1, 20, 5)self.conv2 = nn.Conv2d(20, 20, 5)def forward(self, x):x = F.relu(self.conv1(x))return F.relu(self.conv2(x))

调用该模块时自动执行forward函数,构造函数中定义神经网络需要的隐藏层。

卷积层Convolution Layers

nn.Conv1d代表一维卷积,nn.Conv2d代表二维卷积,常用输入包括输入通道in_channel、输出通道out_channel、卷积核大小kernel_size、填充padding和步长stride,由于卷积核也是训练的变量之一,故该方法并不能手动设置卷积核,若要手动设置卷积核,需使用orch.nn.functional.conv2d方法,在参数的weight中设置。

池化层Pooling layers

为了保留输入特征,但减少数据量而增加的层,如最大池化,选出卷积核对应的最大值MaxPool方法,输入有池化窗kernel_size,步长stride,填充padding和空洞卷积dilated即卷积核有空格,和cellmode是否保留超出核范围的值。

非线性激活Non-linear Activations

给数据引入非线性特质,如RELU截断非负数值、sigmoid分类方法等。

线性层Linear Layers

对传入数据进行线性变换wx+b,参数为输入特征的个数和输出特征的个数,即Linear(x,y),可将x个特征输出为y个预测。

构建序列

上述隐藏层输出层都写在构造函数并命名太繁琐,调用也很不方便,可以使用Sequential进行组合,将这些层共同组成模型,示例如下:

model = nn.Sequential(nn.Conv2d(1,20,5),nn.ReLU(),nn.Conv2d(20,64,5),nn.ReLU())

在后续的forward函数仅需调用self.model()方法即可实现数据的正向传播。

网络模型

网络模型示例图
记不清为啥了,反正当时就是用了这个网络,可能是简单网络中效果较好的一种吧,输入三通道32×32的图像,最终输出10个可能特征的预测,中间分别经过的层列表如下:

5×5卷积核的卷积层输入通道为3,输出通道为32
2×2窗口的最大池化层原有图像缩减16×16
5×5卷积核的卷积层输入通道为32,输出通道为32
2×2窗口的最大池化层原有图像缩减至8×8
5×5卷积核的卷积层输入通道为32,输出通道为64
2×2窗口的最大池化层原有图像缩再减4×4
Falttern层数据一维化,图像处理成64×4×4=1024个样本
全连接层输入1024个样本输出64
全连接层输入64个样本输出10个预测特征

该步的重点在于计算卷积层的参数,32×32的图像经过5×5的卷积核,步长为1的情况下该输出28×28的矩阵,而我们仍需要输出32×32的图像,则需要对原图像进行填充,填充数值可经过如下公式计算:
填充计算公式
空洞卷积我们不使用,故内核间距dilation为默认的1,可得padding=2,该步在调用Conv2d时除了输入输出通道数和卷积核大小外,需要设置该参数。

损失函数

用于衡量预测与实际的差距,为更新输出提供依据(通过反向传播实现),根据模型和预测需要的不同可以选择多种损失函数,MSE平方差,交叉熵等,具体损失函数可见官方文档。

优化器

pytorch实现各种优化算法的包,官方文档在此,使用过程如下:
1,构造优化器对象
2,反向传播计算梯度
3,调优参数
示例代码如下:

optimizer.zero_grad()	# 梯度清零,避免上次学习的干扰,pytorch特性是将梯度累加
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) # 构建SGD优化算法的优化器,学习速率为0.01,动量为0.9
backward()				# 反向传播计算梯度
optimizer.step()		# 执行调优参数

经过两次优化的部分模型参数变化展示如下:
初始参数
新参数

模型保存与加载

torch.save(模型名,保存文件名.pth)
模型名=torch.load(文件名.pth)
使用该方法会保存模型的结构和参数,但在新文件中加载仍然需要以前的结构文件,即需要import 网络模型文件,如果有了网络模型文件就没必要从文件中加载了,而因为保存了模型文件,该方法保存的文件体积也较大,故官方推荐使用如下方法:

torch.save(模型名.state_dict(),文件名.pth)
模型.lload_state_dict(文件名.pth)
该方法只保存了模型的训练数据,减少了保存文件体积。

网络模型优化

GPU加速

首先通过两张图直观感受一下GPU的加速效果:
cpu训练
gpu训练
可以看到用了GPU能加的速不是一点半点,这也是为什么当时学习安装pytorch时要着重搞CUDA的安装了,该方法比较费硬件,也对显卡显存有一定要求,大量数据在显卡上运行时是否有和操作系统一致的保护或调度机制,目前还不了解,先这么用着吧,如果没有英伟达显卡的话也可以去谷歌找一张免费提供的显卡使用,好像效果还不错。

使用方法就是分别在模型、数据和损失函数后加上指定显卡运行标识,如NetWork=NetWork().cuda()img=img.cuda()loss=loss_fn(output,target).cuda()

这种方法不大严谨,官方推荐使用device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu",有显卡使用第一张显卡,否则使用cpu运行,可以增强程序的可移植性和健壮性,通过NetWork=NetWork.to(device)的方式给需要的信息加上标签。

输出处理

直接对经过网络的output进行输出,信息如下:
输出结果信息
该信息为16×10的矩阵序列,表示一个批次16张图像的每个结果的可能概率,我们需要的仅仅是最可能的分类结果,在该序列中选择最大的可能作为输出即可,该方法通过调用argmax()函数实现,参数为0表示横向比较,参数为1表示纵向比较,输出为比较序列最大值的序号。

通过输出可以看到每次预测和真实标签的差距:
预测和真实
统计每个批次预测正确的数量,测试集全部读取完成后与测试集总数之比即为准确率,实现代码如下:

	accuracy=(output.argmax(1)==targets).sum()  # 单次验证集的正确数量total_accuracy=total_accuracy+accuracy      # 总正确数量
# 循环结束后
print("正确率为:", total_accuracy.item()/test_data_size)

答疑

现在已经能构建起自己定义的网络模型并跑出还可以的数据,但在实际构建的确有和基础知识学习时的很大区别,比如:

1,基础学习时特征是经过构建好的神经网络,通过计算损失函数,不断调整神经网络的一些参数,但实验中并没有设置网络参数的过程,只给网络搭起了模型就自行运转了,网络中的参数从何而来?

2,调优过程的反向传播起了什么作用,调优器究竟整合了机器学习的什么步骤?

模型参数

模型在建立时我们并没有指定参数,这是因为pytroch定义了默认值,以Conv2d为例,继承自ConvNd类,参数初始化方法定义在其中:
继承类
初始化参数方法
模型初始化参数的方法

backward()反向传播

我们之前学过,优化成本函数的方法是梯度下降,第一步就需要计算偏导,不同函数人手算很麻烦,计算机实现更复杂,为了简化该过程,有人推导出了由损失函数计算每个结点偏导的快速方法,这种由损失函数推出偏导的方法称为反向传播,pytorch给我们封装成了函数直接使用即可,该步骤在实验中就是为了计算梯度

说白了方向传播就是求偏导,后面的step就是给新的参数进行赋值,优化器本质就是给模型更新参数的过程,从数学上来说就是实现了这两个公式:
在这里插入图片描述

总结

还是画图比较清楚,对pytorch训练神经网络的整体过程总结如下:
pytorch训练神经网络流程
该过程大致和理论学习时一致,优化器整合了梯度下降部分,一些复杂的数学原理并没有向用户过多暴露,使得我们可以很快上手构造模型,但后续调参和模型优化仍要求我们理解底层原理。

这么说来机器学习本身好像也是快上手,慢熟悉的过程,更多操作如特征缩放、判断收敛等还未使用,更不必说神经网络的底层原理,我们并没有规定特征的学习方向,网络究竟是如何通过激活函数和卷积操作等就能学习到准确的特征并判断的呢?不同参数又是如何在一个庞大的神经网络中作用的?目前只能说是稍稍入门,这些都有还待于后续的学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/402255.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓应用开发学习:查看手机传感器信息

一、引言 在手机app的开发中经常会用到手机的传感器,在《Android App 开发进阶与项目实战》一书的第10章就介绍了传感器的一些功能和用法。要想使用传感器,首先得知道手机具备哪些传感器。书中有传感器类型取值的说明,并提供了一个查看手机传…

聊聊场景及场景测试

在我们进行测试过程中,有一种黑盒测试叫场景测试,我们完全是从用户的角度去理解系统,从而可以挖掘用户的隐含需求。 场景是指用户会使用这个系统来完成预定目标的所有情况的集合。 场景本身也代表了用户的需求,所以我们可以认为…

橙色简洁大气体育直播自适应模板赛事直播门户自适应网站源码

源码名称:酷黑简洁大气体育直播自适应模板赛事直播门户网站 源码开发环境:帝国cms 7.5 安装环境:phpmysql 带采集,可以挂着电脑上自动采集发布,无需人工操作! 橙色简洁大气体育直播自适应模板赛事直播门户…

Java Web|day5.MyBatis

MyBatis 定义 它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低 **ORM: **Object Relation Mapping,…

数字孪生技术框架:从数据到决策的桥梁

随着科技的飞速发展,数字孪生技术作为一种创新的信息化手段,正逐步渗透到各个行业领域,成为推动数字化转型的重要力量。数字孪生技术框架,作为支撑这一技术体系的核心架构,以其独特的层级结构,实现了从数据…

如何选择适合流水线作业的工业级条码读码器

高度自动化的工业生产环境中,条码二维码的应用,在工厂流水线作业的高效性和准确性对于企业的生产效率和质量管控至关重要,条码二维码扫描设备作为流水线中用于读取条码或二维码朔源信息的关键设备,它们能够快速、准确地识别和采集…

vim - vim模式及部分操作

文章目录 一、vim 基本介绍二、vim 的简单使用三、几种常用模式切换四、命令模式和底行模式的操作汇总 一、vim 基本介绍 vim 是一款多模式的编辑器。vim 中有很多子命令来进行代码的编写操作。 同时,vim 提供了不同的模式供我们选择。 在vim下的底行模式下通过:he…

8.15 day bug

bug1 一个按钮折腾了 两个小时 一直点第一个按钮,然后进去后发现根本没有课程,需要创建workspace,然后各种问题,还是没把课程启动起来,然后去看gitpod使用文档,搞懂工作区到底是怎么回事,一通操…

JVM 有哪些垃圾回收算法(回收机制)?

JVM 有哪些垃圾回收算法(回收机制)? 标记-清除算法 在Java虚拟机中,标记-清除算法是一种用于垃圾回收的算法。它分为两个阶段:标记阶段和清除阶段。 在标记阶段,垃圾收集器会遍历堆内存中的所有对象&…

JavaEE 第11节 定时器

前言 本篇博客重点介绍定时器的简单实现,帮助理解其底层原理。关于JAVA工具类自带的定时器,只会简单介绍,详细使用参阅官方文档(下文中有官方文档的连接)。 一、什么是定时器 定时器的概念非常简单。 它在软件开发…

自制深度学习推理框架之计算图设计

文章目录 一、计算图1.1 计算图定义1.2 计算图的生成1.2.1 **静态计算图(Static Computational Graph)**1.2.2 **动态计算图(Dynamic Computational Graph)** 1.3 计算图功能1.3.1 训练阶段1.3.2 推理部署阶段 1.4 计算图的调度(执…

引领企业全球化发展 极光亮相华为亚太ICT峰会2024·泰国

近日,华为亚太ICT峰会2024泰国正式开幕,极光(Aurora Mobile,纳斯达克股票代码:JG)凭借其创新的技术实力与前瞻性的产品布局,受邀出席本次活动。会上,极光展示了其全域消息通知解决方…

【ocr识别003】flask+paddleocr+bootstrap搭建OCR文本推理WEB服务

1.欢迎点赞、关注、批评、指正,互三走起来,小手动起来! 2.了解、学习OCR相关技术知识领域,结合日常的场景进行测试、总结。如本文总结的flaskpaddleocrbootstrap搭建OCR文本推理WEB服务应用示例场景。 文章目录 1.代码结构2.效果演…

MySQL 在 Windows 和 Ubuntu 上的安装与远程连接配置简介

MySQL 是一个广泛使用的开源关系型数据库管理系统,它提供了多用户、多线程的数据库服务。本文将介绍如何在 Windows 和 Ubuntu 操作系统上安装 MySQL,并配置远程连接。 Windows 上的 MySQL 安装 1. 下载 MySQL Installer 访问 MySQL 官方网站下载 Win…

融合创新:EasyCVR视频汇聚平台云计算技术与AI技术共筑雪亮工程智能防线

随着信息技术的飞速发展,视频云计算技术作为云计算领域的一个重要分支,正逐步在公共安全、社会治理等领域展现出其独特的优势。特别是在雪亮工程这一群众性治安防控工程中,视频云计算技术更是发挥了不可替代的作用。本文将从视频云计算技术的…

【leetcode详解】特殊数组II : 一题代表了一类问题(前缀和思想)

前缀和的优势 给定一个数组,前缀和的特点在于,任意给出一对始末位置,能够用O(1)的时间复杂度得到始末位置之间所有元素的某种关系。 题型分析 这道题目正是“给出始末位置,检测其中元素特点”那一类,那我们就想&#…

自动化与高效设计:推理技术在FPGA中的应用

想象一下,你正在设计一个复杂的电路系统,就像在搭建一座精巧的积木城堡。你手头有各种形状和功能的积木块,这些积木块可以组合成任何你需要的结构。在这个过程中,你有两种主要的方法:一种是手动挑选和搭建每一块积木&a…

【Qt】内置对话框

一.Qt内置对话框 Qt 提供了多种可复⽤的对话框类型,即 Qt 标准对话框。Qt标准对话框全部继承于QDialog类。常⽤标准对话框如下: 二.内置对话框分类 1.消息对话框 QMessageBox 1.1 概念 消息对话框是应⽤程序中最常⽤的界⾯元素。消息对话框主要⽤于为…

Android-RK356x GT9XX多点触控设置为单点触控的方法

本文基于RK356x Android11系统描述GT9XX驱动芯片由多点触摸改为单点触摸功能。本次介绍的是触觉智能的Purple Pi OH鸿蒙开源主板,Purple Pi OH是华为Laval官方社区主荐的一款鸿蒙开发主板。 该主板主要针对学生党,极客,工程师,极大…

Opencv模板匹配

使用OpenCV和C来识别彩色图片中的特定物体,如黑桃♠,通常涉及几个步骤:预处理图像、特征提取、对象检测等。下面是一个基本的示例代码,演示如何使用OpenCV的模板匹配方法来识别图片中的黑桃♠。 函数原型 void matchTemplate(Inp…