• Pytorch 梯度计算,叶子节点,requires_grad,detach


    前言

    本篇记录pytorch中梯度相关内容,叶子节点定义与detach的使用。

    梯度计算

    神经网络的参数更新依赖于梯度计算与反向传播。pytorch中的tensor张量存在requires_grad属性,requires_grad=True时,计算图的末端节点进行backward()会自动计算该张量的梯度。

    举例:

    import torch
    
    a = torch.tensor([1, 1, 1], requires_grad=True, dtype=torch.float32)
    b = a.mean()
    b.backward()
    
    print(a.grad)  # db/da
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    叶子节点

    即使张量的requires_grad属性为真时,该张量也不一定能够直接通过grad属性访问计算图backward累计的梯度。只有叶子节点同时requires_grad=True的张量,才能通过.grad访问累计梯度;非叶子节点的计算图张量,其梯度在计算后马上被删除以节省内存。

    一个经典的梯度计算与参数更新的顺序是:

    1. 定义张量计算图(也就是输入与模型的运算)
    2. 输出backward累计参数梯度
    3. 优化器step更新参数
    4. 优化器清除累计的梯度

    叶子节点的判断:用户自行创建的requires_grad=True的张量,比如各种网络层nn.Linear, nn.Conv2d的神经元weight, bias或者卷积核参数;requires_grad=False的张量也是叶子节点,但因为它不需要计算梯度,因此认为是游离在计算图之外的。

    通过叶子节点运算得来的节点,都是非叶子节点。非叶子节点添加了一个grad_fn属性,记录了该节点产生时使用的运算函数,用于反向计算其梯度(这个梯度只能通过retain_grad函数或者hook机制获得,因为它计算后即被释放)。

    张量requires_grad属性修改,detach

    上面提到,requires_grad=False的张量梯度不会累计,如果要使得其requires_grad=True,可以使用requires_grad_(True)

    requires_grad=True的非叶子节点不能直接通过requires_grad_(False)修改其梯度属性,可以使用detach剥离其梯度属性,剥离后的张量与原张量内存相同,但不会累计梯度,其属性里也没有了grad_fn

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    a = torch.tensor([1, 1, 1], requires_grad=True, dtype=torch.float32)
    b = torch.tensor([1, 1, 1], requires_grad=False, dtype=torch.float32)
    b.requires_grad_(True)
    c = (a + 2 * b.detach()).sum()
    c.backward()
    
    print(a.grad, b.grad)  # tensor([1., 1., 1.]) None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    常用的文件系统、存储类型小整理
    video caption with frame selection【论文阅读】
    Seata总结
    vagrant 虚拟机扩容磁盘
    linux操作Rpm
    贝叶斯公式——假阳性问题
    commonjs和esmodule
    pytest + yaml 框架 - 我们发布上线了
    零时科技创始人邓永凯先生受邀对话《公链隐私保护及生态安全》
    如何将原生微信小程序页面改成原生VUE框架的H5页面
  • 原文地址:https://blog.csdn.net/qq_41035283/article/details/127845535