PyTorch的深度学习入门教程之构建神经网络


Posted in Python onJune 27, 2019

前言

本文参考PyTorch官网的教程,分为五个基本模块来介绍PyTorch。为了避免文章过长,这五个模块分别在五篇博文中介绍。

Part3:使用PyTorch构建一个神经网络

神经网络可以使用touch.nn来构建。nn依赖于autograd来定义模型,并且对其求导。一个nn.Module包含网络的层(layers),同时forward(input)可以返回output。

这是一个简单的前馈网络。它接受输入,然后一层一层向前传播,最后输出一个结果。

训练神经网络的典型步骤如下:

(1)  定义神经网络,该网络包含一些可以学习的参数(如权重)

(2)  在输入数据集上进行迭代

(3)  使用网络对输入数据进行处理

(4)  计算loss(输出值距离正确值有多远)

(5)  将梯度反向传播到网络参数中

(6)  更新网络的权重,使用简单的更新法则:weight = weight - learning_rate* gradient,即:新的权重=旧的权重-学习率*梯度值。

1 定义网络

我们先定义一个网络:

import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F


class 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_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 (400 ->120)

 (fc2): Linear (120 ->84)

 (fc3): Linear (84 ->10)

)

你只需要定义forward函数,那么backward函数(梯度在此函数中计算)就会利用autograd来自动定义。你可以在forward函数中使用Tensor的任何运算。

学习到的参数可以被net.parameters()返回。

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

预期输出:

10

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

前向计算的输入和输出都是autograd.Variable,注意,这个网络(LeNet)的输入尺寸是32*32。为了在MNIST数据集上使用这个网络,请把图像大小转变为32*32。

input = Variable(torch.randn(1, 1, 32, 32))
out = net(input)
print(out)

预期输出:

Variable containing:
-0.0796 0.0330 0.0103 0.0250 0.1153 -0.0136 0.0234 0.0881 0.0374 -0.0359
[torch.FloatTensor of size 1x10]

将梯度缓冲区归零,然后使用随机梯度值进行反向传播。

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

注意:torch.nn只支持mini-batches. 完整的torch.nn package只支持mini-batch形式的样本作为输入,并且不能只包含一个样本。例如,nn.Conv2d会采用一个4D的Tensor(nSamples* nChannels * Height * Width)。如果你有一个单样本,可以使用input.unsqueeze(0)来添加一个虚假的批量维度。

在继续之前,让我们回顾一下迄今为止所见过的所有类。

概述:

(1)  torch.Tensor——多维数组

(2)  autograd.Variable——包装了一个Tensor,并且记录了应用于其上的运算。与Tensor具有相同的API,同时增加了一些新东西例如backward()。并且有相对于该tensor的梯度值。

(3)  nn.Module——神经网络模块。封装参数的简便方式,对于参数向GPU移动,以及导出、加载等有帮助。

(4)  nn.Parameter——这是一种变量(Variable),当作为一个属性(attribute)分配到一个模块(Module)时,可以自动注册为一个参数(parameter)。

(5)  autograd.Function——执行自动求导运算的前向和反向定义。每一个Variable运算,创建至少一个单独的Function节点,该节点连接到创建了Variable并且编码了它的历史的函数身上。

2 损失函数(Loss Function)

损失函数采用输出值和目标值作为输入参数,来计算输出值距离目标值还有多大差距。在nn package中有很多种不同的损失函数,最简单的一个loss就是nn.MSELoss,它计算输出值和目标值之间的均方差。

例如:

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

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

现在,从反向看loss,使用.grad_fn属性,你会看到一个计算graph如下:

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

当我们调用loss.backward(),整个的graph关于loss求导,graph中的所有Variables都会有他们自己的.grad变量。

为了理解,我们进行几个反向步骤。

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

预期输出:

<torch.autograd.function.MSELossBackwardobjectat0x7fb3c0dcf4f8>

<torch.autograd.function.AddmmBackwardobjectat0x7fb3c0dcf408>

<AccumulateGradobjectat0x7fb3c0db79e8>

3 反向传播(Backprop)

可以使用loss.backward()进行误差反向传播。你需要清除已经存在的梯度值,否则梯度将会积累到现有的梯度上。

现在,我们调用loss.backward(),看一看conv1的bias 梯度在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)

4 更新权重

实践当中最简单的更新法则就是随机梯度下降法( StochasticGradient Descent (SGD))

