一、梯度计算准备工作

调用backward()函数前,叶子/非叶子节点的grad属性均为none,无论是否设置了requires_grad=True(叶子节点),或者调用了retain_grad()(非叶子节点),非叶子节点不能设置requires_grad=True,否则会报错:“RuntimeError: you can only change requires_grad flags of leaf variables.”)。

叶子/非叶子节点定义:

1.叶子节点:

  • 所有requires_grad为false的tensor都是叶子节点,也即is_leaf属性返回true。
  • 若tensor的requires_grad为true,同时是由用户创建,则该tensor为叶子节点。也即不是operation结果的tensor,叶子节点的grad_fn为none。
  • 由requires_grad为false的节点通过operation产生的节点还是叶子节点,此时设置requires_grad为true,不影响是否为叶子节点,但会影响后续节点是否为叶子节点。猜想这么设计的原因是:由于无法判断是否是由operation产生的节点,因此通过设置requires_grad也就无法更新是否为叶子节点。

示例如下:

>>> a = torch.randn((3, 4))
>>> a
tensor([[-1.0351, -0.2712,  2.4718,  0.4248],[ 0.9309,  0.7676, -0.1888, -0.0586],[-0.4290,  0.2478, -0.0056,  0.8502]])
>>> b = torch.randn((3, 4))
>>> b
tensor([[ 0.5519,  0.3557,  0.2577, -0.6338],[ 1.2905,  2.1761, -0.1334, -1.3477],[ 0.8308,  0.1957,  0.1915,  0.1244]])
>>> c = a + b
>>> c.requires_grad
False
>>> c.is_leaf
True
>>> c.requires_grad = True
>>> c.is_leaf
True
// c的requires_grad为true,同时是由operation产生,但是仍为叶子节点,说明requires_grad状态的改变并不能影响是否为叶子节点。

2.非叶子节点

  • 由requires_grad为true的节点通过operation产生,同时operation是可以求导的操作,否则仍为叶子节点。此处对于多元operation,有一个输入是requires_grad为true的节点即可获得非叶子节点。

示例如下:

>>> c
tensor([[-0.4832,  0.0846,  2.7295, -0.2089],[ 2.2214,  2.9437, -0.3222, -1.4063],[ 0.4018,  0.4435,  0.1859,  0.9746]], requires_grad=True)
>>> g = c > 0
>>> g
tensor([[False,  True,  True, False],[ True,  True, False, False],[ True,  True,  True,  True]])
>>> g.is_leaf
True
>>> c
tensor([[-0.4832,  0.0846,  2.7295, -0.2089],[ 2.2214,  2.9437, -0.3222, -1.4063],[ 0.4018,  0.4435,  0.1859,  0.9746]], requires_grad=True)
>>> g = c.sum()
>>> g
tensor(7.5644, grad_fn=<SumBackward0>)
>>> g.is_leaf
False

叶子/非叶子节点获得grad的方法:

1.叶子节点

  • 设置requires_grad为true

2.非叶子节点

  • 调用retain_grad()。

仅叶子节点,调用backward()后,存在grad。

若某个节点的输入节点的requires_grad为True,则该节点的grad_fn必不为none,该节点的梯度就可以通过调用backward()自动计算。loss计算梯度依据的条件同样如此。

二、梯度计算相关内容

1.使用backward()计算梯度

调用backward()函数后,

  • 对于叶子节点,若设置了requires_grad为true,则可以获得梯度,否则梯度为none。
  • 对于非叶子节点,若调用了retain_grad(),则可以获得梯度,否则梯度也为none。

若计算图中没有一个节点设置了requires_grad为true,则经过loss函数计算的结果仅包含计算结果,grad_fn为none,此时调用backward()函数会出错,错误提示信息如下:

“RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn”

解决方法:将计算图中任意一个节点,设置为requires_grad为true,或者调用retain_grad(),并重新计算loss。

若仅设置requires_grad为true,或者调用retain_grad(),不重新计算loss,loss的grad_fn还是none,此时调用backward(),还是会出现上面的错误。

2.调用backward()函数需要注意的问题:

  • 仅标量可以通过backward()计算梯度,若为非标量调用backward(),会出现以下错误:“RuntimeError: grad can be implicitly created only for scalar outputs”
  • 在调用backward()函数时需要将retain_graph设置为True,否则梯度只能计算一次,第二次再调用backward时,会出现如下错误:“RuntimeError: Trying to backward through the graph a second time, but the saved intermediate results have already been freed. Specify retain_graph=True when calling backward the first time.”
  • 对于tensor可以使用.grad.zero_()对梯度清零。
  • 在使用torch.tensor()初始化tensor时需要保证数据为float或者为复数类型,否则无法设置requires_grad为True。错误提示如下:“RuntimeError: Only Tensors of floating point and complex dtype can require gradients”。
  • 在初始化tensor时如果是使用torch.Tensor初始化则没有requires_grad参数,torch.Tensor是一个类,是torch.FloatTensor的别名,因此默认初始化数据为float32类型,但是requires_grad需要单独设置。如果使用torch.tensor初始化,则可以直接设置requires_grad这一参数,但需要注意使用float类型数据,torch.tensor是一个函数。

