在学习的过程中遇见了一个问题,就是当使用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的更多相关文章

  1. Pytorch 之 backward

    首先看这个自动求导的参数: grad_variables:形状与variable一致,对于y.backward(),grad_variables相当于链式法则dz/dx=dz/dy × dy/dx 中 ...

  2. ARTS-S pytorch中backward函数的gradient参数作用

    导数偏导数的数学定义 参考资料1和2中对导数偏导数的定义都非常明确.导数和偏导数都是函数对自变量而言.从数学定义上讲,求导或者求偏导只有函数对自变量,其余任何情况都是错的.但是很多机器学习的资料和开源 ...

  3. Pytorch autograd,backward详解

    平常都是无脑使用backward,每次看到别人的代码里使用诸如autograd.grad这种方法的时候就有点抵触,今天花了点时间了解了一下原理,写下笔记以供以后参考.以下笔记基于Pytorch1.0 ...

  4. pytorch autograd backward函数中 retain_graph参数的作用,简单例子分析,以及create_graph参数的作用

    retain_graph参数的作用 官方定义: retain_graph (bool, optional) – If False, the graph used to compute the grad ...

  5. Pytorch中torch.autograd ---backward函数的使用方法详细解析,具体例子分析

    backward函数 官方定义: torch.autograd.backward(tensors, grad_tensors=None, retain_graph=None, create_graph ...

  6. 关于Pytorch中autograd和backward的一些笔记

    参考自<Pytorch autograd,backward详解>: 1 Tensor Pytorch中所有的计算其实都可以回归到Tensor上,所以有必要重新认识一下Tensor. 如果我 ...

  7. 深度学习框架PyTorch一书的学习-第三章-Tensor和autograd-2-autograd

    参考https://github.com/chenyuntc/pytorch-book/tree/v1.0 希望大家直接到上面的网址去查看代码,下面是本人的笔记 torch.autograd就是为了方 ...

  8. 深度学习框架PyTorch一书的学习-第一/二章

    参考https://github.com/chenyuntc/pytorch-book/tree/v1.0 希望大家直接到上面的网址去查看代码,下面是本人的笔记 pytorch的设计遵循tensor- ...

  9. TensorFlow2.0初体验

    TF2.0默认为动态图,即eager模式.意味着TF能像Pytorch一样不用在session中才能输出中间参数值了,那么动态图和静态图毕竟是有区别的,tf2.0也会有写法上的变化.不过值得吐槽的是, ...

随机推荐

  1. JavaScript解析机制与闭包原理实例详解

    js代码解析机制: js代码解析之前会创建一个如下的词法环境对象(仓库):LexicalEnvironment{ } 在扫描js代码时会把: 1.用声明的方式创建的函数的名字; 2.用var定义的变量 ...

  2. cf1121F. Compress String(后缀自动机)

    题意 题目链接 Sol 居然出个SAM板子也是没谁了233 #include<bits/stdc++.h> #define Pair pair<int, int> #defin ...

  3. 2018-05-09 5分钟入门CTS-尝鲜中文版TypeScript

    知乎原链 本文为中文代码示例之5分钟入门TypeScript的CTS版本. CTS作者是@htwx(github). 它实现了关键词和标准库的所有命名汉化. 本文并未使用附带的vscode相关插件(包 ...

  4. 2018-01-02 JavaScript实现ZLOGO: 用语法树实现多层循环

    原址: https://zhuanlan.zhihu.com/p/32571516 照例先上演示弱效果图. 演示地址照旧: 代码如下: 开始 循环4次 循环4次 前进50 左转90度 到此为止 右转9 ...

  5. 从项目需求角度,使用纯CSS方案解决垂直居中

    CSS是HTML元素的剪刀手,它极度的丰富了web页面的修饰.在众多CSS常见的样式需求中,有一奇葩式的存在[垂直居中],因为不管是从逻辑实现方面还是从正常需求量来讲,这都没理由让这个需求在实践过程中 ...

  6. Caused by:org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type "" available: expected at least 1 bean which qualifies as autowire candidate

    项目使用spring, mybatis.因为分了多个模块,所以会这个模块引用了其它模块的现在,结果使用Junit测试的时候发现有两个模块不能自动注入dao和service问题.解决后在此记录一下. 解 ...

  7. 使用Visual Studio Team Services敏捷规划和项目组合管理(四)——冲刺计划和任务板

    使用Visual Studio Team Services敏捷规划和项目组合管理(四)--冲刺计划和任务板 团队在sprint计划会议期间创建冲刺积压工作项,通常在冲刺的第一天召开该会议.每个冲刺都对 ...

  8. mssql sql server 系统更新,如何正确的增加表字段

    转自: http://www.maomao365.com/?p=5277摘要:下文主要讲述,如何对"已上线的系统"中的表,增加新的字段. 系统部署脚本,增加列的方法:在系统脚本发布 ...

  9. c/c++ 广义表

    广义表 列表里面有列表,比如(1,(2,(3,4)),5) 用链表可以实现 结果如图 guangyibiao.h #ifndef __GUANGYIBIAO__ #define __GUANGYIBI ...

  10. 常见 User-Agent 大全(自己在用)

    分享几个常见的User-Agent吧,复制粘贴过来的,谢谢原创. window.navigator.userAgent 1) Chrome Win7: Mozilla/5.0 (Windows NT ...