【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,因为只有这样,才能够对相应的输入参数梯度下降。

原文地址:https://www.cnblogs.com/duye/p/9913602.html