专栏目录:

第一章:PyTorch之简介与下载

  • PyTorch简介

  • PyTorch环境搭建

第二章:PyTorch之60min入门

第三章:PyTorch之入门强化

  • 数据加载和处理

  • PyTorch小试牛刀

  • 迁移学习

  • 混合前端的seq2seq模型部署

  • 保存和加载模型

第四章:PyTorch之图像篇

  • 微调基于torchvision 0.3的目标检测模型

  • 微调TorchVision模型

  • 空间变换器网络

  • 使用PyTorch进行Neural-Transfer

  • 生成对抗示例

  • 使用ONNX将模型转移至Caffe2和移动端

第五章:PyTorch之文本篇

  • 聊天机器人教程

  • 使用字符级RNN生成名字

  • 使用字符级RNN进行名字分类

  • 在深度学习和NLP中使用Pytorch

  • 使用Sequence2Sequence网络和注意力进行翻译

第六章:PyTorch之生成对抗网络

第七章:PyTorch之强化学习

第二章:PyTorch之60min入门

PyTorch 自动微分

autograd 包是 PyTorch 中所有神经网络的核心。首先让我们简要地介绍它,然后我们将会去训练我们的第一个神经网络。该 autograd 软件包为 Tensors 上的所有操作提供自动微分。它是一个由运行定义的框架,这意味着以代码运行方式定义你的后向传播,并且每次迭代都可以不同。我们从 tensor 和 gradients 来举一些例子。

1、TENSOR

torch.Tensor 是包的核心类。如果将其属性 .requires_grad 设置为 True,则会开始跟踪针对 tensor 的所有操作。完成计算后,您可以调用 .backward() 来自动计算所有梯度。该张量的梯度将累积到 .grad 属性中。

要停止 tensor 历史记录的跟踪,您可以调用 .detach(),它将其与计算历史记录分离,并防止将来的计算被跟踪。

要停止跟踪历史记录(和使用内存),您还可以将代码块使用 with torch.no_grad(): 包装起来。在评估模型时,这是特别有用,因为模型在训练阶段具有 requires_grad = True 的可训练参数有利于调参,但在评估阶段我们不需要梯度。

还有一个类对于 autograd 实现非常重要那就是 Function。Tensor 和 Function 互相连接并构建一个非循环图,它保存整个完整的计算过程的历史信息。每个张量都有一个 .grad_fn 属性保存着创建了张量的 Function 的引用,(如果用户自己创建张量,则g rad_fn 是 None )。

如果你想计算导数,你可以调用 Tensor.backward()。如果 Tensor 是标量(即它包含一个元素数据),则不需要指定任何参数backward(),但是如果它有更多元素,则需要指定一个gradient 参数来指定张量的形状。

import torch

创建一个张量,设置 requires_grad=True 来跟踪与它相关的计算


 

输出:


 

针对张量做一个操作


 

输出:


 

y 作为操作的结果被创建,所以它有 grad_fn


 

输出:


 

针对 y 做更多的操作:


 

输出:


 

.requires_grad_(...) 会改变张量的requires_gra 标记。输入的标记默认为False ,如果没有提供相应的参数。


 

输出:


 

梯度:

我们现在后向传播,因为输出包含了一个标量,out.backward() 等同于out.backward(torch.tensor(1.))。

out.backward()

打印梯度  d(out)/dx


 

输出:


 

原理解释:

现在让我们看一个雅可比向量积的例子:


 

输出:


 

现在在这种情况下,y 不再是一个标量。torch.autograd 不能够直接计算整个雅可比,但是如果我们只想要雅可比向量积,只需要简单的传递向量给 backward 作为参数。


 

输出:


 

你可以通过将代码包裹在 with torch.no_grad(),来停止对从跟踪历史中 的 .requires_grad=True 的张量自动求导。


 

输出:


 

下载 Python 源代码:

autograd_tutorial.py

下载 Jupyter 源代码:

autograd_tutorial.ipynb

PyTorch神经网络

神经网络可以通过 torch.nn 包来构建。

现在对于自动梯度(autograd)有一些了解,神经网络是基于自动梯度 (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__()
        # 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(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)
)

