pytorch之backward()函数张量对张量的求导

原则上,pytorch不支持张量对张量的求导,它只支持标量对张量的求导
我们先看标量对张量求导的情况

import torch
x=torch.ones(2,2,requires_grad=True)
print(x)
print(x.grad_fn)

输出,由于x是被直接创建的,也就是说它是一个叶子节点,所以它的grad_fn属性的值为None
tensor([[1., 1.], [1., 1.]], requires_grad=True) None
接下来对叶子节点x进行第一步操作,y=x+2

y=x+2
print(y)
print(y.grad_fn)

输出:这里可以看到y的grad_fn属性变成了AddBackward,所以grad_fn属性记录的是该张量的上一步操作。
tensor([[3., 3.], [3., 3.]], grad_fn=<AddBackward0>) <AddBackward0 object at 0x00000206A7EE2108>
然后进行操作z=y * y * 3,再对z求平均值

z=y*y*3 
out=z.mean()
print(z,out)

输出结果:
tensor([[27., 27.], [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
此时我们利用backward()函数来求x的梯度,由于out是求平均值得到的一个标量,所以我们可以不用向backward函数传递一个张量,而是直接计算。

out.backward()
print(x.grad)

输出:tensor([[4.5000, 4.5000], [4.5000, 4.5000]])

我们来手动计算,看得到的结果是否与backword函数得到的结果一致
在这里插入图片描述
显然,结果是一致的。

再来看张量对张量求导的情况,前面已经强调过,pytorch不允许张量对张量求导,所以在使用张量对张量求导的时候,必须要传入一个与被求导张量同形的张量,然后pytorch根据传入的张量与被求导张量作加权求和将其转化为标量,这里比较晦涩难懂,没关系,接下来我们用例子来解释
首先创建一个叶子节点x

x=torch.tensor([[1.0,2.0],[3.0,4.0]],requires_grad=True)
print(x)

tensor([[1., 2.], [3., 4.]], requires_grad=True)
接下来计算y=3*x

y=3*x
print(y)

tensor([[ 3., 6.], [ 9., 12.]], grad_fn=<MulBackward0>)
接下来我们直接用y求导y.backward()
毫无意外,直接报错,这就印证了前面说过的pytorch不支持张量对张量直接求导

RuntimeError: grad can be implicitly created only for scalar outputs

于是我们构建一个与y同形的张量z,把z作为y.backward()的参数求y对
x的导。

z=torch.tensor([[1.0,0.1],[0.01,0.001]],dtype=torch.float)
y.backward(z)
print(x.grad)

输出结果:tensor([[3.0000, 0.3000], [0.0300, 0.0030]])(张量的梯度是一个与原张量同形的张量)
事实上,到这里我们仍一头雾水,不知道这个结果是如何得出的,下面给出他的通用计算公式(需要注意的是,该公式只是用来方便计算的,属于计算技巧)
在这里插入图片描述
至于y对x的导数,如果有多层复合函数,利用链式法则计算即可。上面的例子比较简单,y对x求导的结果是3,再乘以张量z,很容验证得到同样的结果。
接下来我们推导上述计算公式,上文已经提到,对于表达式y.backward(z) (y、z为同形张量)的计算过程,实际上将y与z加权求和得到标量m,然后用m对x求导得到结果,也就是说实际上有这样一步计算m=torch.sum(y*z)
我们可以来验证这一步计算的正确性

m = torch.sum(y*z)
print(m)

输出tensor(3.7020, grad_fn=<SumBackward0>)可以看到的是m是一个标量。
接着再用m对x求导

m.backward()
print(x.grad)

很容易得到上述结果tensor([[3.0000, 0.3000], [0.0300, 0.0030]])
下面给出上述计算公式的推导:
在这里插入图片描述

  • 24
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值