自动求梯度

  • 1. 函数对自变量x求梯度--ax^2+b
  • 2. 网络对参数w求梯度- loss(w,x)
  • 3. 自动求梯度的底层支持--torch.autograd
    • 3.1 Variable
      • 3.1.1 Variable构造函数
      • 3.1.2 Variable链式求导--backward()
      • 3.1.3 Variable反向传播函数--grad_fn
    • 3.2 计算图
      • 3.2.1 动态创建计算图
      • 3.2.2 非叶子节点的梯度--autograd.grad 与 hook
    • 3.3 复杂自建函数,自动求导支持

1. 函数对自变量x求梯度–ax^2+b

torch提供了简便的求梯度方法:带入变量值x,求解目标函数f(x),将目标函数的值反向传播f.backward(),就能计算对应变量的导数。

  1. 以二次函数为例:f(x)=ax2+bf(x)=ax^2+bf(x)=ax2+b
  2. 其中a,b是已知的参数,对x 求导:f′(x)=2axf'(x)=2axf′(x)=2ax
  3. 当a=1,x=1时a=1,x=1时a=1,x=1时:f′(x)=2f'(x)=2f′(x)=2
import torch
from torch.autograd import Variable
def f(x):return x**2
x1 = Variable(torch.Tensor([1]),requires_grad=True)  # 使用variable封装待求导的参数
print("初始化", x1.grad)y=f(x1)
y.backward()
print("一次传播", x1.grad)x1.grad.data.zero_()
print("梯度置零", x1.grad)y=f(x1)
y.backward()
y=f(x1)              # #如果x1.grad 每次计算前梯度不归零,那么当前的梯度会与原来的梯度累加
y.backward()         # #每次loss 反向传播前需要将梯度设置为0
print("二次传播", x1.grad)

输出

初始化 None
一次传播 tensor([2.])
梯度置零 tensor([0.])
二次传播 tensor([4.])

2. 网络对参数w求梯度- loss(w,x)

神经网络训练:通过调整神经网络参数使网络输出尽可能接近于想要的对象。具体通过损失函数的梯度下降实现的,即损失函数对网络参数求梯度,利用该梯度调整网络参数。

模型的损失函数实际是输入x 和模型参数w 的函数:loss(w,x)。依据part1demo流程,随机初始化w后,输入观测数据x(图像 或者 其他需要分类或者回归的数据)。loss(w, x).backward()就可以求出对应的网络参数w的梯度。再利用各种优化算法(SGD,admn)更新各个网络参数w即可。
pytorch 网络训练的流程

  1. 搭建好网络:net()
  2. 数据x输入网络:y=net(x,w)
  3. 网络输出y与标签label计算标量损失函数:loss(y,label,w)
  4. 损失函数loss()反向传播:loss.backward()->通过自动求导Adagrad实现
  5. 网络参数更新:net.parameters().step()->通过优化器实现

注意事项:在每次损失函数反向传播计算梯度时,原本的参数梯度必须设置为0。否则,各个参数的梯度会累加之前的梯度。网络参数梯度置0:

optimizer=torch.optim.SGD(net.parameters(),lr=0.001,momentum=0.1)
optimizer.zero_grad()
loss.backward()

3. 自动求梯度的底层支持–torch.autograd

torch.autograd 是一套自动求导引擎,能够根据输入前向传播过程自动构建计算图,并执行反向传播. 计算图是深度学习框架的核心。

[本节为陈云<<深度学习框架-pytorch 入门与实践>>一书第3.2章的内容autograd 读书笔记.]

pytorch 中 autograd模块 实现了 计算图 相关功能. autograd 的核心数据结构Variable。
pytorch 中 autograd模块 底层采用 计算图 实现梯度计算。

3.1 Variable

Variable中封装了以下三个部分内容

  1. data : 保存数据tensor
  2. grad : 保存data对应的梯度,形状与data一致,也是一个Variable
  3. grad_fn : 指向一个Function,记录Variable操作历史,如果一个变量是由用户创建的,则他为叶子节点,对应的grad_fn为None.

3.1.1 Variable构造函数

Variable的构造函数–需要传入tensor,还有两个可选参数:

  1. requires_grad : bool 是否需要对该variable进行求导
  2. volatile : bool 为True , 那么基于该variable 构建的图都不会求导,转为推理阶段设计.

volatile优先级别比requires_grad高。在计算路径上同时存在requires_grad=True 和 volatile=True 的变量,那么其后的通过计算得出的变量的requires_grad 为False.

3.1.2 Variable链式求导–backward()

