我们可以通过torch.nn package构建神经网络。

现在我们已经了解了autograd,nn基于autograd来定义模型并对他们有所区分。

一个 nn.Module模块由如下部分构成:若干层,以及返回output的forward(input)方法。

例如,这张图描述了进行数字图像分类的神经网络:

这是一个简单的前馈( feed-forward)网络,读入input内容,每层接受前一级的输入,并输出到下一级,直到给出outpu结果。

一个经典神经网络的训练程序如下:

1.定义具有可学习参数(或权重)的神经网络

2.遍历input数据集

3.通过神经网络对input进行处理得到output结果

4.计算损失(ouput离正确值有多远)

5.将梯度返回到神经网络的参数中

6.更新神经网络的权重,通常使用一个简单的更新规则:

weight = weight - learning_rate * gradient

一、如何在pytorch中定义神经网络

定义神经网络:

import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F class Net(nn.Module):
# 定义Net的初始化函数,本函数定义了神经网络的基本结构
def __init__(self):
# 继承父类的初始化方法,即先运行nn.Module的初始化函数
super(Net,self).__init__()
# 定义卷积层:输入1通道(灰度图)的图片,输出6张特征图,卷积核5x5
self.conv1 = nn.Conv2d(1,6,(5,5))
# 定义卷积层:输入6张特征图,输出16张特征图,卷积核5x5
self.conv2 = nn.Conv2d(6,16,5)
# 定义全连接层:线性连接(y = Wx + b),16*5*5个节点连接到120个节点上
self.fc1 = nn.Linear(16*5*5,120)
# 定义全连接层:线性连接(y = Wx + b),120个节点连接到84个节点上
self.fc2 = nn.Linear(120,84)
# 定义全连接层:线性连接(y = Wx + b),84个节点连接到10个节点上
self.fc3 = nn.Linear(84,10)
# 定义向前传播函数,并自动生成向后传播函数(autograd)
def forward(self,x):
# 输入x->conv1->relu->2x2窗口的最大池化->更新到x
x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
# 如果大小是一个正方形,可以只指定一个数字
x = F.max_pool2d(F.relu(self.conv2(x)),2)
# view函数将张量x变形成一维向量形式,总特征数不变,为全连接层做准备
x = x.view(-1,self.num_flat_features(x))
# 输入x->fc1->relu,更新到x
x = F.relu(self.fc1(x))
# 输入x->fc2->relu,更新到x
x = F.relu(self.fc2(x))
# 输入x->fc3,更新到x
x = self.fc3(x)
return x
# 计算张量x的总特征量
def num_flat_features(selfself,x):
# 由于默认批量输入,第零维度的batch剔除
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 (400 -> 120)
(fc2): Linear (120 -> 84)
(fc3): Linear (84 -> 10)
)

通过net.parameters()可以得到可学习的参数:

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

输出结果:

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

我们模拟一下单向传播,其中input和output均为autograd.Variable:

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

输出结果:

Variable containing:
-0.0618 -0.0648 -0.0350 0.0443 0.0633 -0.0414 0.0317 -0.1100 -0.0569 -0.0636
[torch.FloatTensor of size 1x10]

对所有参数的梯度缓冲区归零并设置随机梯度反向传播:

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

整个torch.nn包只接受那种小批量样本的数据,而无法接受单个样本。 例如,nn.Conv2d能够构建一个四维的Tensor:nSamples x nChannels x Height x Width。

如果需要对单个样本进行操作,使用input.unsqueeze(0)来加一个假维度就可以了。

我们回顾一下目前出现过的概念:

torch.Tensor - 一个多维数组
autograd.Variable - 改变Tensor并且记录下来历史操作过程。和Tensor拥有相同的API,以及backward()的一些API。同时包含着和Tensor 相关的梯度。
nn.Module - 神经网络模块。便捷的数据封装,能够将运算移往GPU,还包括一些输入输出的东西。
nn.Parameter - 一种变量(Variable),当将任何值赋予Module时自动注册为一个参数。
autograd.Function - 实现了使用自动求导方法的前馈和后馈的定义。每个Variable的操作都会生成至少一个独立的Function节点,与生成了Variable的函数相连之后记录下历史操作过程。

二、Loss Function

Loss function根据(output, target) 输入对计算一个值,该值估计输出离目标有多远。

nn包下有几种不同的损失函数。一个简单的损失是: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)

输出结果:

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

现在如果你沿着loss函数反方向走,用.grad_fn属性,你会看到一个像这样的计算图:

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

三、Backprop

我们只需要进行loss.backward()即可向前传播误差。

你先对现有的梯度进行清零,否则其他梯度将被累积到现有的梯度上。

我们可以看一看 conv1’s bias在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)

输出结果:

Variable containing:
0
0
0
0
0
0
[torch.FloatTensor of size 6]
Variable containing:
-0.0929
0.0419
-0.0218
0.0941
0.2251
0.1809
[torch.FloatTensor of size 6]

四、Update the weights

在实践中使用的最简单的更新规则是随机梯度下降法(SGD):weight = weight - learning_rate * gradient。

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

