• (Pytorch)简单了解torch.autograd.grad()以及torch.autograd.backward()


    背景

    一般情况下,我们有了Loss之后,

    loss.backward()
    
    • 1

    就计算好了梯度,其他的根本不用管,例如标题的那两个函数。但是最近碰到一些定制化需求,上述知识已经不够,遂记录下来。

    torch.autograd.grad()

    torch.autograd.grad(
    outputs,   # 计算图的数据结果张量--它就是需要进行求导的函数
    inputs,   # 需要对计算图求导的张量--它是进行求导的变量
    grad_outputs=None,   # 如果outputs不是标量,需要使用此参数
    retain_graph=None,   # 保留计算图
    create_graph=None,   # 创建计算图
    allow_unused=False#inputs如果有不相关的变量,
    #即不对Outputs产生贡献的,比如你随便乱写一个inputs在那里,会报错,
    #改为True就不会报错,此时对这个垃圾inputs梯度为None返回。
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    作用:计算并返回outputs对inputs的梯度。看起来平平无奇对不对,但是,计算谁对谁的梯度, 通过这个函数,你可以自由控制啦。我们看个例子:

    import torch
    
    • 1
    x=torch.rand(2,2,requires_grad=True)
    print(x)
    y=x+2
    print(y)
    z=torch.sum(y)
    print(z)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    这个时候,如果我们要求z对x的梯度怎么办?我们当然直接

    z.backward()
    print(x.grad)
    
    • 1
    • 2

    对不对。但是我问你,我想求z对y的梯度怎么办?你做到这一点有点麻烦对不对,此时这个函数就可以帮我们实现:

    torch.autograd.grad(z,y)
    
    • 1

    在这里插入图片描述

    然后,我们再说一下其中的参数grad_outputs,其他的比如retain_graph我们就不说了,这个东西我早在其他文章说过,属于必修内容。

    grad_outputs到底是什么呢?我们上面求了z对y的导数,如果我们想要在此基础上求解z对x的导数怎么办呢?显然不能z.backward(),因为这不是在z对y的导数的基础上,而是相当于重新求导一切了。
    这个时候,我们就可以用上grad_outputs,这个东西就会充当dz/dy的作用,那么我门只需要求解dy/dx即可,然后相乘,(dz/dy)*(dy/dx)=dz/dx,就得到了我们最终想要的。

    一个例子如下:

    x=torch.rand(2,2,requires_grad=True)
    print(x)
    y=torch.pow(x,2)
    print(y)
    z=torch.sum(y)
    print(z)
    dzdy=torch.autograd.grad(z,y,retain_graph=True)[0]
    dzdx=torch.autograd.grad(y,x,grad_outputs=dzdy)[0]
    print(dzdx)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    补充:其实这个grad_outputs有一个名字,即Jacobian vector products中的"vector "。下面看一个图(下面的l就是我们的z):

    在这里插入图片描述
    你发现了没有,上面这个图展示了链式求导法则,前面那个矩阵dy/dx我们叫做J,矩阵和向量乘积称之为product。另外,我们提供的grad_outputs就是上面那个v向量dz/dy,有人说,我上面提供的不是一个矩阵吗?
    在这里插入图片描述
    这个没事,他内部会自动view(-1)

    小提示:代码中

    dzdx=torch.autograd.grad(y,x,dzdy)[0]
    
    • 1

    y和dzdy需要形状相同,这其实本来就一定要啊,对y的导数和y的数量当然是一样的。

    torch.autograd.backward()

    这个很简单,搞明白torch.autograd.backward(tensor)和tensor.backward()等价即可。


    完结撒花

  • 相关阅读:
    双十一屡获冠军!TCL空调的爆品密码是什么?
    Confluence升级方案
    HTTP 常见的请求头
    你的 Navicat 可能被下毒了...
    linux篇【11】:linux下的线程<后序>
    Net Core API +Vue Nginx集成发布
    Snort中pcre和正则表达式的使用
    Linux系统连接华为oceanstor数据存储
    vivado产生报告阅读分析5-时序报告1
    H5 手机键盘兼容
  • 原文地址:https://blog.csdn.net/qq_43391414/article/details/127639246