关于Pytorch中autograd和backward的一些笔记
参考自《Pytorch autograd,backward详解》:
1 Tensor
Pytorch中所有的计算其实都可以回归到Tensor上,所以有必要重新认识一下Tensor。
如果我们需要计算某个Tensor的导数,那么我们需要设置其.requires_grad
属性为True
。为方便说明,在本文中对于这种我们自己定义的变量,我们称之为叶子节点(leaf nodes),而基于叶子节点得到的中间或最终变量则可称之为结果节点。
另外一个Tensor中通常会记录如下图中所示的属性:
data
: 即存储的数据信息requires_grad
: 设置为True
则表示该 Tensor 需要求导grad
: 该 Tensor 的梯度值,每次在计算 backward 时都需要将前一时刻的梯度归零,否则梯度值会一直累加,这个会在后面讲到。grad_fn
: 叶子节点通常为 None,只有结果节点的 grad_fn 才有效,用于指示梯度函数是哪种类型。is_leaf
: 用来指示该 Tensor 是否是叶子节点。
举例:
x = torch.rand(3, requires_grad=True)
y = x ** 2
z = x + x print(
'x requires grad: {}, is leaf: {}, grad: {}, grad_fn: {}.'
.format(x.requires_grad, x.is_leaf, x.grad, x.grad_fn)
)
print(
'y requires grad: {}, is leaf: {}, grad: {}, grad_fn: {}.'
.format(y.requires_grad, y.is_leaf, y.grad, y.grad_fn)
)
print(
'z requires grad: {}, is leaf: {}, grad: {}, grad_fn: {}.'
.format(z.requires_grad, z.is_leaf, z.grad, z.grad_fn)
)
运行结果:
x requires grad: True, is leaf: True, grad: None, grad_fn: None.
y requires grad: True, is leaf: False, grad: None, grad_fn: <PowBackward0 object at 0x0000021A3002CD88>.
z requires grad: True, is leaf: False, grad: None, grad_fn: <AddBackward0 object at 0x0000021A3002CD88>.
2 torch.autograd.backward
如下代码:
x = torch.tensor(1.0, requires_grad=True)
y = torch.tensor(2.0, requires_grad=True)
z = x**2+y
z.backward()
print(z, x.grad, y.grad) >>> tensor(3., grad_fn=<AddBackward0>) tensor(2.) tensor(1.)
当 z 是一个标量,当调用它的 backward 方法后会根据链式法则自动计算出叶子节点的梯度值。
但是如果遇到 z 是一个向量或者是一个矩阵的情况,这个时候又该怎么计算梯度呢?这种情况我们需要定义grad_tensor
来计算矩阵的梯度。在介绍为什么使用之前我们先看一下源代码中backward的接口是如何定义的:
torch.autograd.backward(
tensors,
grad_tensors=None,
retain_graph=None,
create_graph=False,
grad_variables=None)
tensor
: 用于计算梯度的 tensor。也就是说这两种方式是等价的:torch.autograd.backward(z) == z.backward()
grad_tensors
: 在计算非标量的梯度时会用到。他其实也是一个tensor,它的shape一般需要和前面的tensor
保持一致。retain_graph
: 通常在调用一次 backward 后,pytorch 会自动把计算图销毁,所以要想对某个变量重复调用 backward,则需要将该参数设置为True
create_graph
: 当设置为True
的时候可以用来计算更高阶的梯度grad_variables
: 这个官方说法是 grad_variables' is deprecated. Use 'grad_tensors' instead. 也就是说这个参数后面版本中应该会丢弃,直接使用grad_tensors
就好了。
pytorch设计了grad_tensors
这么一个参数。它的作用相当于“权重”。
先看一个例子:
x = torch.ones(2,requires_grad=True)
z = x + 2
z.backward() >>> ...
RuntimeError: grad can be implicitly created only for scalar outputs
上面的报错信息意思是只有对标量输出它才会计算梯度,而求一个矩阵对另一矩阵的导数束手无策。
$X = \begin{bmatrix} x_0 & x_1 \end{bmatrix} \Rightarrow Z = \begin{bmatrix} x_0 + 2 & x_1 + 2 \end{bmatrix} \Rightarrow \frac{\partial Z}{\partial X} = ?$
那么我们只要想办法把 $Z$ 转变成一个标量不就好了?比如我们可以对 $Z$ 求和,然后用求和得到的标量在分别对 $x_0, x_1$ 求导,这样不会对结果有影响,例如:
$Z_{sum} = \sum z_i = x_0 + x_1 + 4$
$\frac{\partial Z_{sum}}{\partial x_0} = \frac{\partial Z_{sum}}{\partial x_1} = 1$
x = torch.ones(2,requires_grad=True)
z = x + 2
z.sum().backward()
print(x.grad) >>> tensor([1., 1.])
而grad_tensors
这个参数就扮演了帮助求和的作用。
换句话说,就是对 $Z$ 和一个权重张量grad_tensors
进行 hadamard product 后求和。这也是 grad_tensors 需要与传入的 tensor 大小一致的原因。
x = torch.ones(2,requires_grad=True)
z = x + 2
z.backward(torch.ones_like(z)) # grad_tensors需要与输入tensor大小一致
print(x.grad) >>> tensor([1., 1.])
3 torch.autograd.grad
torch.autograd.grad(
outputs,
inputs,
grad_outputs=None,
retain_graph=None,
create_graph=False,
only_inputs=True,
allow_unused=False)
看了前面的内容后再看这个函数就很好理解了,各参数作用如下:
outputs
: 结果节点,即被求导数inputs
: 叶子节点grad_outputs
: 类似于backward
方法中的grad_tensors
retain_graph
: 同上create_graph
: 同上only_inputs
: 默认为True
,如果为True
,则只会返回指定input
的梯度值。 若为False
,则会计算所有叶子节点的梯度,并且将计算得到的梯度累加到各自的.grad
属性上去。allow_unused
: 默认为False
, 即必须要指定input
,如果没有指定的话则报错。
注意该函数返回的是 tuple 类型。
关于Pytorch中autograd和backward的一些笔记的更多相关文章
- Pytorch中的自动求导函数backward()所需参数含义
摘要:一个神经网络有N个样本,经过这个网络把N个样本分为M类,那么此时backward参数的维度应该是[N X M] 正常来说backward()函数是要传入参数的,一直没弄明白backward需要传 ...
- pytorch学习-AUTOGRAD: AUTOMATIC DIFFERENTIATION自动微分
参考:https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autog ...
- pytorch 中的重要模块化接口nn.Module
torch.nn 是专门为神经网络设计的模块化接口,nn构建于autgrad之上,可以用来定义和运行神经网络 nn.Module 是nn中重要的类,包含网络各层的定义,以及forward方法 对于自己 ...
- pytorch中调用C进行扩展
pytorch中调用C进行扩展,使得某些功能在CPU上运行更快: 第一步:编写头文件 /* src/my_lib.h */ int my_lib_add_forward(THFloatTensor * ...
- PyTorch中的C++扩展
今天要聊聊用 PyTorch 进行 C++ 扩展. 在正式开始前,我们需要了解 PyTorch 如何自定义module.这其中,最常见的就是在 python 中继承torch.nn.Module,用 ...
- [源码解析] PyTorch 分布式 Autograd (1) ---- 设计
[源码解析] PyTorch 分布式 Autograd (1) ---- 设计 目录 [源码解析] PyTorch 分布式 Autograd (1) ---- 设计 0x00 摘要 0x01 分布式R ...
- [源码解析] PyTorch 分布式 Autograd (2) ---- RPC基础
[源码解析] PyTorch 分布式 Autograd (2) ---- RPC基础 目录 [源码解析] PyTorch 分布式 Autograd (2) ---- RPC基础 0x00 摘要 0x0 ...
- [源码解析] PyTorch 分布式 Autograd (3) ---- 上下文相关
[源码解析] PyTorch 分布式 Autograd (3) ---- 上下文相关 0x00 摘要 我们已经知道 dist.autograd 如何发送和接受消息,本文再来看看如何其他支撑部分,就是如 ...
- [源码解析] PyTorch 分布式 Autograd (4) ---- 如何切入引擎
[源码解析] PyTorch 分布式 Autograd (4) ---- 如何切入引擎 目录 [源码解析] PyTorch 分布式 Autograd (4) ---- 如何切入引擎 0x00 摘要 0 ...
随机推荐
- sklearn调用逻辑回归算法
1.逻辑回归算法即可以看做是回归算法,也可以看作是分类算法,通常用来解决分类问题,主要是二分类问题,对于多分类问题并不适合,也可以通过一定的技巧变形来间接解决. 2.决策边界是指不同分类结果之间的边界 ...
- 使用PYaudio录制音频和视频(自己)
参考:https://blog.csdn.net/zhaoyun_zzz/article/details/84341801 音频录制:简洁版 import pyaudioimport waveimpo ...
- Redis——进阶
redis的持久化 redis提供两种备份方式,一种是RDB 一种是AOFRDB默认开启.关闭注释掉所有的save,存储的是redis 具体的值,会压缩存储.AOF配置文件中appendonly ye ...
- PHP使用ElasticSearch做搜索
PHP 使用 ElasticSearch 做搜索 https://blog.csdn.net/zhanghao143lina/article/details/80280321 https://www. ...
- dedeCMS网站栏目管理---释义
一.常规选项 文件保存目录:可以指定保存的目录,也可以用拼音,指定为拼音时系统会自动生成栏目拼音的目录,文件保存目录一般用拼音即可. 目录相对位置:有上级目录,CMS目录与站点根目录.实际上指的都是网 ...
- 043、Java中逻辑运算之实现位与操作
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 吴裕雄--天生自然java开发常用类库学习笔记:RumTime类
public class RuntimeDemo01{ public static void main(String args[]){ Runtime run = Runtime.getRuntime ...
- 《ES6标准入门》(阮一峰)--11.对象的新增方法
1.Object.is() ES5 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===).它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0.J ...
- Golang的运算符-算数运算符
Golang的运算符-算数运算符 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.算术运算符概述 常见的算术运算符: +: 可表示正号,如",结果为"Jaso ...
- POJ - 2456 Aggressive cows(二分+贪心)
题意:把c个牛分进n个摊位,摊位位置已知,所有摊位分布在0 <= xi <= 1,000,000,000,问两头牛间最小距离的最大值. 分析:找所有最小距离取个最大的.所以二分找这个最小的 ...