神经网络

记录一下自己学 pytorch,学习的资料为 pytorch 的中文文档,传送门:https://pytorch.apachecn.org/docs/1.4/blitz/neural_networks_tutorial.html

# 可以使用 torch.nn 包来构建神经网络
# 已经介绍了 autograd 包, nn 包则依赖于 autograd 包来定义模型并对它们求导。
# 一个 nn.Module 包含各个层和一个 forward(input) 方法,该方法返回 output。
# 一个神经网络的典型训练过程如下:
# 1. 定义包含一些可学习参数(或者叫做权重)的神经网络
# 2. 在输入数据集上迭代
# 3. 通过网络处理输入
# 4. 计算 loss(输出和正确答案的距离)
# 5. 将梯度反向传播给网络的参数
# 6. 更新网络的权重,一般使用一个简单的规则: weight = weight - learning_rate * gradient
# 定义网络
# 让我们定义一个这样的网络:

import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):

  def __init__(self):
    super(Net, self).__init__()

    # 输入图像 channel: 1;输出 channel: 6; 5 x 5 卷积核
    self.conv1 = nn.Conv2d(1, 6, 5)
    self.conv2 = nn.Conv2d(6, 16, 5)
    # 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)

  def forward(self, x):
    # 2 x 2 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))
    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:] # 除去批处理维度的其他所有维度
    num_features = 1
    for s in size:
      num_features *= s
    return num_features

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)
)
# 只需要定义 forward 函数, backward 函数会使用 autograd 时自动定义, backward 函数用来计算导数。
# 可以在 forward 函数中使用任何针对张量的操作和计算
# 一个模型的可学习参数可以通过 net.parameters() 返回

params = list(net.parameters())
print(len(params))
print(params[0].size()) # conv1's .weight
#输出为:
10
torch.Size([6, 1, 5, 5])
for i in range(len(params)):
  print(params[i].size())
#输出为:
torch.Size([6, 1, 5, 5])
torch.Size([6])
torch.Size([16, 6, 5, 5])
torch.Size([16])
torch.Size([120, 400])
torch.Size([120])
torch.Size([84, 120])
torch.Size([84])
torch.Size([10, 84])
torch.Size([10])
# 尝试一个随机的 32 x 32 的输入。注意这个网络(LeNet)的期待输入是 32 x 32 的张量。
# 如果使用 MNIST 数据集来训练这个网络,要把图片大小重新调整到 32 x 32。

input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
# 输出为:
tensor([[-0.0884, -0.0955, -0.1157, -0.0185, -0.0328,  0.0188,  0.0193, -0.1154,
          0.0448, -0.0642]], grad_fn=)
# 清零所有参数的梯度缓存,然后进行随机梯度反向传播:
net.zero_grad()
out.backward(torch.randn(1, 10))
# 损失函数
# 一个损失函数接受一对(output,target)作为输入,计算一个值来估计网络的输出和目标值相差多少。
# nn 包中有很多不同的损失函数。 nn.MSELoss 是比较简单的一种,它计算输出和目标的均方误差
output = net(input)
target = torch.randn(10)
target = target.view(1, -1)
criterion = nn.MSELoss()

loss = criterion(output, target)
print(loss)
#输出为:
tensor(1.3201, grad_fn=)
# 现在,如果使用 loss 的 .grad_fn 属性跟踪反向传播过程,会看到计算图如下:

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
      -> view -> linear -> relu -> linear -> relu -> linear
      -> MSELoss
      -> loss
# 所以,当调用 loss.backward(),整张图开始关于 loss 微分,图中所有设置了 requires_grad=True 的张量 .grad 属性累积着张量梯度。

print(loss.grad_fn)
print(loss.grad_fn.next_functions[0][0])
print(loss.grad_fn.next_functions[0][0].next_functions[0][0])
#输出为:



# 反向传播

# 只需要调用 loss.backward() 来反向传播误差。需要清零现有的梯度,否则梯度将会与已有的梯度累加。
# 现在,将调用 loss.backward(),并且查看 conv1 层的偏置在反向传播前后的梯度。

net.zero_grad()
print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)

loss.backward()

print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)
#输出为:
conv1.bias.grad before backward
tensor([0., 0., 0., 0., 0., 0.])
conv1.bias.grad after backward
tensor([ 0.0120, -0.0098, -0.0056,  0.0060,  0.0059, -0.0120])
# 更新权重

# 最简单的更新规则是随机梯度下降法(SGD)
# weight = weight - learning_rate * gradient

