神经网络搭建与训练实战

小实战+sequential的使用

模型结构选择:CIFAR 10 model

模型目的:
在这里插入图片描述
从CIFAR 10的数据集可以看出,CIFAR 10模型的主要作用是,对一个物体进行分类,辨别出一个物品属于哪个类别

模型结构:
在这里插入图片描述

关于卷积之后,尺寸不变的问题:
卷积,我们可以从参数规定其卷积前后的通道数,所以,我们可以认为卷积实际上,主要关注的点在于通道数,但是其尺寸也会在卷积的过程中发生变化,这种变化是可控的,也就是说,我们可以通过设置padding、stride、dilation等参数,控制卷积过程中尺寸的变化
在这里插入图片描述
由于上图中,每次卷积前后的尺寸都以给出,所以可以根据该关系式,计算出padding、stride、dilation设置为多少(其中如果没有对dilation参数传参,那么其默认为1)

最后经过计算,padding等于2,stride等于1

关于池化:
池化,在上面的模型中,主要用于改变数据的尺寸

关于Flatten:
之前我们使用的Flatten是一个API,现在,其他他也有模型层,就叫Flatten,所以,我们可以在模型搭建时,就加上Flatten

关于最后的线性层:
在这里插入图片描述

图中少化了一个input,实际上,将数据处理完之后,展开成一维的结果,就是一个线性处理中的输入层,大小是64 * 4 * 4

之后进行一次线性层的处理,数据量变成了64

再经过一次线性层的处理,数据量变成了10(因为模型最后要从十个类别中预测一个,最后的数据可以是对应类别的对应概率)

后续我们拿到最终的10数据之后,就可以做一些逻辑处理,比如,如果最后的数据是对应类别的对应概率,那么我们取最大的即可

代码

在这里插入图片描述
这就是依据上面的CIFAR10 model的结构,搭建的神经网络

检验代码/推算参数的小技巧

检验代码:
在这里插入图片描述
torch提供了一个API,即ones,这个API可以帮我们构建随机的输入数据,我们只需要规定他的shape即可
这里我们规定输入数据的shape为(64, 3, 32, 32)

将其放入模型中进行处理,然后打印output的shape,可以看到输出两个数:左边是batch size,即抓包数,右边是图片的数量(一维),或者高和宽(二维)

这个可以帮助我们检验模型搭建的参数是否哪里设置的有问题,一旦有问题,这样运行就会报错

推算参数:
在这里插入图片描述
如果某一步我们不知道接下来该设置的参数的大小时,有些情况,我们可以在forward中,将步骤推进到未知参数函数的前一步,让其输出“截止到未知函数之前”的信息,就可以输出接下来该设置什么参数了

如,此处输出了1024:
在这里插入图片描述

Sequential的使用

在这里插入图片描述
他是搭建神经网络时,构造函数和forward函数的一个平替,使用他可以简化构造函数和forward函数

可以看到,我们直接在构造函数中,使用Sequential,然后,接下来的每一层的填入,都当做是Sequential的一个参数即可,我们还是照常设置参数,只不过无需任何的接收,按照顺序进行参数设置即可
之后,在forward中,也无需一个一个将x传入,而是直接调用Sequential返回的对象,将x传入即可

补充介绍

在这里插入图片描述
SummaryWriter对象还有一个API是add_graph,他可以将神经网络展示出来,
且双击其中每一步,可以具体看到神经网络的每个步骤,以及每个步骤的数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以及输入数据的大小尺寸、一些参数等等

损失函数

介绍

在这里插入图片描述
损失函数,举个简单的例子,现在我们有一个实际的输出,还有一个目标
那么损失函数Loss,就会计算出我们现在的实际输出与我们的目标之间的差距,或者说误差,且可以告诉我们是哪个模块误差比较大,差的比较多,从而为我们调整训练方向、更好的训练出更合适的参数,提供一定的依据

文档

在这里插入图片描述
在这里插入图片描述

代码1

以L1Loss为例:
在这里插入图片描述
首先需要一对数据集,tensor类型(因为他有深度学习所需的属性)
分别表示一个实际输出和一个目标

我们需要将其shape修改成:
在这里插入图片描述
任意修改。。。

我们就将其修改为最常用的:抓取数、信道数、高、宽

之后创建L1Loss对象,将两个数据传进去即可得到一个结果,该结果默认情况下是取各个对应值的差值,然后取平均
如上图输出0.66…

当然我们可以修改他的reduction参数为‘sum’,那么最后的损失函数就是各个对应值的求和

代码2

MSELoss,损失函数的计算用“各个对应项的方差”
在这里插入图片描述