Variable支持大部分的tensor操作,但不支持部分inplace函数。如果想要计算各个Variable的梯度,只需要调用根节点variable的backward方法,autograd 会自动沿计算图反向传播,计算每一个叶子节点的梯度.

Variable.backward(grad_variables=None,retain_graph=None,create_graph=None)

  1. grad_variables : 相当与链式法则∂z∂x=∂z∂y∂y∂x\frac{\partial z}{\partial x}=\frac{\partial z}{\partial y}\frac{\partial y}{\partial x}∂x∂z​=∂y∂z​∂x∂y​中的∂z∂y\frac{\partial z}{\partial y}∂y∂z​ 。y.backward(grad_y) 等价于 z.backward()

  2. retain_graph : 反向传播中会缓存一些中间结果,反向传播结束后缓存被清空。可以通过指定这个参数不清空缓存,用于多次反向传播。

  3. create_graph : 反向传播过程中再次构建计算图,通过backward of backward实现高阶求导.

3.1.3 Variable反向传播函数–grad_fn

variable变量的grad_fn 属性可以用来查看反向传播函数, next_functions保存grad_fn的输入,是一个tuple。每个变量在图中的位置可以通过grad_fn 属性在图中的位置推测得到。每一个前向传播函数都有一个与之对应的反向传播函数,用来计算各个输入变量的梯度;这些函数以Backward结尾。

x=Variable(torch.ones(1))
b=Variable(torch.rand(1,requires_grad=True))
w=Variable(torch.rand(1),requires_grad=True)
y=w*x
z=y+b
z.grad_fn                               # 查看z的反向传播函数
Out[16]: <AddBackward0 at 0x7f84b0a0e3c8>z.grad_fn.next_functions               # z 反向传播函数的输入,一个为y.grad_fn(为MulBackward0),另一个是b.grad_fn(为none)
Out[17]: ((<MulBackward0 at 0x7f84903a9588>, 0), (None, 0))y.grad_fn
Out[27]: <MulBackward0 at 0x7f84903a9588>
y.grad_fn.next_functions
Out[19]: ((<AccumulateGrad at 0x7f84b0a0ee10>, 0), (None, 0))z.backward(retain_graph=True)           # 保留中间结果
w.grad
Out[23]: tensor([1.])z.backward(retain_graph=True)           # 保留中间结果, 才能二次传播
w.grad
Out[26]:tensor([2.])                    # 这个为2 不是保留中间结果的原因,而是两次梯度传播

3.2 计算图

pytorch 中 autograd模块 底层采用 计算图 实现梯度计算。计算图是一种特殊的有向无环图 , 用于记录算子变量 之间的关系。

在pytorch 中autograd模块会随着用户操作,记录生成当前 variable 的所有操作。以此建立一个有向无环图(每个变量都有一个有向无环图?还以一个计算过程有一个?应该是一个计算过程有一个图)。用户每进行一次操作,计算图就会变化。对应的变化会通3.1.3 的grad_fn 记录

3.2.1 动态创建计算图

pytorch 的计算图在每次前向传播的时候都是从头开始构建的 , 所以能够利用python的控制语句(for,if) 根据需求 创建动态图.

少一个例子

3.2.2 非叶子节点的梯度–autograd.grad 与 hook

在反向传播的过程中,非叶子节点的导数在计算完成之后即被清空,若想查看这些变量的梯度,有两种方法:autograd.grad 与 hook。

torch.autograd.grad()

In [28]: x=Variable(torch.ones(3),requires_grad=True)
In [30]: w=Variable(torch.ones(3),requires_grad=True)
In [31]: y=x*w
In [32]: z=y.sum()
In [33]: z.backward()
In [34]: (x.grad,w.grad,y.grad)
Out[34]: (tensor([1., 1., 1.]), tensor([1., 1., 1.]), None)   # y.grad的梯度计算完被释放掉了
# 使用torch.autograd.grad()计算中间节点的梯度
In [35]: torch.autograd.grad(z,y)      # 求Z对Y的梯度
Out[35]: (tensor([1., 1., 1.]),)

hook 呢?

