zoukankan      html  css  js  c++  java
  • 【pytorch】pytorch-backward()的理解

    pytorch-backword函数的理解

    函数:(tensor.backward(params))

    这个params的维度一定要和tensor的一致,因为tensor如果是一个向量y = [y1,y2,y3],那么传入的params=[a1,a2,a3],这三个值是系数,那么是什么的系数呢?
    假定对x =[ x1,x2]求导,那么我们知道,
    (dy/dx) 为:
    第一列: (dy1/dx1,dy2/dx1,dy3/dx1)
    第二列:(dy1/dx2, dy2/dx2,dy3/dx2)
    从而 (dy/dx)是一个3行2列的矩阵,每一列对应了对x1的导数,每一列也就是(x1)的梯度向量
    而反向计算的时候,并不是返回这个矩阵,而是返回这个矩阵每列的和作为梯度,也就是:(dy1/dx1+dy2/dx1+dy3/dx1) 是y对x1的梯度
    这就好理解了,系数为(params=[a1,a2,a3])就对应了这加和的三项!也就是,对(x1)的梯度实际上是(a1*dy1/dx1+a2*dy2/dx1+a3*dy3/dx1)
    而输出y是标量的时候,就不需要了,默认的就是(1.)

    自己重写backward函数时,要写上一个grad_output参数,这个参数就是上面提到的params

    这个grad_output参数究竟是什么呢?下面作出解释:
    是这样的,假如网络有两层, h = h(x),y = y(h)
    你可以计算(dy/dx),这样,y.backward(),因为(dy/dy=1),那么,backward的参数就可以省略
    如果计算h.backward(),因为你想求的是(dy/dx),(这才是输出对于输入的梯度),那么,计算图中的y = y(h)就没有考虑到
    因为(dy/dx = dy/dh * dh/dx)h.backward()求得是(dh/dx),那么你必须传入之前的梯度(dy/dh)才行,也就是说,h.backward(params=dy/dh)这里面的参数就是(dy/dh)

    这就好理解了,如果我们自己实现了一层,继承自Function,自己实现静态方法forwardbackward时,backward必须有个grad_output参数,这个参数就是计算图中输出对该自定义层的梯度,这样才能求出对输入的梯度。

    另外,假设定义的层计算出的是y,调用的就是y.backward(grad_output),这个里面的参数的维度必须和y是相同的。这也就是为什么前面提到对于输出是多维的,会有个“系数”的原因,这个系数就是后向传播时,该层之前的梯度的累积,这样与本层再累积,才实现了完整的链式法则,最终求出outinput的梯度。

    另外,自定义实现forwardbackward时,两函数的输入输出是有要求的,即forward的输入必须和~的return相对应,如forwardinput有个w参数,那么backwardreturn就必须在对应的位置返回grad_w,因为只有这样,才能够对相应的输入参数梯度下降。

  • 相关阅读:
    【CF103D】Time to Raid Cowavans-分块+离线处理
    【BZOJ3992】序列统计(SDOI2015)-NTT+循环卷积+快速幂
    【BZOJ3527】力(ZJOI2014)-FFT
    【HDU4609】3-idiots-FFT+生成函数
    【LuoguP3803】多项式乘法-FFT/NTT模板题(附带FFT/NTT简单介绍)
    网络流24题解题总结(更新中)
    【BZOJ3531】旅行(SDOI2014)-树链剖分+动态加点线段树
    [Noip2012]借教室
    bzoj3394:[Usaco2009 Jan]Best Spot 最佳牧场
    [NOIP2014]无线网站发射器选址
  • 原文地址:https://www.cnblogs.com/duye/p/9913602.html
Copyright © 2011-2022 走看看