文章目录

  • 前言
  • 1 概念
  • 2 Tensor
  • 3 梯度

前言

在深度学习中,我们经常需要对函数求梯度(gradient)。PyTorch提供的autograd包能够根据输入和前向传播过程自动构建计算图,并执行反向传播。本节将介绍如何使用autograd包来进行自动求梯度的有关操作。

1 概念

Tensor是这个包的核心类,如果将其属性.requires_grad设置为True,它将开始追踪(track)在其上的所有操作(这样就可以利用链式法则进行梯度传播了)。完成计算后,可以调用.backward()来完成所有梯度计算。此Tensor的梯度将累积到.grad属性中。

注意在y.backward()时,如果y是标量,则不需要为backward()传入任何参数;否则,需要传入一个与y同形的Tensor。解释见 2.3.2 节。

如果不想要被继续追踪,可以调用.detach()将其从追踪记录中分离出来,这样就可以防止将来的计算被追踪,这样梯度就传不过去了。此外,还可以用with torch.no_grad()将不想被追踪的操作代码块包裹起来,这种方法在评估模型的时候很常用,因为在评估模型时,我们并不需要计算可训练参数(requires_grad=True)的梯度。

Function是另外一个很重要的类。TensorFunction互相结合就可以构建一个记录有整个计算过程的有向无环图(DAG)。每个Tensor都有一个.grad_fn属性,该属性即创建该TensorFunction, 就是说该Tensor是不是通过某些运算得到的,若是,则grad_fn返回一个与这些运算相关的对象,否则是None。

下面通过一些例子来理解这些概念。

2 Tensor

创建一个Tensor并设置requires_grad=True:

输出:

再做一下运算操作:

输出:

注意x是直接创建的,所以它没有grad_fn, 而y是通过一个加法操作创建的,所以它有一个为<AddBackward>grad_fn

像x这种直接创建的称为叶子节点,叶子节点对应的grad_fnNone

再来点复杂度运算操作:

输出:

通过.requires_grad_()来用in-place的方式改变requires_grad属性:

输出:

3 梯度

因为out是一个标量,所以调用backward()时不需要指定求导变量:

我们来看看out关于x的梯度 d(out)dx\frac{d(out)}{dx}dxd(out)​:

输出:

我们令out为 ooo , 因为
o=14∑i=14zi=14∑i=143(xi+2)2o=\frac14\sum_{i=1}^4z_i=\frac14\sum_{i=1}^43(x_i+2)^2 o=41​i=1∑4​zi​=41​i=1∑4​3(xi​+2)2
所以
∂o∂xi∣xi=1=92=4.5\frac{\partial{o}}{\partial{x_i}}\bigr\rvert_{x_i=1}=\frac{9}{2}=4.5 ∂xi​∂o​∣∣​xi​=1​=29​=4.5
所以上面的输出是正确的。

数学上,如果有一个函数值和自变量都为向量的函数 y⃗=f(x⃗)\vec{y}=f(\vec{x})y​=f(x), 那么 y⃗\vec{y}y​ 关于 x⃗\vec{x}x 的梯度就是一个雅可比矩阵(Jacobian matrix):
J=(∂y1∂x1⋯∂y1∂xn⋮⋱⋮∂ym∂x1⋯∂ym∂xn)J=\left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}}\\ \vdots & \ddots & \vdots\\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right) J=⎝⎜⎛​∂x1​∂y1​​⋮∂x1​∂ym​​​⋯⋱⋯​∂xn​∂y1​​⋮∂xn​∂ym​​​⎠⎟⎞​
torch.autograd这个包就是用来计算一些雅克比矩阵的乘积的。例如,如果 vvv 是一个标量函数的 l=g(y⃗)l=g\left(\vec{y}\right)l=g(y​) 的梯度:
v=(∂l∂y1⋯∂l∂ym)v=\left(\begin{array}{ccc}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right) v=(∂y1​∂l​​⋯​∂ym​∂l​​)
那么根据链式法则我们有 lll 关于 x⃗\vec{x}x 的雅克比矩阵就为:
vJ=(∂l∂y1⋯∂l∂ym)(∂y1∂x1⋯∂y1∂xn⋮⋱⋮∂ym∂x1⋯∂ym∂xn)=(∂l∂x1⋯∂l∂xn)v J=\left(\begin{array}{ccc}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right) \left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}}\\ \vdots & \ddots & \vdots\\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right)=\left(\begin{array}{ccc}\frac{\partial l}{\partial x_{1}} & \cdots & \frac{\partial l}{\partial x_{n}}\end{array}\right) vJ=(∂y1​∂l​​⋯​∂ym​∂l​​)⎝⎜⎛​∂x1​∂y1​​⋮∂x1​∂ym​​​⋯⋱⋯​∂xn​∂y1​​⋮∂xn​∂ym​​​⎠⎟⎞​=(∂x1​∂l​​⋯​∂xn​∂l​​)

注意:grad在反向传播过程中是累加的(accumulated),这意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前需把梯度清零。

输出:

我们规定不允许张量对张量求导,只允许标量对张量求导,求导结果是和自变量同形的张量。所以必要时我们要把张量通过将所有张量的元素加权求和的方式转换为标量,举个例子,假设y由自变量x计算而来,w是和y同形的张量,则y.backward(w)的含义是:先计算l = torch.sum(y * w),则l是个标量,然后求l对自变量x的导数。
参考

来看一些实际例子。

输出:

现在 z 不是一个标量,所以在调用backward时需要传入一个和z同形的权重向量进行加权求和得到一个标量。

输出:

注意,x.grad是和x同形的张量。

再来看看中断梯度追踪的例子:

输出:

