PyTorch官方60分钟教程笔记-神经网络

 

注意:在观看本笔记前,你应该对Python、神经网络有基本的概念上的了解

神经网络可以用torch.nn创建

例子:手写数字识别神经网络

定义神经网络

定义类
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个输出通道,5×5方形卷积
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # 一个仿射变换:y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 5*5:图像维度
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # 通过(2, 2)窗口的最大池化
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # 如果size是方形,可以用1个数字指定
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = torch.flatten(x, 1) # 扁平化除了batch维之外的维度
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()
print(net)

输出:

Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, 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)
)

(backward函数会自动由autograd生成)

参数
params = list(net.parameters())
print(len(params))
print(params[0].size())  # conv1的权重

(可学习的参数由net.parameters()返回)

输出:

10
torch.Size([6, 1, 5, 5])
获取随机的32×32输入并得到输出
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)

(这个网络的输入必须是32×32)

输出:

tensor([[-0.0013, -0.0198, -0.0745, -0.0067, -0.0456,  0.0398, -0.0620,  0.0607,
          0.0924,  0.0445]], grad_fn=<AddmmBackward0>)
反向传播
net.zero_grad()
out.backward(torch.randn(1, 10)) # 用随机梯度反向传播

损失函数

MSE损失函数
output = net(input)
target = torch.randn(10)  # 简单的一个示例target
target = target.view(1, -1)  # 使维度和output一样
criterion = nn.MSELoss()

loss = criterion(output, target)
print(loss)

输出:

tensor(0.9642, grad_fn=<MseLossBackward0>)
反向传播

一旦调用loss.backward(),所有参数的梯度将会被累积。

net.zero_grad()     # 把所有的梯度缓存清零

print('反向传播之前的conv1.bias.grad')
print(net.conv1.bias.grad)

loss.backward() # 反向传播

print('反向传播之后的conv1.bias.grad')
print(net.conv1.bias.grad)

输出:

反向传播之前的conv1.bias.grad
tensor([0., 0., 0., 0., 0., 0.])
反向传播之后的conv1.bias.grad
tensor([ 0.0032,  0.0048, -0.0005, -0.0062,  0.0045,  0.0166])

(有关nn中的模型和损失函数的文档

更新权重

最简单的更新方法是随机梯度下降(Stochastic Gradient Descent, SGD

weight = weight - learning_rate * gradient

使用Python实现SGD:

learning_rate = 0.01
for f in net.parameters():
    f.data.sub_(f.grad.data * learning_rate)

实际编程中,可以使用torch.optim:

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()    # 更新参数