前言
通常,一个典型的神经网络训练过程包括以下几点:
1.定义一个包含可训练参数的神经网络
2.通过神经网络处理输入
3.计算损失(loss)
4反向传播梯度到神经网络的参数
5.更新网络的参数,典型的用一个简单的更新方法:weight = weight - learning_rate *gradient
1.定义神经网络
from __future__ import print_function
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 输入单通道图像,输出6通道图像,卷积核9*9
self.conv1 = nn.Conv2d(1, 6, 9)
# 输入6通道图像,输出20通道图像,卷积核9*9
self.conv2 = nn.Conv2d(6, 20, 9)
# an affine operation: y = Wx + b
# 线性变化,输入2000个特征,输出150个特征
self.fc1 = nn.Linear(20 * 10 * 10, 150)
# 输入150个特征,输出96个特征
self.fc2 = nn.Linear(150, 96)
# 输入96个特征,输出8个特征
self.fc3 = nn.Linear(96, 8)
#前向传播
def forward(self, x):
# 2D最大池化,窗口大小2*2 步长2
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# If the size is a square you can only specify a single number
# 2D最大池化,窗口大小2*2 步长2
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
# 将所有特征展成一维
x = x.view(-1, self.num_flat_features(x))
# 对线性变换后的特征,做relu激活
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 计算特征的个数
def num_flat_features(self, x):
size = x.size()[1:] # all dimensions except the batch dimension
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
打印输出:
2.通过神经网络处理输入
以上定义了一个前馈函数,反向传播函数被自动通过 autograd 定义,现在可以使用任何张量操作在前馈函数上。
input = torch.randn(1, 1, 64, 64)
out = net(input)
打印输出
测试实例随机生成一个 64x64 的输入,最后输出1*10的特征向量。
3.计算损失值
损失函数
损失函数计算的是模型的输出离目标有多远。通常需要一对输入,即模型输出和目标,
在 nn 包中有一些不同的损失函数, nn.MSELoss是最简单的损失函数,计算了均方误差。
# 计算损失
output = net(input)
# 随机生成目标
target = torch.randn(8)
#和输入一样shape,展成一维
target = target.view(1, -1)
#计算损失值
criterion = nn.MSELoss()
loss = criterion(output, target)
print(loss)
打印输出
4.调用反向传播
把所有参数梯度缓存器先置零
net.zero_grad()
loss.backward()
5.更新网络的参数
更新规则采用随机梯度下降。
learning_rate = 0.01
for f in net.parameters():
f.data.sub_(f.grad.data * learning_rate)
在torch.optim 包中实现了不同的更新规则,类似于SGD, Nesterov-SGD, Adam,RMSProp,使用它非常方便。
import torch.optim as optim
# 创建一个优化器
optimizer = optim.SGD(net.parameters(), lr=0.01)
#循环
# 梯度缓存置零
optimizer.zero_grad()
output = net(input)
loss = criterion(output, target)
# 反向传播
loss.backward()
# 参数更新
optimizer.step()