然而,在使用神经网络时,用户希望使用各种不同的更新规则,如SGD、nesterov - SGD、Adam、RMSProp等,为了实现这一点,pytorch构建了一个小的包:torch.optim实现了所有这些方法。

SGD使用方法如下:

import torch.optim as optim

# create your optimizer lr为learning_rate
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()  #得到梯度,i.e. 给Variable.grad赋值
optimizer.step() # Does the update

PyTorch教程之Neural Networks的更多相关文章

  1. PyTorch教程之Training a classifier

    我们已经了解了如何定义神经网络,计算损失并对网络的权重进行更新. 接下来的问题就是: 一.What about data? 通常处理图像.文本.音频或视频数据时,可以使用标准的python包将数据加载 ...

  2. PyTorch Tutorials 3 Neural Networks

    %matplotlib inline Neural Networks 使用torch.nn包来构建神经网络. 上一讲已经讲过了autograd,nn包依赖autograd包来定义模型并求导. 一个nn ...

  3. PyTorch教程之Autograd

    在PyTorch中,autograd是所有神经网络的核心内容,为Tensor所有操作提供自动求导方法. 它是一个按运行方式定义的框架,这意味着backprop是由代码的运行方式定义的. 一.Varia ...

  4. PyTorch教程之Tensors

    Tensors类似于numpy的ndarrays,但是可以在GPU上使用来加速计算. 一.Tensors的构建 from __future__ import print_function import ...

  5. 新手教程之:循环网络和LSTM指南 (A Beginner’s Guide to Recurrent Networks and LSTMs)

    新手教程之:循环网络和LSTM指南 (A Beginner’s Guide to Recurrent Networks and LSTMs) 本文翻译自:http://deeplearning4j.o ...

  6. pytorch -- CNN 文本分类 -- 《 Convolutional Neural Networks for Sentence Classification》

    论文  < Convolutional Neural Networks for Sentence Classification>通过CNN实现了文本分类. 论文地址: 666666 模型图 ...

  7. Machine Learning - 第4周(Neural Networks: Representation)

    Neural networks is a model inspired by how the brain works. It is widely used today in many applicat ...

  8. 3D Graph Neural Networks for RGBD Semantic Segmentation

    3D Graph Neural Networks for RGBD Semantic Segmentation 原文章:https://www.yuque.com/lart/papers/wmu47a ...

  9. 课程二(Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization),第三周(Hyperparameter tuning, Batch Normalization and Programming Frameworks) —— 2.Programming assignments

    Tensorflow Welcome to the Tensorflow Tutorial! In this notebook you will learn all the basics of Ten ...

随机推荐

  1. 正则表达式-linux基础

    通配符 通赔符是模糊匹配的基础,因为通赔符机制的存在使得我们在查找文件的时候非常方便     * :匹配任意长度的任意字符,也可以一个都没有     .  :匹配任意单个字符,必须有一个    [ ] ...

  2. Web学习-jsp实现servlet过程赏析

    Jsp在某种程度上就是一种servelt. 来看看tomcat容器如何将jsp页面翻译成一个"servlet". 一. F:\apache-tomcat-6.0.51\work\C ...

  3. JAVA奇技淫巧简化代码之lombok

    背景 最近在做一个小功能,又不想在原有体态臃肿的项目中追加,为了调试方便并且可以快速开发就采用了springboot.由于使用了JPA,建了几个类,然后通过IDE去生成其属性的构造器.getter.s ...

  4. javaSE基础之 LinkedList的底层简单实现

    这里贴上LinkedList底层的简单实现 package com.yck.mylinkedlist; public class Node { private Node previous; //上一结 ...

  5. class对象详解

    我们知道,对于java语言,我们一般先写一个类对象,表示对某一类对象概述,其中包括属性,方法等.我们在对类对象编译时,会产生一个.class对象,jvm在加载类对象时,是加载.class 对象文件,我 ...

  6. 2017年9月3日 Spring及Mybatis中连接数据库的不同方式

    连接数据库用spring和mybatis中使用的方法可以不同,mybaits可以不用写数据库的配置文件 Spring的连接方法 <!-- 读取属性文件(.properties)的内容 --> ...

  7. [2014-11-02]为EF6+Mysql+CodeFirst启用Migration

    刚为一个EF6 CodeFirst项目启用了Migration,记几个注意点. 启用方法 在Nuget控制台使用以下命令启用Migration Enable-Migrations #此时生成当前数据库 ...

  8. Python初学——pickle & set

    pickle 存放数据 保存和提取python运算完的结果 首先import pickle模块 定义一个字典: a_dict={'da':111,2:[23,1,4],'23':{1:2,'d':'s ...

  9. 增强遍历和Object多参数遍历

    public class T2 { public void t1(Object o){//Object是任何类型,多态 System.out.println(o.toString()); } publ ...

  10. django下进行项目的部署

    -------------------Django下进行对应的服务器配置1.服务器购买 本人在阿里云购买了一个服务器,操作系统为windows server2008/Linux(ubuntu) 2.服 ...