【深度学习】Pytorch torch.autograd 自动差分引擎

简介: 【1月更文挑战第26天】【深度学习】Pytorch torch.autograd 自动差分引擎

 

image.gif编辑

目录

一、Autograd 概述:

二、Pytorch 训练示例:

三、Autograd 自动求导:

四、计算图:

从 DAG 中排除张量的自动求导:


一、Autograd 概述:

   torch.autograd是 PyTorch 的自动差分引擎,可为神经网络训练提供支持。

       神经网络(NN)是在某些输入数据上执行的嵌套函数的集合。 这些函数由参数(由权重和偏差组成)定义,这些参数在 PyTorch 中存储在张量中。

训练 NN 分为两个步骤:

    • 正向传播:在正向传播中,NN 对正确的输出进行最佳猜测。 它通过其每个函数运行输入数据以进行猜测。

           正向传播是对输入的真实数据进行函数运算得到一个预测的结果输出的过程,输入的数据是真实可信的,输出的结果是预测值,不可信。

      • 反向传播:在反向传播中,NN 根据其猜测中的误差调整其参数。 它通过从输出向后遍历,收集有关函数参数(梯度)的误差导数并使用梯度下降来优化参数来实现。

             反向传播是指预测输出的不可信结果(函数计算结果)和输入数据的真实可信值(输入数据的标签)通过损失函数,通过梯度下降来修改参数(优化),拟合数据集。


      二、Pytorch 训练示例:

             让我们来看一个训练步骤。 对于此示例,我们从torchvision加载了经过预训练的 resnet18 模型。 我们创建一个随机数据张量来表示具有 3 个通道的单个图像,高度&宽度为 64,其对应的label初始化为一些随机值。

      import torch, torchvision
      # 从torchvision加载了经过预训练的 resnet18 模型:
      model = torchvision.models.resnet18(pretrained=True)
      # 创建一个随机张量,表示一个图像的RGB三通道,宽高为64x64:
      data = torch.rand(1, 3, 64, 64)
      # 随机初始化一个二维列向量,1行,1000列(标签值)
      labels = torch.rand(1, 1000)

      image.gif

      torchvision resnet18 模型:

             残差网络,残差网络是由来自Microsoft Research的4位学者提出的卷积神经网络,在2015年的ImageNet大规模视觉识别竞赛(ImageNet Large Scale Visual Recognition Challenge, ILSVRC)中获得了图像分类和物体识别的优胜。 残差网络的特点是容易优化,并且能够通过增加相当的深度来提高准确率。其内部的残差块使用了跳跃连接,缓解了在深度神经网络中增加深度带来的梯度消失问题

             在VGG中,卷积网络达到了19层,在GoogLeNet中,网络史无前例的达到了22层。那么,网络的精度会随着网络的层数增多而增多吗?在深度学习中,网络层数增多一般会伴着下面几个问题

        1. 计算资源的消耗
        2. 模型容易过拟合
        3. 梯度消失/梯度爆炸问题的产生

               这里没有详细去解释rsenet18网络模型(因为我自己也没学过,哈哈哈),我将在下一篇文章中去学习和详细解析resnet18网络模型......

               这里大概解释一下输入和输出,输入主要是一个一张RGB三色的长宽为64x64的彩色图片,输出是一个 1行1000列的一个行向量

        image.gif编辑

               接下来,我们通过模型的每一层运行输入数据以进行预测。 这是正向传播

        # 把随机生成的图像张量传入预训练的模型,获得预测值
        prediction = model(data) # forward pass

        image.gif

               我们使用模型的预测和相应的标签来计算误差(loss。 下一步是通过网络反向传播此误差。 当我们在误差张量上调用.backward()时,开始反向传播。 然后,Autograd 会为每个模型参数计算梯度并将其存储在参数的.grad属性中。

        loss = (prediction - labels).sum()
        loss.backward() # backward pass

        image.gif

               接下来,我们加载一个优化器,在本例中为 SGD学习率为 0.01动量为 0.9。 我们在优化器中注册模型的所有参数。

              SGD(随机梯度下降)

               从样本中随机抽出一组,训练后按梯度更新一次,然后再抽取一个样本,再更新一次,在样本量及其大的情况下,可能不用训练完所有的样本就可以获得一个损失值在可接受范围之内的模型了。

               动量这是是一个知识盲区(等我学完后再补这里的内容)!!!(2022 - 07 - 26)

               最后,我们调用.step()启动梯度下降。 优化器通过.grad中存储的梯度来调整每个参数。

        optim.step() #gradient descent

        image.gif

                咱也不知道它干了个啥,貌似也没有啥输出......


        三、Autograd 自动求导:

               Autograd可以自动收集梯度:

        import torch
        a = torch.tensor([2., 3.], requires_grad=True)
        b = torch.tensor([6., 4.], requires_grad=True)

        image.gif

               用requires_grad=True创建两个张量ab。 这向autograd发出信号,应跟踪对它们的所有操作。

               通过创建的a和b张量构建了一个等式,计算结果等于张量Q:

        Q = 3 * a ** 3 - b ** 2

        image.gif

               假设ab是神经网络的参数,Q是误差(类似构造了一个损失函数)。 在 NN 训练中,我们想要相对于参数的误差(分别对参数求偏导),即

               当我们在Q上调用.backward()时,Autograd 将计算这些梯度并将其存储在各个张量的.grad属性中。我们需要在Q.backward()中显式传递gradient参数,因为它是向量。 gradient是与Q形状相同的张量,它表示Q相对于本身的梯度,即

               同样,我们也可以将Q聚合为一个标量,然后隐式地向后调用,例如Q.sum().backward()

        external_grad = torch.tensor([1., 1.])
        Q.backward(gradient=external_grad)

        image.gif

               梯度现在沉积在a.gradb.grad中,检查梯度是否相等:

        # check if collected gradients are correct
        print(9*a**2 == a.grad)
        print(-2*b == b.grad)

        image.gif

        tensor([True, True])
        tensor([True, True])

        image.gif


                又一个知识盲区:雅可比矩阵!!!太难了,都是数学!!!

               向量值函数y = f(x),则y相对于x的雅可比矩阵J

        image.gif编辑

               一般来说,torch.autograd是用于计算向量雅可比积的引擎。 也就是说,给定任何向量v,计算乘积J^T · v

               如果v恰好是标量函数的梯度

               然后根据链式规则,向量-雅可比积将是l相对于x的梯度:

        image.gif编辑

               上面的示例中使用的是 vector-Jacobian 乘积的这一特征。 external_grad表示v


        四、计算图:

               Autograd在由函数对象组成的有向无环图(DAG)中记录数据(张量)和所有已执行的操作(由已知张量计算产生的新张量)。在DAG中,叶子是输入张量,根是输出张量。通过从根到叶跟踪此图,可以使用链式规则自动计算梯度。

               DAG(Direct Acyclic Graph)中文名叫有向无环图,按照数学上的定义,DAG是一个没有有向循环的、有限的有向图。

               从DAG图中任意一个节点出发,根据方向无法回到原节点的图就叫做有向无环图。

        image.gif编辑

               在正向传播中,Autograd 同时执行两项操作:

          • 运行请求的操作以计算结果张量,并且
          • 在 DAG 中维护操作的梯度函数

                 当在 DAG 根目录上调用.backward()时,反向传递开始。 autograd然后:

            • 从每个.grad_fn计算梯度,
            • 将它们累积在各自的张量的.grad属性中,然后
            • 使用链式规则,一直传播到叶子张量。

                   下面是我们示例中 DAG 的直观表示。 在图中,箭头指向前进的方向。 节点代表正向传播中每个操作的反向函数。 蓝色的叶节点代表我们的叶张量ab

            image.gif编辑

                   DAG 在 PyTorch 中是动态的。要注意的重要一点是,图是从头开始重新创建的; 在每个.backward()调用之后,Autograd 开始填充新图。 这正是允许您在模型中使用控制流语句的原因。 您可以根据需要在每次迭代中更改形状,大小和操作。

            从 DAG 中排除张量的自动求导:

             torch.autograd跟踪所有将其requires_grad标志设置为True的张量的操作。 对于不需要梯度的张量,将此属性设置为False会将其从梯度计算 DAG 中排除。

                   当计算一个张量的时候,输入的其中一个或者多个张量是需要记录梯度的,这时候,计算得出的张量也是需要记录梯度的!!!

            x = torch.rand(5, 5)
            y = torch.rand(5, 5)
            z = torch.rand((5, 5), requires_grad=True)
            a = x + y
            print(f"Does `a` require gradients? : {a.requires_grad}")
            b = x + z
            print(f"Does `b` require gradients?: {b.requires_grad}")

            image.gif

            Does `a` require gradients? : False
            Does `b` require gradients?: True

            image.gif

                   在 NN 中,不计算梯度的参数通常称为冻结参数。 如果事先知道您不需要这些参数的梯度,则“冻结”模型的一部分很有用(通过减少自动梯度计算,这会带来一些性能优势)。

                   在微调中,我们冻结了大部分模型,通常仅修改分类器层以对新标签进行预测。 让我们来看一个小例子来说明这一点。 和以前一样,我们加载一个预训练的 resnet18 模型,并冻结所有参数。

            from torch import nn, optim
            model = torchvision.models.resnet18(pretrained=True)
            # Freeze all the parameters in the network
            # 循环遍历模型中的左右参数,并冻结他们的自动记录梯度:
            for param in model.parameters():
                param.requires_grad = False

            image.gif

                   假设我们要在具有 10 个标签的新数据集中微调模型。 在 resnet 中,分类器是最后一个线性层model.fc。 我们可以简单地将其替换为充当我们的分类器的新线性层(默认情况下未冻结)。

            model.fc = nn.Linear(512, 10)

            image.gif

                   现在,除了model.fc的参数外,模型中的所有参数都将冻结。 计算梯度的唯一参数是model.fc的权重和偏差。

            # Optimize only the classifier
            optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)

            image.gif

                   请注意,尽管我们在优化器中注册了所有参数,但唯一可计算梯度的参数(因此会在梯度下降中进行更新)是分类器的权重和偏差。

                   中的上下文管理器可以使用相同的排除功能。


            学习文档地址:torch.autograd的简要介绍 (apachecn.org)


            相关实践学习
            【AI破次元壁合照】少年白马醉春风,函数计算一键部署AI绘画平台
            本次实验基于阿里云函数计算产品能力开发AI绘画平台,可让您实现“破次元壁”与角色合照,为角色换背景效果,用AI绘图技术绘出属于自己的少年江湖。
            从 0 入门函数计算
            在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
            相关文章
            |
            4月前
            |
            机器学习/深度学习 人工智能 PyTorch
            PyTorch深度学习 ? 带你从入门到精通!!!
            🌟 蒋星熠Jaxonic,深度学习探索者。三年深耕PyTorch,从基础到部署,分享模型构建、GPU加速、TorchScript优化及PyTorch 2.0新特性,助力AI开发者高效进阶。
            PyTorch深度学习 ? 带你从入门到精通!!!
            |
            5月前
            |
            机器学习/深度学习 存储 PyTorch
            Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
            Neural ODE将神经网络与微分方程结合,用连续思维建模数据演化,突破传统离散层的限制,实现自适应深度与高效连续学习。
            450 3
            Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
            |
            8月前
            |
            机器学习/深度学习 存储 PyTorch
            PyTorch + MLFlow 实战:从零构建可追踪的深度学习模型训练系统
            本文通过使用 Kaggle 数据集训练情感分析模型的实例,详细演示了如何将 PyTorch 与 MLFlow 进行深度集成,实现完整的实验跟踪、模型记录和结果可复现性管理。文章将系统性地介绍训练代码的核心组件,展示指标和工件的记录方法,并提供 MLFlow UI 的详细界面截图。
            374 2
            PyTorch + MLFlow 实战:从零构建可追踪的深度学习模型训练系统
            |
            机器学习/深度学习 数据可视化 算法
            PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络
            神经常微分方程(Neural ODEs)是深度学习领域的创新模型,将神经网络的离散变换扩展为连续时间动力系统。本文基于Torchdyn库介绍Neural ODE的实现与训练方法,涵盖数据集构建、模型构建、基于PyTorch Lightning的训练及实验结果可视化等内容。Torchdyn支持多种数值求解算法和高级特性,适用于生成模型、时间序列分析等领域。
            624 77
            PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络
            |
            机器学习/深度学习 PyTorch TensorFlow
            深度学习工具和框架详细指南:PyTorch、TensorFlow、Keras
            在深度学习的世界中,PyTorch、TensorFlow和Keras是最受欢迎的工具和框架,它们为研究者和开发者提供了强大且易于使用的接口。在本文中,我们将深入探索这三个框架,涵盖如何用它们实现经典深度学习模型,并通过代码实例详细讲解这些工具的使用方法。
            1100 0
            |
            机器学习/深度学习 算法 PyTorch
            深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
            这篇文章详细介绍了多种用于目标检测任务中的边界框回归损失函数,包括IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU和WIOU,并提供了它们的Pytorch实现代码。
            3878 1
            深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU、SIOU、WIOU损失函数分析及Pytorch实现
            |
            机器学习/深度学习 监控 PyTorch
            深度学习工程实践:PyTorch Lightning与Ignite框架的技术特性对比分析
            在深度学习框架的选择上,PyTorch Lightning和Ignite代表了两种不同的技术路线。本文将从技术实现的角度,深入分析这两个框架在实际应用中的差异,为开发者提供客观的技术参考。
            441 7
            |
            机器学习/深度学习 算法 搜索推荐
            深度学习之差分隐私
            基于深度学习的差分隐私是一种在保护用户隐私的同时使用数据进行模型训练的技术。它的核心理念是通过加入随机噪声来隐藏个体数据的影响,防止在分析或模型训练过程中泄露个人信息。
            1462 1
            |
            机器学习/深度学习 算法 数据可视化
            如果你的PyTorch优化器效果欠佳,试试这4种深度学习中的高级优化技术吧
            在深度学习领域,优化器的选择对模型性能至关重要。尽管PyTorch中的标准优化器如SGD、Adam和AdamW被广泛应用,但在某些复杂优化问题中,这些方法未必是最优选择。本文介绍了四种高级优化技术:序列最小二乘规划(SLSQP)、粒子群优化(PSO)、协方差矩阵自适应进化策略(CMA-ES)和模拟退火(SA)。这些方法具备无梯度优化、仅需前向传播及全局优化能力等优点,尤其适合非可微操作和参数数量较少的情况。通过实验对比发现,对于特定问题,非传统优化方法可能比标准梯度下降算法表现更好。文章详细描述了这些优化技术的实现过程及结果分析,并提出了未来的研究方向。
            517 1

            推荐镜像

            更多