首先声明Pytorch的backward机制:
y.backward()时,如果y是标量(scalar),则不需要为backward()传入任何参数;
如果y是张量(tensor),需要传入一个与y同形的Tensor(张量)
①y是scalar标量
②y是Tensor张量
①如果直接像标量那样计算
就会报错显示:RuntimeError: grad can be implicitly created only for scalar outputs。翻译过来就是,grad只能隐式地为标量输出创建。
②y调用backward时需要传入一个和y同形的权重向量进行加权求和得到一个标量。
所以要谨记:在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。
举个例子:
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】
转载请注明原文地址: https://lol.8miu.com/read-18416.html