网站建设培训班学费,wordpress分页 标题,公证网站建设管理,手机app软件开发报价手把手带你快速搭建PyTorch神经网络1. 定义一个Class2. 使用上面定义的Class3. 执行正向传播过程4. 总结顺序相关资料话不多说#xff0c;直接上代码1. 定义一个Class
如果要做一个神经网络模型#xff0c;首先要定义一个Class#xff0c;继承nn.Module#xff0c;也就是i…
手把手带你快速搭建PyTorch神经网络1. 定义一个Class2. 使用上面定义的Class3. 执行正向传播过程4. 总结顺序相关资料话不多说直接上代码1. 定义一个Class
如果要做一个神经网络模型首先要定义一个Class继承nn.Module也就是import torch.nn as nn示例如下
import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super().__init__()self.conv1 nn.Conv2d(1,6,5)self.conv2 nn.Conv2d(6,16,5)def forward(self, x):x F.max_pool2d(F.relu(self.conv1(x)), 2)x F.max_pool2d(F.relu(self.conv2(x)), 2)return x这里我们把class的名字就叫成Net。Class里面主要写两个函数一个是初始化的__init__函数另一个是forward函数。
__init__里面就是定义卷积层先super()一下给父类nn.Module初始化一下。在这个__init__里边主要定义就是卷积层。比如第一层我们叫它conv1把它定义成输入1通道输出6通道卷积核5*5的的一个卷积层。conv2同理。forward里边是真正执行数据的流动。比如上面的代码输入的x先经过定义的conv1这个名字是自己起的再经过激活函数F.relu()这里源自import torch.nn.functional as FF.relu()是官方提供的函数。当然如果在__init__里面把relu定义成了myrelu那这里直接第一句话就成了xF.max_pool2d(myrelu(self.conv1(x)),2)。下一步的F.max_pool2d池化也是一样的。在一系列流动以后最后把x返回到外面去。
需要强调的是
注意前后输出通道和输入通道的一致性。不能第一个卷积层输出4通道第二个输入6通道这样就会报错。它和我们常规的python的class还有一些不同
2. 使用上面定义的Class
先定义一个Net的实例毕竟Net只是一个类不能直接传参数
netNet()然后就可以往里边传入x了。假设已经有一个要往神经网络的输入的数据“input这个input应该定义成tensor类型在传入的时候
outputnet(input)注意在常规python编程中一般向class里面传入一个数据x在class的定义里面应该是把这个x作为形参传入__init__函数里的而在上面的定义中x作为形参是传入forward函数里面的。其实也不矛盾因为在定义net的时候是netNet()并没有往里面传入参数。如果想初始化的时候按需传入则需要在__init__中增加需要传入的参数然后把需要的传入进去即可。
3. 执行正向传播过程
在网络net定义好以后就涉及到传入参数计算误差反向传播更新权重等等这些不太容易记住这些东西的格式和顺序。但是我们可以将这个过程理解为一次正向传播需要把这一路上的输入x都计算出来。在计算的过程中要想让网络输出output与期望的ground truth差不多就需要不断缩小二者的差距这个差距就是目标函数object function或者称为损失函数。
如果损失函数loss趋近于0那么自然就达到目的了。但是损失函数loss基本上没法达到0但是仍然希望能让它达到最小值那么这个做的方式是它能按照梯度进行下降。 那么神经网络怎么才能达到按照梯度下降呢或者说是怎么调整自己使得loss函数趋近于0。它只能不断修改权重比如ywxbx是给定的它只能改变w和b让最后的输出y尽可能接近希望的y值这样损失loss就越来越小。
如果loss对于输入x的偏导数接近0了是不是就意味着到达了一个极值吗而l在你的损失函数计算方式已经给定的情况下loss对于输入x的偏导数的减小其实只能通过更新参数卷积层参数W来实现。
所以通过下述方式实现对W的更新
先算loss对于输入x的偏导数。当然网络好几层这个x指的是每一层的输入而不是最开始的输入input对第1步的结果再乘以一个步长这样就相当于是得到一个对参数W的修改幅度用W减掉这个修改幅度完成一次对参数W的修改。
具体过程代码如下
compute_lossnn.MSELoss() # 定义损失函数
losscompute_loss(target,output) # 把神经网络net的输出和标准答案target传入进去
loss.backward() # 算出loss下一步就是反向传播到这里就把上面的第1步完成了得到对参数W一步的更新量算是一次反向传播。
当然搞深度学习不可能只用官方提供的loss函数所以如果要想用自己的loss函数。必须也把loss定义成上面Net的样子它也是继承nn.Module把传入的参数放进forward里面具体的loss在forward里面算最后return loss。__init__()就空着写个super().__init__就行了。
在反向传播之后对于第2步和第3步的计算就需要用到优化器来实现让优化器来自动实现对网络权重W的更新
from torch import optim
optimizeroptim.SGD(net.parameters(),lr0.001,momentum0.9)同样地优化器也是一个类先定义一个实例optimizer然后使用其中的一个优化器方法。注意在optimizer定义的时候需要给SGD传入了net的参数parameters这样优化器就掌握了对网络参数的控制权就能够对它进行修改了。同时传入的时候把学习率lr也传进去。
注意在每次迭代之前先把optimizer里存的梯度清零一下因为W已经更新过的“更新量”下一次就不需要用了。
optimizer.zero_grad()在loss.backward()反向传播以后更新参数
optimizer.step()4. 总结顺序
定义网络写网络Net的Class声明网络的实例netNet();定义优化器optimizeroptim.xxx(net.parameters()lrxxx)定义损失函数自己写class或者直接用官方的例如compute_lossnn.MSELoss()开始循环过程 首先清空优化器里的梯度信息optimizer.zero_grad();再将input传入outputnet(input) 开始正向传播计算损失losscompute_loss(target,output)误差反向传播loss.backward()更新参数optimizer.step()
综上这样就实现了一个基本的神经网络。大部分神经网络的训练都可以简化为这个过程无非是传入的内容复杂网络定义复杂损失函数复杂等等。
相关资料
梯度下降算法原理讲解——机器学习深度学习数学基础之链式法则