Neural Networks(神经网络)
神经网络可以使用 torch.nn package来构建
现在您已经大致了解了autograd, nn依赖于autograd来定义模型并区分它们。一个nn.Module包含layers和一个接收输入的前向方法(forward method )并且会返回输出
例如,看看这个分类数字图像的网络:
它是一个简单的前馈网络。它接收输入,将它喂给一层接一层的神经元,最后得到输出。
神经网络的典型训练过程如下:
- 定义一些具有可学习参数(或权重)的神经网络
- 遍历输入的数据集
- 通过网络处理输入
- 计算损失(离正确的输出有多远)
- 传播梯度以调节网络参数
- 更新网络的权重,通常使用简单的更新规则:weight = weight - learning_rate * gradient
Define the network(定义网络)
让我们来定义这个网络:
import torch
import torch.nn as nn
import torch.nn.function as F
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
# 6个输出通道,3X3的卷积核
# 卷积 1
self.conv1 = nn.Conv2d(1,6,3)
# 卷积 2
self.conv2 = nn.Conv2d(6,16,3)
# y = Wx + b
# 线性全连接层,120维的输出
self.fc1 = nn.Linear(16*6*6,120)
# 线性全连接层,120维输入,84维的输出
self.fc2 = nn.Linear(120,84)
# 线性全连接层,84维的输入,10维的输出
self.fc2 = nn.Linear(84,10)
def forward(self, x):
# (2,2)的最大池化,作用主要是降低维度,通过对卷积后的结果进行降采样来降低维度
x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
x = F.max_pool2d(F.relu(self.conv2(x)),2)
# 使用view将前面的多维度的tensor展平成一维,-1是根据原tensor数据自动分配列数
x = x.view(-1,self.num_flat_features(x))
x = F.relu(self.fc1(c))
x = F.relu(self.fc2(c))
# 最后一层不使用relu激活函数
x = self.fc3(c)
return x
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()
print(net)
输出:
Net(
(conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))
(fc1): Linear(in_features=576, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
您只需定义 forward函数,然后使用autograd为您自动定义backward函数(其中计算梯度)。你可以在 forward函数中使用任何一个张量运算.
模型的可学习参数由net.parameters()返回
params = list(net.parameters())
print(len(params))
print(params[0].size()) # conv1's .weight
输出:
10
torch.Size([6, 1, 3, 3])
让我们尝试一个随机的32x32输入。注意:此网络(LeNet)的预期输入大小为32x32。要在MNIST数据集上使用此网络,请将数据集中的图像大小调整为32x32。
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
输出:
tensor([[ 0.0329, -0.0316, -0.1040, -0.0586, 0.1620, -0.0514, 0.0443, 0.0822,
0.1102, -0.1116]], grad_fn=<AddmmBackward>)
使用随机梯度方法将参数的梯度缓冲池置为0:
net.zero_grad()
out.backward(torch.randn(1, 10))