首先声明Pytorch的backward机制:
y.backward()
时,如果
y
是标量(scalar),则不需要为
backward()
传入任何参数;
y.backward()
y
backward()
如果
y
是张量(tensor),需要传入一个与
y
同形的
Tensor(张量)
y
y
Tensor(张量)
①y是scalar标量
②y是Tensor张量
①如果直接像标量那样计算
就会报错显示:
RuntimeError: grad can be implicitly created only for scalar outputs。
翻译过来就是,grad只能隐式地为标量输出创建。
RuntimeError: grad can be implicitly created only for scalar outputs。
②
y
调用
backward
时需要传入一个和
y
同形的权重向量进行加权求和得到一个标量
。
backward
y
所以要谨记:
在Pytorch中,
调用
backward
时,一定是标量对张量求导
。
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
的四维张量。问题来了,怎样反向传播?怎样将两个四维张量相乘???这要怎么乘???就算能解决两个四维张量怎么乘的问题,四维和三维的张量又怎么乘?导数的导数又怎么求,这一连串的问题,感觉要疯掉…… 为了避免这个问题,我们
不允许张量对张量求导,只允许标量对张量求导,求导结果是和自变量同形的张量
。
m x n
p x q
s x t
s x t x p x q
p x q x m x n
2.
y.backward(w)
前面提高的都是直接
y.backward()
,那么如果是
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)
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
】
版权声明:本文为qq_38880969原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。