你刚定义了一个前馈函数,然后反向传播函数被自动通过 autograd 定义了。你可以使用任何张量操作在前馈函数上。

一个模型可训练的参数可以通过调用 net.parameters() 返回:

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

输出:

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

让我们尝试随机生成一个 32x32 的输入。注意:期望的输入维度是 32x32 。为了使用这个网络在 MNIST 数据及上,你需要把数据集中的图片维度修改为 32x32。

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

输出:

tensor([[-0.0233,  0.0159, -0.0249,  0.1413,  0.0663,  0.0297, -0.0940, -0.0135,
          0.1003, -0.0559]], grad_fn=<AddmmBackward>)

把所有参数梯度缓存器置零,用随机的梯度来反向传播

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

在继续之前,让我们复习一下所有见过的类。

torch.Tensor - A multi-dimensional array with support for autograd operations like backward(). Also holds the gradient w.r.t. the tensor.

在此,我们完成了:

1.定义一个神经网络

2.处理输入以及调用反向传播

还剩下:

1.计算损失值

2.更新网络中的权重

损失函数

一个损失函数需要一对输入:模型输出和目标,然后计算一个值来评估输出距离目标有多远。

有一些不同的损失函数在 nn 包中。一个简单的损失函数就是 nn.MSELoss ,这计算了均方误差。

例如:

output = net(input)
target = torch.randn(10)  # a dummy target, for example
target = target.view(1, -1)  # make it the same shape as output
criterion = nn.MSELoss() loss = criterion(output, target)
print(loss)

输出:

tensor(1.3389, grad_fn=<MseLossBackward>)

现在,如果你跟随损失到反向传播路径,可以使用它的 .grad_fn 属性,你将会看到一个这样的计算图:

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

所以,当我们调用 loss.backward(),整个图都会微分,而且所有的在图中的requires_grad=True 的张量将会让他们的 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

输出:

<MseLossBackward object at 0x7fab77615278>
<AddmmBackward object at 0x7fab77615940>
<AccumulateGrad object at 0x7fab77615940>

反向传播

为了实现反向传播损失,我们所有需要做的事情仅仅是使用 loss.backward()。你需要清空现存的梯度,要不然帝都将会和现存的梯度累计到一起。

现在我们调用 loss.backward() ,然后看一下 con1 的偏置项在反向传播之前和之后的变化。

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)

输出:

conv1.bias.grad before backward
tensor([0., 0., 0., 0., 0., 0.])
conv1.bias.grad after backward
tensor([-0.0054,  0.0011,  0.0012,  0.0148, -0.0186,  0.0087])

现在我们看到了,如何使用损失函数。

唯一剩下的事情就是更新神经网络的参数。

更新神经网络参数:

最简单的更新规则就是随机梯度下降。

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, 等。为了让这可行,我们建立了一个小包: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 源代码:

neural_networks_tutorial.py

下载 Jupyter 源代码:

neural_networks_tutorial.ipynb