weight = weight - learning_rate * gradient

执行这个操作的python代码如下:

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

但是当你使用神经网络的时候,你可能会想要尝试多种不同的更新法则,例如SGD,Nesterov-SGD, Adam, RMSProp等。为了实现此功能,有一个package叫做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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Zabbix实现微信报警功能
Oct 09 Python
彻彻底底地理解Python中的编码问题
Oct 15 Python
numpy 计算两个数组重复程度的方法
Nov 07 Python
对python遍历文件夹中的所有jpg文件的实例详解
Dec 08 Python
Python爬虫——爬取豆瓣电影Top250代码实例
Apr 17 Python
总结Python图形用户界面和游戏开发知识点
May 22 Python
python实现简单五子棋游戏
Jun 18 Python
Python+Selenium使用Page Object实现页面自动化测试
Jul 14 Python
Python模块_PyLibTiff读取tif文件的实例
Jan 13 Python
python中adb有什么功能
Jun 07 Python
Django开发RESTful API实现增删改查(入门级)
May 10 Python
Python利用folium实现地图可视化
May 23 Python
PyTorch的深度学习入门之PyTorch安装和配置
Jun 27 #Python
解决pycharm remote deployment 配置的问题
Jun 27 #Python
python turtle库画一个方格和圆实例
Jun 27 #Python
Python实现的对一个数进行因式分解操作示例
Jun 27 #Python
python pytest进阶之xunit fixture详解
Jun 27 #Python
Python批量查询关键词微信指数实例方法
Jun 27 #Python
Django框架orM与自定义SQL语句混合事务控制操作
Jun 27 #Python
You might like
php语言中使用json的技巧及json的实现代码详解
2015/10/27 PHP
php数值转换时间及时间转换数值用法示例
2017/05/18 PHP
PHP+JS实现的实时搜索提示功能
2018/03/13 PHP
Js组件的一些写法
2010/09/10 Javascript
浅析用prototype定义自己的方法
2013/11/14 Javascript
基于jQuery制作小图标上下滑动特效
2017/01/18 Javascript
vue.js  父向子组件传参的实例代码
2017/10/29 Javascript
jQuery中复合选择器简单用法示例
2018/03/31 jQuery
JS模拟实现哈希表及应用详解
2018/05/04 Javascript
JavaScript实现多态和继承的封装操作示例
2018/08/20 Javascript
vue项目中使用lib-flexible解决移动端适配的问题解决
2018/08/23 Javascript
关于AngularJS中ng-repeat不更新视图的解决方法
2018/09/30 Javascript
JavaScript惰性求值的一种实现方法示例
2019/01/11 Javascript
Node.js 的 GC 机制详解
2019/06/03 Javascript
详解vue中的父子传值双向绑定及数据更新问题
2019/06/13 Javascript
nodejs一个简单的文件服务器的创建方法
2019/09/13 NodeJs
JavaScript 作用域scope简单汇总
2019/10/23 Javascript
微信小程序实现首页弹出广告
2020/12/03 Javascript
[02:44]完美大师赛主赛事淘汰赛第二日观众采访
2017/11/24 DOTA
[00:32]2018DOTA2亚洲邀请赛Liquid出场
2018/04/03 DOTA
使用Python读写文本文件及编写简单的文本编辑器
2016/03/11 Python
python list排序的两种方法及实例讲解
2017/03/20 Python
Python使用正则表达式过滤或替换HTML标签的方法详解
2017/09/25 Python
python装饰器常见使用方法分析
2019/06/26 Python
python中wx模块的具体使用方法
2020/05/15 Python
用python爬虫批量下载pdf的实现
2020/12/01 Python
python实现scrapy爬虫每天定时抓取数据的示例代码
2021/01/27 Python
西尔斯百货官网:Sears
2016/09/06 全球购物
Europcar比利时:租车
2019/08/26 全球购物
四议两公开实施方案
2014/03/28 职场文书
社团活动总结书
2014/06/27 职场文书
办公室务虚会发言材料
2014/10/20 职场文书
房屋所有权证明
2015/06/19 职场文书
2016年119消防宣传日活动总结
2016/04/05 职场文书
SQL语句中JOIN的用法场景分析
2021/07/25 SQL Server
Go语言实现一个简单的并发聊天室的项目实战
2022/03/18 Golang