Pytorch(5)-梯度反向传播相关推荐

  1. pytorch 入门学习反向传播-4

    pytorch 入门学习反向传播 反向传播 import numpy as np import matplotlib.pyplot as plt import torchdef forward(x): ...

  2. 梯度反向传播过程中,测试强行修改后的预测结果是否还会传递loss?

    在深度学习计算损失函数的过程中,我一直有这样一个问题,如果Label是1.0,而预测结果是0.0,则BCE损失中理论上计算出的结果是无穷大的(当然pytorch并不会报错,而是将损失上限设在了100. ...

  3. 损失函数与优化器理解+【PyTorch】在反向传播前为什么要手动将梯度清零?optimizer.zero_grad()

    目录 回答一: 回答二: 回答三: 传统的训练函数,一个batch是这么训练的: 使用梯度累加是这么写的: 回答一: 一句话,用来更新和计算影响模型训练和模型输出的网络参数,使其逼近或达到最优值,从而 ...

  4. 梯度反向传播求解示例

    深度学习中进行网络的训练的时候,常常采用梯度反向传递的方式对网络中的参数进行调整,那么具体是怎么实现的呢?我用一个简单的例子进行推导求解. 如下图,这里采用的是两层网络,损失函数采用的是平方差损失函数 ...

  5. Pytorch专题实战——反向传播(Backpropagation)

    文章目录 1.前言 2.初识如何更新梯度 3.手动更新梯度 4.自动更新梯度 1.前言 大体分为三步: (1)前向传播,计算loss (2)计算局部梯度 (3)反向传播,用链式求导法则计算梯度 2.初 ...

  6. 梯度反向传播(CS231n课程笔记翻译)

    CS231n课程笔记翻译:反向传播笔记 - 杜客的文章 - 知乎 译者注:本文智能单元首发,译自斯坦福CS231n课程笔记Backprop Note,课程教师Andrej Karpathy授权翻译.本 ...

  7. pytorch 正向与反向传播的过程 获取模型的梯度(gradient),并绘制梯度的直方图

    记录一下怎样pytorch框架下怎样获得模型的梯度 文章目录 引入所需要的库 一个简单的函数 模型梯度获取 先定义一个model 如下定义两个获取梯度的函数 定义一些过程与调用上述函数的方法 可视化一 ...

  8. 神经网络梯度反向传播公式

    考虑三层网络: 输出层没有激活函数,只有中间层有: y=Wout⋅tanh(Win⋅x)y = W_{out}\cdot tanh(W_{in}\cdot x)y=Wout​⋅tanh(Win​⋅x) ...

  9. PyTorch 入坑四 梯度、链式法则、计算图与反向传播

    PyTorch 一文入门 PyTorch 入坑四:计算图与反向传播 导数.梯度与最优化 方向导数与梯度 最优化 复合函数求梯度 计算图 PyTorch实战 PyTorch中的动态图机制 PyTorch ...

最新文章

  1. 解决Windows Git Bash中文乱码问题
  2. 多用户使用一台计算机可设置,《计算机应用基础》试卷(A)
  3. cython编码报错
  4. netty里集成spring注入mysq连接池(二)
  5. 通过这5个简单的技巧减少GC开销
  6. android Intent 全面点的介绍
  7. 农村大学生的出路或许是读个真才实学的博士
  8. 百倍加速!Python量化策略的算法性能提升指南
  9. AI进军B-Box界:输入20秒任意声音,还你一段定制的B-Box演奏
  10. python for mac下载_Python for Mac
  11. linux jdk11 64位下载安装
  12. 深度学习涉及到的线性代数知识点总结(二)
  13. 中文论文检索证明怎么开_SCI论文检索后收录证明怎么开?
  14. 计划预算(PV)、实际完成工作预算(EV)、实际成本(AC)
  15. 前端实现GIF图片压缩上传
  16. MODBUS-RTU协议主机和从机代码STM32 包含2个程序代码,主机和从机
  17. java 将字符串集合转换成字符串并以顿号隔开
  18. 月份对比_2020年5月份,四款主流游戏电脑配置横向对比,你会选择哪款呢?
  19. 计算机网络之五层体系结构
  20. matlab 三维相交面,MATLAB画三维图时如何画相交部分

热门文章

  1. C语言的putpiel函数,C语言graphics.h函数介绍
  2. mysql修改语句_序言:MySQL与Navicat安装Tips
  3. python中如何标识语句块_如何用python在一个块中编写多个try语句?
  4. php公交查询系统源代码,基于Smarty公交查询系统的设计与实现(PHP,MySQL)
  5. g5420 win7集显驱动_台式机装WIN7?雷我已经趟完了
  6. C#多线程编程系列(二)- 线程基础
  7. 关于w3wp.exe
  8. ROS机器人导航仿真(kinetic版本)
  9. 与gps优缺点_长缨在手,敢缚苍龙,中国北斗三号圆满收官,相比美国GPS怎样?...
  10. 【POJ - 2965】The Pilots Brothers' refrigerator(暴力枚举,思维)