构建PyTorch神经网络的基本流程和实现过程;
关于torch.nn:
- 使用Pytorch来构建神经网络,主要的工具都在torch.nn包中
- nn依赖于autgrad来定义模型,并对其自动求导
构架神经网络的典型流程:
- 定义一个拥有可学习参数的神经网络
- 遍历训练数据集
- 处理输入数据使其流经神经网络
- 计算损失值
- 将网络参数的梯度进行反向传播
- 以一定的规则更新网络的权重
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义网络类
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
# 定义第一次卷积层,输入纬度=1,输出纬度=6,卷积核大小为3*3
self.conv1=nn.Conv2d(1,6,3)
# 定义第二个卷积层,输入纬度=6,输出纬度=16,卷积核大小3*3
self.conv2=nn.Conv2d(6,16,3)
# 定义三层全连接神经网络
self.fc1=nn.Linear(16*6*6,120)
self.fc2=nn.Linear(120,84)
self.fc3=nn.Linear(84,10)
def forwad(self,x):
# 注意:任意卷积层后面要加激活层、池化层
x=F.max_pool2d(F.relu(self.conv1(x)),(2,2))
x=F.max_pool2d(F.relu(self.conv2(x)),2)
# 经过卷积层的梳理后,张量要进入全连接层,进入前需要调整张量的形状
x=x.view(-1,self.num_flat_features(x))
x=F.relu(self.fc1(x))
x=F.relu(self.fc2(x))
x=self.fc3(x)
return x
def num_flat_fetures(self,x):
size=x.size()[1:]
num_features=1
for s in size:
num_features*=s
return num_features
net=Net()
print(net)
注意:模型中所有的可训练参数,可以通过net.paramenters()来获得。
# 注意所有的可训练的参数,可以通过net.paramenters()获得
params = list(net.parameters())
print(len(params))
print(params[0].size())
input = torch.randn(1,1,32, 32)
out = net(input)
print(out)
print(out.size())
注意:
- torc.nn构建的神经网络只支持mini-batches的输入,不支持单一样本的输入
- 比如:nn.Conv2d需要一个4D tensor,形状为(nSamples,nChannels,Height,Width)如果你的输入只有单一样本形式,则需要执行input.unsqueeze(0),主动将3D Tensor 扩充成2D Tensor
-------------------------------
损失函数:
- 损失函数的输入是一个输入的pair:(output,target),然后计算出一个数值来评估output 和target之间的差距大小。
- 在torch.nn中有若干不同的损失函数可供使用,比如nn.MSELoss就通过计算均方差损失来评估输入和目标值之间的差距
-------------------------------
target = torch.randn(10)
target = target.view(1, -1)
criterion = nn.MSELoss()
loss = criterion(out, target)
print(loss)
- 关于方向传播的链条:如果我们跟踪loss反向传播的方向,使用.grad_fn属性打印,将可以看到一章完整的计算图如下:
- input -> conv2d -> maxpool2d -> conv2d -> relu -> maxpool2d -> view -> linear -> relu -> linear -> relu ->linear -> MSELoss ->loss
- 当调用loss.backward()时,整张计算图对loss进行自动求导,所有属性requires_gard=True 的Tensors都将参与梯度求导的运算,并将梯度累加到Tensors中的.gard属性中。
- 在PyTorch中执行反向传播非常简便,全部的操作就是loss.backward()
- 执行反向传播之前,要将梯度清零,否则梯度会在不同的批次数据之间被累加。
# pytorch中首先执行梯度清零的操作
net.zero_grad()
print('conv1.bias.grad before backward.')
print(net.conv1.bias.grad)
# 在pytorch中实现一次反向传播
loss.backward()
print('conv2.bias.grad after backward.')
print(net.conv1.bias.grad)
浙公网安备 33010602011771号