learning_rate = 0
for f in net.parameters():
  f.data.sub_(f.grad.data * learning_rate)
# 然而,在使用神经网络时,可能希望使用各种不同的更新规则,如 SGD,Nesterov-SGA、Adam、RMSProp 等。
# 为此,可以使用 torch.optim

import torch.optim as optim

# 创建优化器(optimizer)
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 在训练的迭代中:
optimizer.zero_grad() # 清零梯度缓存
print(net.conv1.weight.grad)
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()
print(net.conv1.weight.grad)
#输出为:
tensor([[[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]],


        [[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]],


        [[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]],


        [[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]],


        [[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]],


        [[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]]])
tensor([[[[ 1.4132e-03,  3.0524e-03,  1.4387e-02, -6.9879e-05,  5.0496e-03],
          [ 6.2602e-03,  7.7174e-04,  7.7477e-03,  4.8251e-03, -6.2586e-03],
          [-1.1347e-02,  1.7323e-02,  1.4601e-03,  4.7047e-03,  4.5172e-04],
          [ 1.5339e-03,  6.5314e-03,  3.5240e-03, -1.6078e-04,  2.6001e-02],
          [-4.3787e-03,  2.5129e-02, -4.8452e-03,  1.7136e-02, -2.2656e-03]]],


        [[[ 1.1603e-02,  2.5870e-04, -4.7882e-04, -1.2974e-02, -7.0833e-03],
          [ 9.1224e-03, -2.7099e-02, -7.2172e-03,  6.0094e-03, -1.9354e-03],
          [ 8.9487e-03,  1.0132e-03, -1.2599e-02,  6.6889e-04,  1.2481e-02],
          [ 1.9308e-02,  1.1304e-02, -2.6835e-02, -5.0302e-03, -1.2123e-02],
          [-8.6779e-03,  2.4515e-03, -1.5991e-03,  3.2772e-03,  1.5057e-03]]],


        [[[ 2.9538e-03,  3.2182e-03,  2.1735e-02, -4.1001e-03,  7.3709e-03],
          [-7.8341e-03,  8.6530e-03,  1.2804e-02,  4.7380e-03,  2.7090e-02],
          [ 2.3400e-02, -9.9183e-03, -2.7806e-03, -5.3960e-03,  6.5356e-03],
          [-9.2149e-03,  6.3300e-03, -9.1231e-03, -3.1583e-03, -2.5313e-02],
          [-6.8671e-03,  8.7669e-03,  2.8738e-02, -4.0501e-04,  1.3954e-02]]],


        [[[-2.8224e-02,  3.6240e-03, -3.5161e-03, -1.1865e-02,  5.3318e-03],
          [-3.4220e-03, -9.4413e-03, -8.9566e-03, -9.7369e-03,  9.6336e-03],
          [ 1.0341e-02, -1.8074e-02,  5.9631e-03,  6.8791e-03, -1.7632e-02],
          [ 6.7529e-03,  1.5338e-02,  6.8727e-03,  8.8999e-03, -5.4561e-03],
          [ 9.2013e-03,  4.1394e-03, -1.4813e-02,  1.5590e-02, -9.7826e-03]]],


        [[[-9.2427e-03,  1.0145e-02, -1.0158e-03,  6.6471e-03, -8.1966e-03],
          [-1.4890e-02, -3.3134e-02, -1.8499e-02,  2.5454e-03,  1.2673e-02],
          [-7.3737e-03, -2.1420e-02, -1.0963e-02, -1.5361e-02, -1.0578e-03],
          [-1.4120e-03,  6.1323e-04, -1.1165e-02,  4.9900e-03, -1.1872e-02],
          [-2.7640e-03,  2.2880e-02, -1.1687e-03, -5.3693e-03,  3.2699e-03]]],


        [[[ 6.0525e-03, -3.7511e-03, -5.7904e-03, -1.8990e-02,  7.1018e-03],
          [-1.3982e-02,  4.2345e-03, -1.7800e-02, -6.0713e-03, -4.9168e-03],
          [-7.9266e-03, -2.8650e-03,  1.9363e-02, -9.5297e-03, -2.8823e-03],
          [ 1.6598e-03, -8.0634e-04,  3.9225e-03,  1.4599e-02,  1.4768e-03],
          [ 1.2664e-04,  1.2907e-02, -6.1437e-03, -4.5010e-03,  1.0548e-02]]]])

你可能感兴趣的:(神经网络)