PyTorch专栏(二)的更多相关文章

  1. 【转载】PyTorch系列 (二):pytorch数据读取

    原文:https://likewind.top/2019/02/01/Pytorch-dataprocess/ Pytorch系列: PyTorch系列(一) - PyTorch使用总览 PyTorc ...

  2. PyTorch专栏开篇

    目前研究人员正在使用的深度学习框架不尽相同,有 TensorFlow .PyTorch.Keras等.这些深度学习框架被应用于计算机视觉.语音识别.自然语言处理与生物信息学等领域,并获取了极好的效果. ...

  3. 关于Pytorch的二维tensor的gather和scatter_操作用法分析

    看得不明不白(我在下一篇中写了如何理解gather的用法) gather是一个比较复杂的操作,对一个2维tensor,输出的每个元素如下: out[i][j] = input[index[i][j]] ...

  4. 如何入门Pytorch之二:如何搭建实用神经网络

    上一节中,我们介绍了Pytorch的基本知识,如数据格式,梯度,损失等内容. 在本节中,我们将介绍如何使用Pytorch来搭建一个经典的分类神经网络. 搭建一个神经网络并训练,大致有这么四个部分: 1 ...

  5. PyTorch专栏(八):微调基于torchvision 0.3的目标检测模型

    专栏目录: 第一章:PyTorch之简介与下载 PyTorch简介 PyTorch环境搭建 第二章:PyTorch之60分钟入门 PyTorch入门 PyTorch自动微分 PyTorch神经网络 P ...

  6. PyTorch专栏(六): 混合前端的seq2seq模型部署

    欢迎关注磐创博客资源汇总站: http://docs.panchuang.net/ 欢迎关注PyTorch官方中文教程站: http://pytorch.panchuang.net/ 专栏目录: 第一 ...

  7. PyTorch专栏(五):迁移学习

    专栏目录: 第一章:PyTorch之简介与下载 PyTorch简介 PyTorch环境搭建 第二章:PyTorch之60分钟入门 PyTorch入门 PyTorch自动微分 PyTorch神经网络 P ...

  8. PyTorch专栏(一)

    专栏目录: 第一章:PyTorch之简介与下载 PyTorch简介 PyTorch环境搭建 第二章:PyTorch之60min入门 PyTorch 入门 PyTorch 自动微分 PyTorch 神经 ...

  9. PyTorch(二)Intermediate

    Convolutional Neural Network import torch import torch.nn as nn import torchvision import torchvisio ...

随机推荐

  1. Redis(1)——5种基本数据结构

    一.Redis 简介 "Redis is an open source (BSD licensed), in-memory data structure store, used as a d ...

  2. SGD与Adam识别MNIST数据集

    几种常见的优化函数比较:https://blog.csdn.net/w113691/article/details/82631097 ''' 基于Adam识别MNIST数据集 ''' import t ...

  3. 一道二叉树题的n步优化——LeetCode98validate binary search tree(草稿)

    树的题目,往往可以用到三种遍历.以及递归,因为其结构上天然地可以往深处递归,且判断条件也往往不复杂(左右子树都是空的). LeetCode 98题讲的是,判断一棵树是不是二叉搜索树. 题目中给的是标准 ...

  4. 批量复制及执行命令shell脚本

    平时在处理一个或几个机器运行环境时,一个机器一个机器处理也能接受,但是如果是一批机器,几十或几百台,要是一台一台去安装环境,光是输入同一的命令,估计你自己都想吐,所有聪明的人会想一些偷懒的办法,确实可 ...

  5. java基础进阶篇(四)_HashMap------【java源码栈】

    目录 一.前言 二.特点和常见问题 二.接口定义 三.初始化构造函数 四.HashMap内部结构 五.HashMap的存储分析 六.HashMap的读取分析 七.常用方法 八.HashMap 的jav ...

  6. 使用Vagrant部署虚拟分布式开发和测试环境

    同步更新到笔者个人博客,可以访问我的博客查看原文:https://www.rockysky.tech 创建自动化配置开发环境 最近由于最近研究和学习的关系,需要经常配置和搭建多个虚拟机组成的分布式系统 ...

  7. 差分放大电路的CMRR与输入电阻分析

    分析了经典差分放大电路的共模抑制比CMRR与输入电阻RIN 1.经典差分放大电路 基于运放的经典差分放大电路在各模电教材中均能找到,利用分离电阻和运算放大器实现,如图1所示为一种差分放大电路: 图1 ...

  8. 2020年,如何成为一名 iOS 开发高手!

    2020年对应程序员来说,是一个多灾的年份,很多公司都进行了不同比例的优化和裁员.等疫情得到控制后,将会是找工作的高峰期,从去年的面试经历来看,现在只会单纯写业务代码的人找工作特别难,很多大厂的面试官 ...

  9. 关于 InnoDB 锁的超全总结

    有点全的 InnoDB 锁 几个月之前,开始深入学习 MySQL .说起数据库,并发控制是其中很重要的一部分.于是,就这样开起了 MySQL 锁的学习,随着学习的深入,发现想要更好的理解锁,需要了解 ...

  10. Python——五分钟带你弄懂迭代器与生成器,夯实代码能力

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是周一Python专题,给大家带来的是Python当中生成器和迭代器的使用. 我当初第一次学到迭代器和生成器的时候,并没有太在意,只是觉 ...