pytorch 梯度计算相关内容总结相关推荐

  1. Pytorch 梯度计算,叶子节点,requires_grad,detach

    Pytorch 梯度计算,叶子节点,requires_grad,detach 前言 梯度计算 叶子节点 张量requires_grad属性修改,detach 前言 本篇记录pytorch中梯度相关内容 ...

  2. pytorch——梯度计算

    一.梯度介绍 梯度是一个向量,是学习(参数更新的方向).收集数据,构建机器学习模型,得到 判断模型好坏的方法: (回归损失) (分类损失) 通过调整参数,尽可能降低 随机选择一个起始,通过调整,使得函 ...

  3. 通俗讲解Pytorch梯度的相关问题:计算图、torch.no_grad、zero_grad、detach和backward;Variable、Parameter和torch.tensor

    文章目录 with torch.no_grad()和requires_grad backward() Variable,Parameter和torch.tensor() zero_grad() 计算图 ...

  4. pytorch的梯度计算以及backward方法

    基础知识 tensors: tensor在pytorch里面是一个n维数组.我们可以通过指定参数reuqires_grad=True来建立一个反向传播图,从而能够计算梯度.在pytorch中一般叫做d ...

  5. Pytorch中的向前计算(autograd)、梯度计算以及实现线性回归操作

    在整个Pytorch框架中, 所有的神经网络本质上都是一个autograd package(自动求导工具包) autograd package提供了一个对Tensors上所有的操作进行自动微分的功能. ...

  6. pytorch得到梯度计算结果

    借助pytorch可以很方便的计算梯度,但需要明确的是: 只有float类型的Tensor才可以 只有最后是一个标量才可以求导,就是最后的值只有大小,不能自带方向 文章目录 逐步计算梯度 完整代码 参 ...

  7. pytorch梯度的计算过程

    1.基础知识: 与numpy中的基本操作相似, pytorch 的作用是引入GPU加快运算, 增加图形界面, 适合大数据运算, 尤其是deep learning gradient 梯度类似于求导, 找 ...

  8. pytorch局部范围内禁用梯度计算,no_grad、enable_grad、set_grad_enabled使用举例

    参考链接: Locally disabling gradient computation-1 参考链接: Locally disabling gradient computation-2 参考链接: ...

  9. python中backward_pytorch的梯度计算以及backward方法详解

    基础知识 tensors: tensor在pytorch里面是一个n维数组.我们可以通过指定参数reuqires_grad=True来建立一个反向传播图,从而能够计算梯度.在pytorch中一般叫做d ...

最新文章

  1. window.location操作url对象
  2. wlan端口服务器无响应,wlan项目遇到的问题,总结
  3. ant Design表单验证笔记
  4. SmartUpload 中文API帮助
  5. [转]【Linux】一幅图秒懂LoadAverage(负载)
  6. 为什么hashtable中桶的数目都是用质数表示
  7. c51流水灯实验报告汇编语言,51单片机流水灯实验报告.doc
  8. Quuppa_基站灯闪烁原因
  9. 3 staruml 流程图,staruml流程图(staruml怎么画顺序图)
  10. Android组件化开发实践和案例分享
  11. 分布式专题——接口幂等性实战
  12. 百度TTS,支持离线环境下使用
  13. Catia V5-6R2016软件安装教程——附下载地址
  14. java 知网 语义 相似度,基于知网语义相似度的中文文本分类研究 论文笔记
  15. 指数多项式的Galois群计算
  16. $monitor用法
  17. 如何推广微信公众号 微信公众号推广技巧
  18. 【黑苹果升级到ventura13】 Y7000P-2018升级到 ventura13
  19. handoff (wimax of nist)
  20. 工作中实用的 Linux 命令

热门文章

  1. 新加坡没有改变对 Web3 的立场
  2. C语言中用单引号括起多个字符的问题
  3. 深度技术GHOST WIN7 SP1 2013 新春版
  4. C/C++中宏概念理解
  5. ant design vue table 高度自适应_很受欢迎的vue前端UI框架
  6. UE4开发三:创建游戏模式、角色、控制器
  7. ASK调制的matlab代码
  8. 如何放慢selenium的运行速度
  9. Java 实现蓝桥杯不同非空子串
  10. K8s学习之yum安装