代码3(“分类”的损失函数)

在这里插入图片描述
假设,我们的结果是“三分类”,分别是人、狗、猫

然后,我们给进去一个input,然后给出一个三元组,就是最后的输出,表示各个分类的一个概率
而我们期望的目标结果是,能预测到第二个分类,对应下标也就是“1”

这样,x就是[0.1 , 0.2, 0.3]
class就是1

最后损失函数的计算见上图公式的最终推导结果
负的x的target下标对应的概率+log(e的各个概率的次方求和)
第一部分表示,对应目标分类的概率越高,损失函数的结果就越小,表示误差越小
第二部分表示,其概率差异越大,误差越小,概率越持平,误差越大,表示一个灵敏度

注意,其中的log是默认以10为底,所有log可以看成ln

在这里插入图片描述
可以看到,input(这里的输入其实就是模型训练出来的实际输出)的shape,可以设置为C,或者(N,C)
N是batch size,就是抓取数。而C是分类的类别的个数

Target的shape可以不设置,或者设置一个N即可

在这里插入图片描述
可以看到最后的输出是1.1019
在这里插入图片描述
与我们的计算结果相同

在神经网络当中的应用:

在这里插入图片描述
我们设置抓取器一次抓取一张图片,这样便于观察数据

我们利用之前的CIARF10的神经网络,拿到每个数据的inputs和labels之后,将inputs放入模型处理一下,拿到一个输出,直接打印输出结果,以及这张图真正的target(或者说label,因为label是已经标注好了的,其label就是这张图真正的类别,所以也就是这个数据的目标target)

可以看到输出结果是:10个概率(因为这个神经网络就是对十个类别做出判断,十选一)
图片的真正的target是[3]

如果抓包数为2:
在这里插入图片描述
一次循环计算两个数据,因为两个数据被打包在了一个data里,所以可以一次循环计算两个数据

计算出每个数据的损失函数的结果:
在这里插入图片描述

之后,我们看看如何让损失函数提供我们调整模型参数的依据:
在这里插入图片描述
得到损失函数的结果后,我们使用该结果,调用backward函数,就可以让损失函数为我们的神经网络的模型调整提供依据

我们在41打断点,进行调试(注意,这样调试运行的话,代码会执行完40行之后停下来)
我们找到神经网络模型中,某个卷积层的weight的grad:
在这里插入图片描述

模型参数的调整,实际上就是调整卷积层的卷积核的值,可以看到weight后面有五个数,那就是五个参数,之所以有五个,是因为我们设置卷积核的大小是5

而现在,还没有执行backward,所以grad是None,grad是梯度的意思,损失函数就是通过影响梯度值,从而影响到参数的调整,梯度值会很大程度上参与参数的调整

当我们下一步,执行了bacward之后:
在这里插入图片描述
可以看到grad被赋值了,所以,损失函数通过grad梯度值,为模型的参数调整提供依据,具体说,其中所要调整的参数包括“卷积层的卷积核的值”

优化器

作用

当我们根据损失函数计算出误差,并且使用backward对梯度进行了设置之后,就要用到优化器,优化器会根据梯度grad去进行参数的调整,也就是调参的动作是优化器完成的

文档

在这里插入图片描述
在这里插入图片描述
文档中会有使用示例

而下面的算法,就是各种不同的优化器,我们可以调用不同的算法,去创建不同的优化器,每个算法调用时,传参有所不同,具体可以点进去查看具体的传参,但是前两个参数都是需要传入“模型参数”、“学习速率”:(所以我们初学时,可以只传前两个参数先)
在这里插入图片描述

代码

在这里插入图片描述
我们可以在原先损失函数的模型基础上,进行一些添加

首先就是先根据一个算法,创建出一个优化器:
第一个参数传入模型对象的parameters()方法即可,第二个参数传入学习速率,一般0.01就可以

之后,在每次损失函数backward之后,就使用优化器去调参(optim.step()),但是注意,每次backward之前,都要使用优化器对象调用zero_grad()去将梯度清零,这是在每个循环步都进行梯度清零,避免当前循环步新的梯度产生影响

但是,经过上图的代码,我们只是对数据集中的每个包的数据都进行了一遍调参,也就是对整个数据集只进行了一轮调参

所以,我们可以更新代码,使得可以对数据集进行多轮调参:
在这里插入图片描述
我们对每一轮的损失函数计算出来的误差进行累加,最后输出,就可以量化的看到优化器的优化,误差越来越小
(当然,某些情况下会出现误差越来越大的情况,因为这是模型训练,不可能很简单的一维线性的降低,会受到多方面影响)

