本文参考官方文档,对文档中的神经网络代码进行解读
1.分析神经网络结构:
神经网络结构如下图:
这是一个前馈神经网络,(1)输入为32*32的图片,(2)第一个卷积层有6个5*5(32-28+1=5)的卷积核,这个卷积层输出为6*28*28,经过2*2的池化窗口下采样后,形成6*14*14的输出特征。(3)第二个卷积层有16个6*5*5的卷积核,这个卷积层输出为16*10*10,经过2*2的池化窗口下采样后,形成16*5*5的输出特征。(4)然后将这个16*5*5的特征平坦化(拉成一维),再经过3个全连接层(5)第一个全连接层输入400(16*5*5)个特征输出120个特征。(6)第二个全连接层输入120个特征输出84个特征。(7)第三个全连接层输入84个特征,输出长度为10向量。
然后用代码将上述过程定义。
2.定义网络结构
使用torch.nn
包来构建神经网络,nn
包则依赖于autograd
包来定义模型并对它们求导。一个nn.Module
包含各个层和一个forward(input)
方法,该方法返回output。关于
代码中涉及autograd
包中求导函数和属性在上一篇已经提到了。Pytorch:自动求导(Autograd)_Super_user_and_woner的博客-CSDN博客
import torch
import torch.nn as nn
import torch.nn.functional as F
#定义Net类,继承于torch.nn.Module,torch.nn.Module是所有神经网络模块的基类
class Net(nn.Module):
#在初始化函数中定义各层网络的结构
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 6, 5) # 输入图像channel:1;输出channel:6;5x5卷积核
self.conv2 = nn.Conv2d(6, 16, 5) #输入channel:6;输出channel:16;5x5卷积核
# an affine operation: y = Wx + b
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
#在forward()中定义处理过程
def forward(self, x):
# 2x2 Max pooling
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))#平坦化,重塑张量形状,-1表示自动判断维度,
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
#将x的维数相乘(除了第一维(batch))
def num_flat_features(self, x):
size = x.size()[1:] # 除去批处理维度的其他所有维度
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
有了一个神经网络结构后,需要考虑怎样才能对其权重进行更新。想要更新权重就需要定义损失函数(nn包中有很多不同的损失函数),有了损失函数就可以反向传播误差求梯度,然后根据一定规则(比如:SGD、Nesterov-SGD、Adam、RMSProp等,包torch.optim
实现了所有的这些方法)来更新权重。
3更新权重
首先看看这个网络需要更新的权重有多少个
params = list(net.parameters())
print(len(params))
#输出10,因为Wx+b
随机产生一个输入和输出数据
input = torch.randn(1, 1, 32, 32)#根据定义的网络,第一维表示batch大小,第二维表示channel,第三四维表示32*32的图片
target = torch.randn(10) # 本例子中使用模拟数据标签
target = target.view(1, -1) # 使目标值与数据值尺寸一致
选取的损失函数,根据模型输出output计算损失函数,求在loss上,模型参数的梯度。然后根据优化器更新参数。
criterion = nn.MSELoss()#计算输出和目标的均方误差(mean-squared error)
# 创建优化器(optimizer)
optimizer = optim.SGD(net.parameters(), lr=0.01)#网络参数,学习率
optimizer.zero_grad() # 清零梯度缓存
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step() # 更新参数
如有错误,感谢指正