可以看到,上面的y2是没有grad_fn而且y2.requires_grad=False的,而y3是有grad_fn的。如果我们将y3x求梯度的话会是多少呢?

y3.backward()
print(x.grad)

输出:

为什么是2呢?y3=y1+y2=x2+x3y_3 = y_1 + y_2 = x^2 + x^3y3​=y1​+y2​=x2+x3,当 x=1x=1x=1 时 dy3dx\frac {dy_3} {dx}dxdy3​​ 不应该是5吗?事实上,由于 y2y_2y2​ 的定义是被torch.no_grad():包裹的,所以与 y2y_2y2​ 有关的梯度是不会回传的,只有与 y1y_1y1​ 有关的梯度才会回传,即 x2x^2x2 对 xxx 的梯度。

上面提到,y2.requires_grad=False,所以不能调用 y2.backward(),会报错:

此外,如果我们想要修改tensor的数值,但是又不希望被autograd记录(即不会影响反向传播),那么我么可以对tensor.data进行操作。

输出:

pytorch学习笔记(二):自动求梯度相关推荐

  1. PyTorch学习笔记(二)——回归

    PyTorch学习笔记(二)--回归 本文主要是用PyTorch来实现一个简单的回归任务. 编辑器:spyder 1.引入相应的包及生成伪数据 import torch import torch.nn ...

  2. 《动手学深度学习 PyTorch版》学习笔记(二):自动求梯度

    一.自动求梯度 1.requires_grad_(), detach(), torch.no_grad()的区别 参考博客:https://www.jianshu.com/p/ff74ccae25f3 ...

  3. PyTorch入门学习(二):Autogard之自动求梯度

    autograd包是PyTorch中神经网络的核心部分,简单学习一下. autograd提供了所有张量操作的自动求微分功能. 它的灵活性体现在可以通过代码的运行来决定反向传播的过程, 这样就使得每一次 ...

  4. PyTorch学习笔记(二):PyTorch简介与基础知识

    往期学习资料推荐: 1.Pytorch实战笔记_GoAI的博客-CSDN博客 2.Pytorch入门教程_GoAI的博客-CSDN博客 本系列目录: PyTorch学习笔记(一):PyTorch环境安 ...

  5. Pytorch总结一之 数据操作、类型转换、数学计算、自动求梯度

    Pytorch总结一 在PyTorch中, torch.Tensor 是存储和变换数据的主要⼯具.如果你之前⽤过NumPy,你会发现Tensor 和NumPy的多维数组⾮常类似.然⽽, Tensor ...

  6. pytorch学习笔记(二):gradien

    pytorch学习笔记(二):gradient 2017年01月21日 11:15:45 阅读数:17030

  7. Polyworks脚本开发学习笔记(二二)-调取视角用脚本自动生成报告

    Polyworks脚本开发学习笔记(二二)-调取视角用脚本自动生成报告 Polyworks中,3D场景的视图可用标准视角及等轴侧视角.项目视角等方式调用,也可以用txt格式保存下来调用,如果以脚本的形 ...

  8. 《动手学深度学习》 第二天 (自动求梯度)

    2.3.自动求梯度 MXNet提供的autograd模块可以用来自动求梯度. 2.3.1 一个简单的栗子 这里我们要求对函数 y = 2xTx (2乘以x的转秩乘以X)求关于列向量 x 的梯度.(使用 ...

  9. 深度学习入门之PyTorch学习笔记:多层全连接网络

    深度学习入门之PyTorch学习笔记 绪论 1 深度学习介绍 2 深度学习框架 3 多层全连接网络 3.1 PyTorch基础 3.2 线性模型 3.2.1 问题介绍 3.2.2 一维线性回归 3.2 ...

最新文章

  1. python3安装pip3-Python3中安装pip3
  2. UML用例图总结来源于网络
  3. springboot接收json参数_Springboot + Vue + shiro 实现前后端分离、权限控制
  4. 三星Galaxy Note10系列带壳渲染图曝光:将取消3.5mm耳机孔
  5. thinkphp3.2.3漏洞_Chrome新版本修复CVE202015999 0 day漏洞
  6. 深度学习-语音处理-语音分离入门学习(Speech separation)
  7. 为什么中国有很大一部分人不愿使用windows10?
  8. Java设计模式05:常用设计模式之原型模式(创建型模式)
  9. java日志分级概要
  10. WebGrid Enterprise免费下载
  11. html5ie11缩放,IE 11 页面缩放后再次打开不能保存之前的缩放比例
  12. Pycharm下载pytorch
  13. 【招聘】上海微创医疗机器人集团 - 软件工程师/图像算法工程师
  14. 谷歌浏览器如何给长网页截图?
  15. DiskMan使用方法
  16. 嵌入式主板开发设计需要考虑哪些因素?
  17. 03-元素定位-基本
  18. 学人工智能需要什么学历?AI学历要求
  19. iOS开发常用国外网站清单
  20. Win软件 - 无法卸载 Windows 版 iCloud,因为您当前已登录到 Windows 版 iCloud 之解决方案

热门文章

  1. 高阶台式计算机零组件,2010年电脑旺季!零组件缺DDR3封测紧
  2. phpnow 更改mysql data文件夹路径
  3. 【案例】保健品行业如何优化供应链管理?APS系统来帮忙
  4. Could not load file or assembly (Exception from HRESULT: 0x80131047)-解决办法
  5. Android日期格式化
  6. 快速查找Hashtable中的元素
  7. 【Spring 持久层】Spring 与 Mybatis 整合
  8. Mybatis逆向工程(生成实体类)开发指南
  9. Windows远程桌面(mstsc) 无法全屏显示的解决方法
  10. 博客主机_自动申请续期免费证书