Pytorch中的backward

首先声明Pytorch的backward机制:

y.backward()时,如果y是标量(scalar),则不需要为backward()传入任何参数;

如果y是张量(tensor),需要传入一个与y同形的Tensor(张量)

①y是scalar标量

Pytorch中的backward

②y是Tensor张量

①如果直接像标量那样计算Pytorch中的backward

就会报错显示:RuntimeError: grad can be implicitly created only for scalar outputs。翻译过来就是,grad只能隐式地为标量输出创建。

y调用backward时需要传入一个和y同形的权重向量进行加权求和得到一个标量

Pytorch中的backward

所以要谨记:在Pytorch中,调用backward时,一定是标量对张量求导

③续

1.为什么不能Tensor 对 Tensor 求导

举个例子,假设形状为 m x n 的矩阵 X 经过运算得到了 p x q 的矩阵 Y,Y 又经过运算得到了 s x t 的矩阵 Z。那么按照前面讲的规则,dZ/dY 应该是一个 s x t x p x q 四维张量,dY/dX 是一个 p x q x m x n的四维张量。问题来了,怎样反向传播?怎样将两个四维张量相乘???这要怎么乘???就算能解决两个四维张量怎么乘的问题,四维和三维的张量又怎么乘?导数的导数又怎么求,这一连串的问题,感觉要疯掉…… 为了避免这个问题,我们不允许张量对张量求导,只允许标量对张量求导,求导结果是和自变量同形的张量

2.  y.backward(w)

前面提高的都是直接y.backward(),那么如果是y.backward(w)呢?

y.backward(w) 求的就不是 y 对 x 的导数,而是 l = torch.sum(y*w) 对 x 的导数,即dl/dx = d(y*w)/dx。

举个例子:

Pytorch中的backward

 

Pytorch中的backward
Pytorch中的backward

t.backward(z),即l = torch.sum(t*z)

所以x.grad = dl/dx = d(t * z)/dx = d((x +y) * z)/dx = z;

y.grad = dl/dy = d(t * z)/dy = d((x +y) * z)/dy = z;

【参考资料:①Dive-into-DL-PyTorch-master   ②https://zhuanlan.zhihu.com/p/29923090