【转载】关于grad_tensors的解惑
转载:https://www.cnblogs.com/marsggbo/p/11549631.html
平常都是无脑使用backward,每次看到别人的代码里使用诸如autograd.grad这种方法的时候就有点抵触,今天花了点时间了解了一下原理,写下笔记以供以后参考。以下笔记基于Pytorch1.0
1|0Tensor
Pytorch中所有的计算其实都可以回归到Tensor上,所以有必要重新认识一下Tensor。如果我们需要计算某个Tensor的导数,那么我们需要设置其.requires_grad
属性为True
。为方便说明,在本文中对于这种我们自己定义的变量,我们称之为叶子节点(leaf nodes),而基于叶子节点得到的中间或最终变量则可称之为结果节点。例如下面例子中的x
则是叶子节点,y
则是结果节点。
另外一个Tensor中通常会记录如下图中所示的属性:
data
: 即存储的数据信息requires_grad
: 设置为True
则表示该Tensor需要求导grad
: 该Tensor的梯度值,每次在计算backward时都需要将前一时刻的梯度归零,否则梯度值会一直累加,这个会在后面讲到。grad_fn
: 叶子节点通常为None,只有结果节点的grad_fn才有效,用于指示梯度函数是哪种类型。例如上面示例代码中的y.grad_fn=<PowBackward0 at 0x213550af048>, z.grad_fn=<AddBackward0 at 0x2135df11be0>
is_leaf
: 用来指示该Tensor是否是叶子节点。
2|0torch.autograd.backward
有如下代码:
可以z是一个标量,当调用它的backward方法后会根据链式法则自动计算出叶子节点的梯度值。
但是如果遇到z是一个向量或者是一个矩阵的情况,这个时候又该怎么计算梯度呢?这种情况我们需要定义grad_tensor
来计算矩阵的梯度。在介绍为什么使用之前我们先看一下源代码中backward的接口是如何定义的:
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
这么一个参数,以及它有什么用呢?
还是用代码做个示例
当我们运行上面的代码的话会报错,报错信息为RuntimeError: grad can be implicitly created only for scalar outputs。
上面的报错信息意思是只有对标量输出它才会计算梯度,而求一个矩阵对另一矩阵的导数束手无策。
那么我们只要想办法把矩阵转变成一个标量不就好了?比如我们可以对z求和,然后用求和得到的标量在对x求导,这样不会对结果有影响,例如:
我们可以看到对z求和后再计算梯度没有报错,结果也与预期一样:
我们再仔细想想,对z求和不就是等价于z点乘一个一样维度的全为1的矩阵吗?即sum(Z)=dot(Z,I)sum(Z)=dot(Z,I),而这个I也就是我们需要传入的grad_tensors
参数。(点乘只是相对于一维向量而言的,对于矩阵或更高为的张量,可以看做是对每一个维度做点乘)
代码如下:
弄个再复杂一点的:
x = torch.tensor([2., 1.], requires_grad=True).view(1, 2)
y = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True) z = torch.mm(x, y)
print(f"z:{z}")
z.backward(torch.Tensor([[1., 0]]), retain_graph=True)
print(f"x.grad: {x.grad}")
print(f"y.grad: {y.grad}")>>> z:tensor([[5., 8.]], grad_fn=<MmBackward>)
x.grad: tensor([[1., 3.]])
y.grad: tensor([[2., 0.],
[1., 0.]])
结果解释如下:
总结:
说了这么多,grad_tensors
的作用其实可以简单地理解成在求梯度时的权重,因为可能不同值的梯度对结果影响程度不同,所以pytorch弄了个这种接口,而没有固定为全是1。引用自知乎上的一个评论:如果从最后一个节点(总loss)来backward,这种实现(torch.sum(y*w))的意义就具体化为 multiple loss term with difference weights 这种需求了吧。
3|0torch.autograd.grad
看了前面的内容后在看这个函数就很好理解了,各参数作用如下:
outputs
: 结果节点,即被求导数inputs
: 叶子节点grad_outputs
: 类似于backward
方法中的grad_tensors
retain_graph
: 同上create_graph
: 同上only_inputs
: 默认为True
, 如果为True
, 则只会返回指定input
的梯度值。 若为False
,则会计算所有叶子节点的梯度,并且将计算得到的梯度累加到各自的.grad
属性上去。allow_unused
: 默认为False
, 即必须要指定input
,如果没有指定的话则报错。
4|0参考
【转载】关于grad_tensors的解惑的更多相关文章
- 【转】字符编码笔记:ASCII,Unicode和UTF-8
今天整理笔记,关于NSString转NSData时,什么时候使用NSUTF8StringEncoding,或者NSASCIIStringEncoding,或者 NSUnicodeStringEncod ...
- 转载:Python 包管理工具解惑
Python 包管理工具解惑 本站文章除注明转载外,均为本站原创或者翻译. 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商: 本站部分原创和翻译文章提供m ...
- ASP.NET 跨域请求之jQuery的ajax jsonp的使用解惑 (转载)
前天在项目中写的一个ajax jsonp的使用,出现了问题:可以成功获得请求结果,但没有执行success方法,直接执行了error方法提示错误——ajax jsonp之前并没有用过,对其的理解为跟普 ...
- GCC中-fpic解惑(转载)
参考: 1.<3.18 Options for Code Generation Conventions>2.<Options for Linking>3.<GCC -fP ...
- 转载:第五弹!全球首个微信小程序(应用号)开发教程!通宵吐血赶稿,每日更新!
博卡君今天继续更新,忙了一天,终于有时间开工写教程.不罗嗦了,今天我们来看看如何实现一些前端的功能和效果. 第八章:微信小程序分组开发与左滑功能实现 先来看看今天的整体思路: 进入分组管理页面--&g ...
- (译)iOS Code Signing: 解惑
子龙山人 Learning,Sharing,Improving! (译)iOS Code Signing: 解惑 免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切 ...
- Gulp入门与解惑
Gulp简介 Gulp.js 是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务.Gulp.js是基于 Node.js构建的,利用Node.js流的威力,你可以快速构建项目. 安装 ...
- JVM菜鸟进阶高手之路九(解惑)
转载请注明原创出处,谢谢! 在第八系列最后有些疑惑的地方,后来还是在我坚持不懈不断打扰笨神,阿飞,ak大神等,终于解决了该问题.第八系列地址:http://www.jianshu.com/p/7f7c ...
- JVM 菜鸟进阶高手之路九(解惑)
转载请注明原创出处,谢谢! 在第八系列最后有些疑惑的地方,后来还是在我坚持不懈不断打扰笨神,阿飞,ak大神等,终于解决了该问题.第八系列地址:http://www.cnblogs.com/lirenz ...
随机推荐
- HDU 3336——Count the string
It is well known that AekdyCoin is good at string problems as well as number theory problems. When g ...
- JavaScript函数console、this关键字
console.dir()打印出来的东西不加任何操作 console.log()打印出来东西实现进行了操作,打印出来的东西可能不是原型 具体对象的类型可以在"_proto_"中看, ...
- 牛客编程巅峰赛S1第5场 - 青铜&白银 C.排队 (优先队列,归并排序)
题意:有\(m\)个窗口,\(n\)个人排队,每个人都有各自的办理时间,只有办理完成窗口才能空出来,后面的人开始办理,求有多少人比后面的人开始办理的早但完成的晚. 题解:我们可以用优先队列来模拟办理, ...
- .net中swagger忽略某些字段
需要忽略的字段上用特性 [System.Text.Json.Serialization.JsonIgnore] 例如:
- JVM你了解?
1.谈谈你对JAVA的理解 平台无关性(一次编译,到处运行) GC(不必手动释放堆内存) 语言特性(泛型.lambda) 面向对象(继承,封装,多态) 类库 异常处理 2.平台无关性怎么实现
- [备忘] DevOps 工具上的准备清单(不断补充中……)
目录 概念 发展历程 工具清单 规划 概念 从字面上来看,"DevOps"一词是由英文 Development(开发)和 Operations (运维)组合而成,但它所代表的理念和 ...
- K8S(02)管理核心资源的三种基本方法
系列文章说明 本系列文章,可以基本算是 老男孩2019年王硕的K8S周末班课程 笔记,根据视频来看本笔记最好,否则有些地方会看不明白 需要视频可以联系我 管理k8s核心资源的三种基本方法: 目录 系列 ...
- Redis 的缓存淘汰机制(Eviction)
本文从源码层面分析了 redis 的缓存淘汰机制,并在文章末尾描述使用 Java 实现的思路,以供参考. 相关配置 为了适配用作缓存的场景,redis 支持缓存淘汰(eviction)并提供相应的了配 ...
- HDU - 5115 Dire Wolf (非原创)
Dire wolves, also known as Dark wolves, are extraordinarily large and powerful wolves. Many, if not ...
- Dapr 正式发布1.0
年前我写了一篇博客<Dapr 已在塔架就位 将发射新一代微服务>, 今天Dapr 正式发布了1.0 : Dapr Runtime v1.0.0 Dapr dotnet SDK v1.0.0 ...