现有网络模型的使用和修改

文档

我们在Pytorch训练神经网络-入门一栏的最后末尾,也提到了pytorch给我们提供了各个领域的各个类别的模型,现在我们来学着使用他们

在这里插入图片描述
在这里插入图片描述
我们以视觉为例
在这里插入图片描述
进去之后就可以看到这些都是视觉方面的模型,上图展示的是“物体分类”方面的模型

在这里插入图片描述
右侧有着不同类别的模型索引
分别是“分类”、“语义分割”、“目标检测、实例分割”等等

使用

接下来就以分类的VGG模型为例:

在这里插入图片描述
第一个参数:可以指定使用哪个已经训练好的权重,即已经训练好了的参数,并且是多个参数,可以进行选择
(默认为无,也就是不使用训练好的权重(或者说参数),而是使用一些随机的初始值,后续再进行训练)
第二个参数:指定是否显示下载进度

代码

不进行预权重的指定:
在这里插入图片描述
可以看到,直接打印模型,可以打印出模型的框架、以及内容、以及各个层的形参设置
(注意,这里的形参参数与我们的训练参数不一样,这里是对模型的结构进行设置的参数,而我们平时说的参数是训练过程中,所调整的数据的权重,或者说函数的参数,二者不是一回事)

指定一个预处理的权重(即已经训练好了的权重):
在这里插入图片描述
如果指定了预处理完成的权重,那么会下载这些权重,然后同样会加载打印上面的模型结构

修改

假如说,我就是想用CIFAR10去训练这个模型:
在这里插入图片描述
可以从模型的结构看到,最终模型会输出1000个类型,而CIFAR10最终只有10个类型

所以,我们要对模型进行一些修改,或者在最后进行一些添加,
这里我们在最后添加一层线性层,使其输入为1000,输出为10:
在这里插入图片描述
使用add_module这个API,可以对现有的网络模型进行添加一些层,上图就是添加了线性层,使得最终的输出为10个类型
参数一是对添加的层的命名
参数二是这个层的构建

当然也可以添加一个Sequential,从而实现批量添加

同时,我们注意到,这个网络模型分为了三个部分,最后一部分叫做classifier,我们还可以指定添加到该部分的末尾:
在这里插入图片描述

当然也可以指定到其他部分的末尾:
在这里插入图片描述
这里可以知道,这个添加暂时还是一次性的,即保存在内存,进程结束的话,就会恢复原样,因为我们没有进行任何形式的硬盘保存,所以此处看到之前在classifter中添加的层没有了

同样的,我们还可以进行修改:
在这里插入图片描述
指出要修改哪一个部分的哪一个(使用下标索引),上图打印模型时,每一层前面的数字就是他的下标
我们修改第七个(下标为6)的线性层的输出为10

网络模型的保存和读取

方式1

保存

在这里插入图片描述
No.7:首先,需要从网络上拿到一个模型到程序中

之后,使用torch.save进行模型的保存
参数一:模型对象的名字
参数二:模型的保存路径以及保存文件的名字(如上图)

读取/加载

在这里插入图片描述
直接使用torch.load,参数传入模型文件的路径(精确到文件本身)

就可以加载模型,并且得到模型对象

注意,这种方法的保存和读取,都是模型结构+权重参数一起保存和读取的

陷阱

方式1有一个陷阱,或者说容易忽略的地方:
在这里插入图片描述
假如说我们保存的不是网络模型,而是自己手搓的模型,那么保存时,还是使用save进行保存

加载时:
在这里插入图片描述
可以看到,直接加载会报错
原因:当前加载的文件内没有Tudui这个模型的定义或者声明,文件找不到

解决:将我们的模型拷过来,或者进行文件的引用:

拷贝模型:
在这里插入图片描述
注意,只将类拷贝过来即可,无需再创建对象

引用文件:
在这里插入图片描述
Tudui这个类在model_save这个文件中,所以,就如上图所示进行文件的引用

方式2

保存

在这里插入图片描述
第二种保存时,同样是使用save这个方法,但是第一个传参是模型对象.state_dict(),表示获取模型的权重参数即可,将模型的权重参数保存到参数二的路径中

加载

在这里插入图片描述
由于模型文件中只保存了模型的权重参数,而没有保存模型的结构,所以,在加载模型时,只有权重参数是不够的,需要先加载模型的结构,所以,先创建模型的对象(对于网络模型,选择不使用预处理的权重参数),之后,调用模型对象的load_state_dict方法,传入“使用load加载出来的权重参数”

最后打印模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值