pytorch的backward
在学习的过程中遇见了一个问题,就是当使用backward()反向传播时传入参数的问题:
net.zero_grad() #所有参数的梯度清零
output.backward(Variable(t.ones(1, 10))) #反向传播
这里的backward()中为什么需要传入参数Variable(t.ones(1, 10))呢?没有传入就会报错:
RuntimeError: grad can be implicitly created only for scalar outputs
这个错误的意思就是梯度只能为标量(即一个数)输出隐式地创建
比如有一个例子是:
1)
#使用Tensor新建一个Variable
x = Variable(t.ones(2, 2),requires_grad = True)
x
返回:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
此时查看该值的grad和grad_fn是没有返回值的,因为没有进行任何操作
x.grad_fn
x.grad
进行求和操作,查看梯度
y = x.sum()
y
返回:
tensor(4., grad_fn=<SumBackward0>)
这时候可查看:
y.grad_fn
返回:
<SumBackward0 at 0x122782978>
可知y是变量Variable x进行sum操作求来的,但是这个时候y.grad是没有返回值的,因为没有使用y进行别的操作
这个时候的x.grad也是没有值的,虽然使用x进行了sum操作,但是还没有对y反向传播来计算梯度
y.backward()#反向传播,计算梯度
然后再查看:
#因为y = x.sum() = (x[0][0] + x[0][1] + x[1][0] + x[1][1])
#每个值的梯度都为1
x.grad
返回:
tensor([[1., 1.],
[1., 1.]])
在这里我们可以看见y能够求出x的梯度,这里的y是一个数,即标量
如果这里我们更改一下y的操作,将y设置为一个二维数组:
from __future__ import print_function
import torch as t
from torch.autograd import Variable
x = Variable(t.ones(, ),requires_grad = True)
y = x +
y.backward()
然后就会报上面的错误:
RuntimeError: grad can be implicitly created only for scalar outputs
总结:
因此当输出不是标量时,调用.backwardI()就会出错
解决办法:
显示声明输出的类型作为参数传入,且参数的大小必须要和输出值的大小相同
x.grad.data.zero_() #将之前的值清零
x.grad
返回:
tensor([[., .],
[., .]])
进行反向传播:
y.backward(y.data)
x.grad
也可以写成,因为Variable和Tensor有近乎一致的接口
y.backward(y)
x.grad
返回:
tensor([[., .],
[., .]])
但是这里返回值与预想的1不同,这个原因是得到的梯度会与参数的值相乘,所以最好传入值为1,如:
y.backward(Variable(t.ones(, )))
x.grad
这样就能够成功返回想要的值了:
tensor([[., .],
[., .]])
更加复杂的操作:
在上面的例子中,x和y都是(2,2)的数组形式,每个yi都只与对应的xi相关
1)如果每个yi都与多个xi相关时,梯度又是怎么计算的呢?
比如x = (x1 = 2, x2 = 4), y = (x12+2x2, 2x1+3x22)
(i,j)的值就是传入.backward()的参数的值
x = Variable(t.FloatTensor([[, ]]),requires_grad = True)
y = Variable(t.zeros(, ))
y[,] = x[,]** + * x[,]
y[,] = * x[,] + * x[,]**
y.backward(Variable(t.ones(, ))) #(i,j)= (,)
x.grad
返回:
tensor([[ ., .]])
2)如果x和y不是相同的数组形式,且每个yi都与多个xi相关时,梯度又是怎么计算的呢?
比如x = (x1 = 2, x2 = 4, x3=5), y = (x12+2x2+4x3, 2x1+3x22+x32)
x = Variable(t.FloatTensor([[, , ]]),requires_grad = True)
y = Variable(t.zeros(, ))
y[,] = x[,]** + * x[,] + * x[,]
y[,] = * x[,] + * x[,]** + x[,]**
y.backward(Variable(t.ones(, )))
x.grad
返回:
tensor([[ ., ., .]])
如果(i, j) = (2,2),结果是否为(12, 52, 28)呢?
x = Variable(t.FloatTensor([[, , ]]),requires_grad = True)
y = Variable(t.zeros(, ))
y[,] = x[,]** + * x[,] + * x[,]
y[,] = * x[,] + * x[,]** + x[,]**
y.backward(Variable(t.FloatTensor([[, ]])))
x.grad
返回:
tensor([[., ., .]])
3)如果你想要分别得到y1,y2对x1,x2,x3的求导值,方法是:
x = Variable(t.FloatTensor([[, , ]]),requires_grad = True)
y = Variable(t.zeros(, ))
y[,] = x[,]** + * x[,] + * x[,]
y[,] = * x[,] + * x[,]** + x[,]**
j = t.zeros(,)#用于存放求导的值
#(i,j)=(,)这样就会对应只求得y1对x1,x2和x3的求导
#retain_variables=True的作用是不在反向传播后释放内存,这样才能够再次反向传播
y.backward(Variable(t.FloatTensor([[, ]])),retain_variables=True)
j[:,] = x.grad.data
x.grad.data.zero_() #将之前的值清零
#(i,j)=(,)这样就会对应只求得y2对x1,x2和x3的求导
y.backward(Variable(t.FloatTensor([[, ]])))
j[:,] = x.grad.data
print(j)
报错:
TypeError: backward() got an unexpected keyword argument 'retain_variables'
原因是新版本使用的参数名为retain_graph,改了即可:
x = Variable(t.FloatTensor([[, , ]]),requires_grad = True)
y = Variable(t.zeros(, ))
y[,] = x[,]** + * x[,] + * x[,]
y[,] = * x[,] + * x[,]** + x[,]**
j = t.zeros(,)#用于存放求导的值
#(i,j)=(,)这样就会对应只求得y1对x1,x2和x3的求导
#retain_graph=True的作用是不在反向传播后释放内存,这样才能够再次反向传播
y.backward(Variable(t.FloatTensor([[, ]])),retain_graph=True)
j[:,] = x.grad.data
x.grad.data.zero_() #将之前的值清零
#(i,j)=(,)这样就会对应只求得y2对x1,x2和x3的求导
y.backward(Variable(t.FloatTensor([[, ]])))
j[:,] = x.grad.data
print(j)
返回:
tensor([[ ., .],
[ ., .],
[ ., .]])
pytorch的backward的更多相关文章
- Pytorch 之 backward
首先看这个自动求导的参数: grad_variables:形状与variable一致,对于y.backward(),grad_variables相当于链式法则dz/dx=dz/dy × dy/dx 中 ...
- ARTS-S pytorch中backward函数的gradient参数作用
导数偏导数的数学定义 参考资料1和2中对导数偏导数的定义都非常明确.导数和偏导数都是函数对自变量而言.从数学定义上讲,求导或者求偏导只有函数对自变量,其余任何情况都是错的.但是很多机器学习的资料和开源 ...
- Pytorch autograd,backward详解
平常都是无脑使用backward,每次看到别人的代码里使用诸如autograd.grad这种方法的时候就有点抵触,今天花了点时间了解了一下原理,写下笔记以供以后参考.以下笔记基于Pytorch1.0 ...
- pytorch autograd backward函数中 retain_graph参数的作用,简单例子分析,以及create_graph参数的作用
retain_graph参数的作用 官方定义: retain_graph (bool, optional) – If False, the graph used to compute the grad ...
- Pytorch中torch.autograd ---backward函数的使用方法详细解析,具体例子分析
backward函数 官方定义: torch.autograd.backward(tensors, grad_tensors=None, retain_graph=None, create_graph ...
- 关于Pytorch中autograd和backward的一些笔记
参考自<Pytorch autograd,backward详解>: 1 Tensor Pytorch中所有的计算其实都可以回归到Tensor上,所以有必要重新认识一下Tensor. 如果我 ...
- 深度学习框架PyTorch一书的学习-第三章-Tensor和autograd-2-autograd
参考https://github.com/chenyuntc/pytorch-book/tree/v1.0 希望大家直接到上面的网址去查看代码,下面是本人的笔记 torch.autograd就是为了方 ...
- 深度学习框架PyTorch一书的学习-第一/二章
参考https://github.com/chenyuntc/pytorch-book/tree/v1.0 希望大家直接到上面的网址去查看代码,下面是本人的笔记 pytorch的设计遵循tensor- ...
- TensorFlow2.0初体验
TF2.0默认为动态图,即eager模式.意味着TF能像Pytorch一样不用在session中才能输出中间参数值了,那么动态图和静态图毕竟是有区别的,tf2.0也会有写法上的变化.不过值得吐槽的是, ...
随机推荐
- 事件处理程序(HTML)
HTML事件处理程序 通过设置HTML标签特性来绑定事件处理程序. 处理方式(如图): 1:会创建一个封装元素属性值的函数 2:会在这个函数中创建一个event事件对象 <form> &l ...
- phpstorm连接服务器,实时编辑上传文件到服务器
教程一:我的老版本,并且是汉化的,找到该位置 打开后:点击Configuration进行配置! 输入服务器的ip.端口.用户名.密码即可 打开编辑: 教程二:下面更新了一个新版本的(2018.2): ...
- C#自定义控件、用户控件、动态加载菜单按钮
一.效果图,动态加载5个菜单按钮: 二.实现方法 1.创建用户控件 2.在用户控件拖入toolStrip 3.进入用户控件的Lood事件,这里自动添加5个选 ToolStripMenuItem,后期 ...
- ACL技术总结
1.ACL的全称是访问控制列表,本质上是定义一组策略,以便指导报文在交换机内部的转发行为. 2.要配置策略,首先要明确ACL应用的对象,可以是针对端口,也可以是针对特殊的一条流. 针对端口,就是指端口 ...
- Python_关于多线程下变量赋值取值的一点研究
关于多线程下变量赋值取值的一点研究 by:授客 QQ:1033553122 1.代码实践1 #!/usr/bin/env python # -*- coding:utf-8 -*- __author_ ...
- Servlet以及单例设计模式
1.Servlet概述 a)Servlet,全城是Servlet Applet,服务器端小程序,是一个接口,定义了若干方法,要求所有的Servlet必须实现. b)Servlet用于接收客户端的请求, ...
- EXT.NET初学
1.ext:Hidden 必须在body里面有ext:ResourceManager的情况下才能运行 2.ext:Store里面不能有文字
- EOS智能合约开发(二):EOS创建和管理钱包
上节介绍了EOS智能合约开发之EOS环境搭建及启动节点 那么,节点启动后我们要做的第一件事儿是什么呢?就是我们首先要有账号,但是有账号的前提是什么呢?倒不是先创建账号,而是先要有自己的一组私钥,有了私 ...
- 查看iPhone电池寿命
iBackupBot 软件:iBackupBot for iTunes (收费软件) 官网:http://www.icopybot.com/download.htm iBackupBot for iT ...
- Docker: docker container常用命令实战(2)-数据持久化
应用服务是在容器中运行的,容器随时会被删除,如果是个mysql容器呢?数据存储在容器里,容器删除了,数据也没了,那就是个噩梦. 所以一些数据是需要存储在容器之外的,可以是宿主机,可以是网络存储位置上, ...