Pytorch:Neural Networks

Posted CollectTime

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch:Neural Networks相关的知识,希望对你有一定的参考价值。

    让我们使用Pytorch建立一个神经网络模型,使用的模块是:torch.nn。基于之前以及学习的autograd,nn模块依据此模块定义了不同的模型。通过nn.Model定义网络模型,然后通过forward(input)计算出output值。

    这里我们以定义一个下图的神经卷积网络为例:

    具体网络模型可参考之前讲解的关于CNN的文章。

    训练一个神经网络模型基本的步骤如下:

  1. 确定网络的科学系参数

  2. 遍历一个数据集作为输入

  3. 将数据输入网络

  4. 计算损失函数

  5. 计算梯度

  6. 更新参数


1 定义网络:

import torchfrom torch.autograd import Variableimport torch.nn as nnimport torch.nn.functional as Fclass Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        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):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square you can only specify a single number
        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:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_featuresnet = Net()print(net)

思路非常清晰和简单,首先定义一个类Net,该类继承与nn.Model,这样就可以调用nn.Model的方法生成模型,和使用model中的各种网络模块。

out:

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)
  (fc2): Linear(in_features=120, out_features=84)
  (fc3): Linear(in_features=84, out_features=10))

可以看出来,我们只需要定义前向网络,输入一个Variable,通过输出调用backward即可自动计算出每个变量相对于输出的梯度。非常的简单。

通过一下方式可以看到网络的所有参数:

params = list(net.parameters())
print(len(params))
print(params[0].size()) # conv1's .weight

out:

10
torch.Size([6, 1, 5, 5])

同时为了使初始的梯度都为0,可以调用:

net.zero_grad()
out.backward(torch.randn(1, 10))

需要注意的是:

torch.nn中支支持mini-batch,而不是单个的样本。所以对于图片来说,输入的参数是一个4维iede数据:nSamples x nChannels x Height x Width

如果是想要输入单个样本的话,使用input.unsqueeze(0)营造一个假的batch。


2.定义loss函数

loss函数输入的参数为output和target,通过计算算出目标值和检测出的值之间的差距。

nn包下有好几种不同的loss函数包,一个简单的loss函数平方差误差损失函数。

如下:

output = net(input)
target = Variable(torch.arange(1, 11)) # a dummy target, for example
criterion = nn.MSELoss()

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

out:

Variable containing:
 38.3962
[torch.FloatTensor of size 1]

现在来看loss函数如何通过其grad.fn属性计算出参数的梯度的。

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
      -> view -> linear -> relu -> linear -> relu -> linear
      -> MSELoss
      -> loss

通过loss变量的grad_fn属性,可以看到各层网络的函数。

print(loss.grad_fn)  # MSELoss
print(loss.grad_fn.next_functions[0][0]) # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0]) # ReLU

out:

<MseLossBackward object at 0x7f95e0a148d0>
<AddmmBackward object at 0x7f95e0a14c18>
<ExpandBackward object at 0x7f95e0a14c18>


3 反向传播:

以上发现可以使用loss.backward()计算出个参数的梯度,现在需要定位到每个参数对其进行修改。定位每一层网络的参数方式为:

net.zero_grad() # zeroes the gradient buffers of all parameters
print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)
loss.backward()
print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)

这里看的仅仅是参数的梯度,如果调用data属性即可根据grad进行修改。

out:

conv1.bias.grad before backwardVariable containing:
 0
 0
 0
 0
 0
 0[torch.FloatTensor of size 6]

conv1.bias.grad after backward
Variable containing:
1.00000e-02 * -6.1643 -2.5201 -4.5238 6.8188 -0.2024 3.4750[torch.FloatTensor of size 6]


同pytorch中还包含了各种各样的网络模型,可以参考链接:
http://pytorch.org/docs/master/nn.html


4.更新参数

最后剩下的就是更新参数了,随机梯度下降法更新参数的公式为:
weight = weight - learning_rate * gradient

如下:

learning_rate = 0.01

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

不仅仅有随机梯度下降法跟新参数,还有其他的优化方法,包含在torch.optim包中。如图:

import torch.optim as optim
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
# in your training loop:
optimizer.zero_grad() # zero the gradient buffers
output = net(input)loss = criterion(output, target)
loss.backward()
optimizer.step() # Does the update


以上是关于Pytorch:Neural Networks的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch - Dropout: A Simple Way to Prevent Neural Networks from Overfitting

训练技巧详解含有部分代码Bag of Tricks for Image Classification with Convolutional Neural Networks

用 Recursive Neural Networks 得到分析树

Graph Neural Networks for Link Prediction with Subgraph Sketching

探讨COMP9444 Neural Networks

Neural networks学习——记录python3下与教材里的python2的不同