pytorch基础【4】梯度计算、链式法则、梯度清零

文章目录

  • 梯度计算
      • 计算图(Computational Graph)
      • 梯度求导(Gradient Computation)
        • 函数与概念
      • 示例代码
      • 更多细节
      • 梯度求导的过程
      • 梯度求导的基本步骤
      • 示例代码
      • 注意事项
      • 总结
    • 链式法则是什么?
      • 链式法则的数学定义
      • 链式法则在深度学习中的应用
      • 反向传播中的链式法则
      • 具体示例
        • 反向传播过程
      • 总结
    • 为什么需要梯度清零
      • 如何实现梯度清零
      • 进一步说明
      • 总结

梯度计算

在PyTorch中,计算图和梯度求导是核心功能之一,特别是在深度学习模型的训练过程中。以下是对这两个概念的详细解释:

计算图(Computational Graph)

计算图是一种有向无环图(Directed Acyclic Graph, DAG),其中节点表示操作(operation)或变量(variable),边表示操作的输入输出关系。PyTorch 使用计算图来记录和管理变量之间的依赖关系,以便在反向传播时计算梯度。在这里插入图片描述

  • 动态计算图(Dynamic Computational Graph):PyTorch 采用动态计算图(Dynamic Computational Graph),即每次进行前向传播(forward pass)时,都会动态构建一个新的计算图。这样做的好处是可以更灵活地处理各种复杂的模型结构,尤其是那些在每个前向传播中都会变化的模型。

梯度求导(Gradient Computation)

梯度求导是深度学习中优化模型参数的关键步骤。梯度描述了损失函数对每个参数的变化率,用于指导参数的更新方向。

  • 自动求导(Autograd):PyTorch 提供了一个强大的自动求导库,称为 Autograd。通过 Autograd,PyTorch 可以自动计算标量值(通常是损失函数)的梯度。
函数与概念
  1. torch.Tensor
    • Tensor 是 PyTorch 中存储数据和定义计算图的基础数据结构。默认情况下,所有的张量(Tensor)都不会自动追踪计算的历史。
    • 如果要使张量参与计算图并能够进行自动求导,需要在创建张量时设置 requires_grad=True
  2. backward()
    • 调用张量的 backward() 方法,PyTorch 会自动计算该张量的所有依赖张量的梯度,并存储在各自的 .grad 属性中。
    • backward() 只接受标量张量(一个数值),如果不是标量张量,通常会传递一个与张量形状匹配的梯度参数。
  3. torch.no_grad()
    • 在评估模型或推理时,我们不需要计算梯度,可以使用 torch.no_grad() 以节省内存和计算资源。

示例代码

import torch# 创建张量,并设置 requires_grad=True 以追踪其计算历史
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2# 计算图中 y 的梯度
y.backward()  # 计算 y 对 x 的梯度
print(x.grad)  # 输出 x 的梯度,dy/dx = 2*x => 4# 在不需要梯度计算的情况下进行计算
with torch.no_grad():z = x * 2print(z)  # 输出:tensor(4.0)

更多细节

  • 梯度累积与清零:每次调用 backward(),梯度会累积(即,累加到 .grad 属性中),因此在每次新的梯度计算之前通常需要清零现有的梯度,例如通过 optimizer.zero_grad()
  • 多次反向传播:如果在同一个计算图上进行多次反向传播(例如在 RNN 中),需要设置 retain_graph=True,以防止计算图被释放。

通过这些机制,PyTorch 提供了一个灵活且高效的框架,用于构建和训练复杂的神经网络模型。

梯度求导的过程

在PyTorch中,梯度求导的过程是通过自动微分(Autograd)机制实现的。以下是梯度求导过程的详细步骤:

梯度求导的基本步骤

  1. 定义计算图
    • 每当你对 torch.Tensor 进行操作时,PyTorch 会动态地创建一个计算图来记录操作。
    • 如果 Tensorrequires_grad 属性设置为 True,那么该张量会开始追踪其上的所有操作,这样你就可以调用 backward() 来自动计算其梯度。
  2. 前向传播(Forward Pass)
    • 计算图的构建是在前向传播过程中完成的。在前向传播过程中,输入数据通过神经网络的各层进行计算,最终生成输出。
  3. 计算损失(Loss Calculation)
    • 通常情况下,在前向传播结束后会计算损失函数(Loss),这是一个标量值,用于评估模型的输出与目标之间的差距。
  4. 反向传播(Backward Pass)
    • 调用损失张量的 backward() 方法。反向传播通过链式法则计算损失函数相对于每个叶子节点(即,所有具有 requires_grad=True 的张量)的梯度。
  5. 更新参数(Parameter Update)
    • 使用优化器(如 SGD、Adam 等)通过梯度下降或其他优化算法更新模型的参数。

示例代码

以下是一个简单的示例代码,演示了梯度求导的过程:

import torch
import torch.nn as nn
import torch.optim as optim# 定义一个简单的线性模型
class LinearModel(nn.Module):def __init__(self):super(LinearModel, self).__init__()self.linear = nn.Linear(1, 1)  # 输入维度为1,输出维度为1def forward(self, x):return self.linear(x)# 创建模型实例
model = LinearModel()# 定义损失函数和优化器
criterion = nn.MSELoss()  # 均方误差损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 随机梯度下降优化器# 创建输入数据和目标数据
inputs = torch.tensor([[1.0], [2.0], [3.0], [4.0]])
targets = torch.tensor([[2.0], [4.0], [6.0], [8.0]])# 前向传播
outputs = model(inputs)
loss = criterion(outputs, targets)# 反向传播
loss.backward()# 查看梯度
for param in model.parameters():print(param.grad)# 更新参数
optimizer.step()

步骤解析

  1. 创建模型和数据
    • 定义一个简单的线性回归模型,并创建输入数据和目标数据。
  2. 前向传播
    • 将输入数据传递给模型,计算输出。
    • 使用损失函数计算输出与目标之间的损失。
  3. 反向传播
    • 调用 loss.backward() 计算损失相对于每个参数的梯度。PyTorch 会通过计算图自动进行反向传播,计算各个参数的梯度并存储在 param.grad 中。
  4. 更新参数
    • 使用优化器的 step() 方法更新参数。这一步通常在每个训练迭代中执行。

注意事项

  • 梯度清零:在每次调用 backward() 之前,通常需要清零现有的梯度,以避免梯度累积。这可以通过 optimizer.zero_grad()model.zero_grad() 来实现。
  • 链式法则:反向传播过程中使用链式法则计算梯度,因此在计算图较深时,梯度的计算会逐层进行,直到计算到每个叶子节点。

总结

PyTorch 的自动微分机制使得梯度计算变得简单且高效,通过构建计算图并自动进行反向传播,你可以专注于模型的设计和训练,而不必手动计算复杂的梯度。

链式法则是什么?

链式法则(Chain Rule)是微积分中的一个基本法则,用于求复合函数的导数。在深度学习中,链式法则用于反向传播(backpropagation)算法的核心,帮助计算损失函数相对于每个模型参数的梯度。

链式法则的数学定义

假设有两个函数 u=f(x) 和 y=g(u),那么复合函数 y=g(f(x)) 的导数可以表示为:
d y d x = d y d u ⋅ d u d x \frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx} dxdy=dudydxdu

链式法则在深度学习中的应用

在深度学习中,神经网络由多个层组成,每一层可以看作是一个函数,这些函数依次连接形成一个复合函数。假设我们有一个三层的神经网络,其前向传播可以表示为:

  1. a=f(x)
  2. b=g(a)
  3. c=h(b)

损失函数 L可以表示为 L=l©,其中 x 是输入数据,a、b、c 是中间层的输出。

反向传播中的链式法则

在反向传播过程中,我们需要计算损失函数 L对每个参数的梯度。通过链式法则,我们可以逐层计算这些梯度。具体步骤如下:

  1. 计算损失函数相对于输出层的梯度
    ∂ L ∂ c \frac{\partial L}{\partial c} cL

  2. 计算损失函数相对于中间层 b的梯度
    ∂ L ∂ b = ∂ L ∂ c ⋅ ∂ c ∂ b \frac{\partial L}{\partial b} = \frac{\partial L}{\partial c} \cdot \frac{\partial c}{\partial b} bL=cLbc

  3. 计算损失函数相对于中间层 a 的梯度
    ∂ L ∂ a = ∂ L ∂ b ⋅ ∂ b ∂ a \frac{\partial L}{\partial a} = \frac{\partial L}{\partial b} \cdot \frac{\partial b}{\partial a} aL=bLab

  4. 计算损失函数相对于输入层 x的梯度
    ∂ L ∂ x = ∂ L ∂ a ⋅ ∂ a ∂ x \frac{\partial L}{\partial x} = \frac{\partial L}{\partial a} \cdot \frac{\partial a}{\partial x} xL=aLxa

通过这种逐层传播梯度的方式,我们可以计算每个参数的梯度,从而使用梯度下降法来更新模型参数。

具体示例

让我们通过一个具体的例子来说明链式法则的应用。假设我们有一个简单的神经网络,其前向传播过程如下:

  1. 输入 xxx

  2. 第一层:
    z 1 = W 1 x + b 1 z_1=W_1x+b_1 z1=W1x+b1

    ,激活函数
    a 1 = σ ( z 1 ) a_1 = \sigma(z_1) a1=σ(z1)

  3. 第二层:
    z 2 = W 2 a 1 + b 2 z_2 = W_2 a_1 + b_2 z2=W2a1+b2
    ,激活函数
    a 2 = σ ( z 2 ) a_2 = \sigma(z_2) a2=σ(z2)

  4. 输出层:
    y = W 3 a 2 + b 3 y = W_3 a_2 + b_3 y=W3a2+b3

损失函数 L 是输出 y 和目标 ytarget之间的均方误差。

反向传播过程

计算输出层的梯度
∂ L ∂ y = 2 ( y − y t a r g e t ) \frac{\partial L}{\partial y} = 2 (y - y_{target}) yL=2(yytarget)

计算第二层的梯度
∂ L ∂ z 2 = ∂ L ∂ y ⋅ ∂ y ∂ z 2 = ∂ L ∂ y ⋅ W 3 \frac{\partial L}{\partial z_2} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial z_2} = \frac{\partial L}{\partial y} \cdot W_3 z2L=yLz2y=yLW3

∂ L ∂ a 2 = ∂ L ∂ z 2 ⋅ σ ′ ( z 2 ) ∂ \frac{\partial L}{\partial a_2} = \frac{\partial L}{\partial z_2} \cdot \sigma'(z_2)∂ a2L=z2Lσ(z2)

计算第一层的梯度
∂ L ∂ z 1 = ∂ L ∂ a 2 ⋅ ∂ a 2 ∂ z 1 = ∂ L ∂ a 2 ⋅ W 2 \frac{\partial L}{\partial z_1} = \frac{\partial L}{\partial a_2} \cdot \frac{\partial a_2}{\partial z_1} = \frac{\partial L}{\partial a_2} \cdot W_2 z1L=a2Lz1a2=a2LW2

∂ L ∂ a 1 = ∂ L ∂ z 1 ⋅ σ ′ ( z 1 ) \frac{\partial L}{\partial a_1} = \frac{\partial L}{\partial z_1} \cdot \sigma'(z_1) a1L=z1Lσ(z1)

计算输入层的梯度
∂ L ∂ x = ∂ L ∂ a 1 ⋅ W 1 \frac{\partial L}{\partial x} = \frac{\partial L}{\partial a_1} \cdot W_1 xL=a1LW1

通过链式法则,反向传播算法能够有效地计算出每一层参数的梯度,从而更新参数,最小化损失函数。

总结

链式法则是微积分中的一个重要法则,它在深度学习中的反向传播算法中起到了关键作用。通过链式法则,我们可以有效地计算复合函数的导数,从而利用梯度下降等优化方法来训练神经网络模型。

在深度学习中,梯度清零(zeroing gradients)是训练过程中的一个关键步骤,通常在每次参数更新之前进行。这个过程在PyTorch等深度学习框架中尤为重要。以下是关于为什么需要梯度清零以及如何实现梯度清零的详细解释:

为什么需要梯度清零

  1. 防止梯度累积
    • 在每次反向传播计算中,梯度会累积到模型参数的 .grad 属性中。如果不清零,梯度会在每个小批次(mini-batch)训练后继续累积,这将导致错误的梯度更新。
    • 举例来说,如果没有清零,当前批次的梯度会与之前批次的梯度相加,导致最终的梯度远大于实际应该的值。这会使参数更新的步长不合理,影响模型训练效果。
  2. 正确的参数更新
    • 每个小批次的梯度计算都应该基于当前的小批次数据,确保每次参数更新都准确反映当前的小批次数据对损失函数的贡献。

如何实现梯度清零

在PyTorch中,梯度清零通常通过调用 optimizer.zero_grad() 来实现。这里有一个完整的例子来说明这一过程:

import torch
import torch.nn as nn
import torch.optim as optim# 定义一个简单的神经网络
class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()self.fc1 = nn.Linear(10, 5)self.fc2 = nn.Linear(5, 1)def forward(self, x):x = torch.relu(self.fc1(x))x = self.fc2(x)return x# 实例化模型和优化器
model = SimpleNet()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 生成一些假数据
data = torch.randn(10)  # 输入数据
target = torch.tensor([1.0])  # 目标标签# 损失函数
criterion = nn.MSELoss()# 训练过程中的一个小批次
for epoch in range(100):  # 假设训练100个epochoptimizer.zero_grad()  # 清零梯度output = model(data)  # 前向传播loss = criterion(output, target)  # 计算损失loss.backward()  # 反向传播计算梯度optimizer.step()  # 更新参数

进一步说明

  • 清零位置optimizer.zero_grad() 通常放在每个训练循环的开头,确保在计算新的梯度之前先将上一次迭代的梯度清零。
  • 梯度累积应用场景: 在某些特定情况下,例如梯度累积(Gradient Accumulation)技术中,故意让梯度在多个小批次上累积,然后再更新参数。但这是特定应用场景,不适用于标准的训练过程。

总结

梯度清零是深度学习模型训练中的一个重要步骤,确保每次参数更新时的梯度计算是正确的、独立的。通过 optimizer.zero_grad() 方法,我们可以有效地防止梯度累积问题,从而确保模型训练过程的稳定性和准确性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30478.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMR,支持30+种编程语言的SDK版本管理器,支持Windows/MacOS/Linux。

官方文档地址:documents 官方项目地址:github 欢迎安装使用,分享转发,前往github star。 跨平台,支持Windows,Linux,MacOS支持多种语言和工具,省心受到lazygit的启发,拥…

Flutter【组件】可折叠文本组件

简介 flutter 可折叠文本组件。 点击展开,收起折叠文本。支持样式自定义 github地址: github.com/ThinkerJack… pub地址:https://pub.dev/packages/jac_uikit 展开收起文本 使用方式: ExpandableText(content: 测试 * 50,ma…

生活实用口语柯桥成人外语培训机构“客服”用英文怎么说?

● 01. “客服”英语怎么说? ● 我们都知道“客服”就是“客户服务”, 所以Customer Service就是#15857575376客服的意思。 但是这里的“客服”指代的不是客服人员, 而是一种Service服务。 如果你想要表达客服人员可以加上具体的职位&a…

中国500米分辨率年平均LAI数据集(2000-2020)

叶面积指数LAI(Leaf Area Index)是描述植被冠层几何结构的基本参数之一,被定义为单位地表面积上所有叶片面积的倍数,它控制着植被的许多生物物理过程,如光合作用、呼吸作用、蒸腾作用、碳循环和降水截获等,是陆面过程一个十分重要…

安装免费版的jfrog artifactory oss

1、下载 软件,本案例安装的是 jfrog-artifactory-oss-7.59.11-linux.tar.gz https://releases.jfrog.io/artifactory/bintray-artifactory/org/artifactory/oss/jfrog-artifactory-oss/ 2、解压下载下来的压缩包 tar zxf jfrog-artifactory-oss-7.59.11-linux.tar…

10 种语言文本准确渲染;Mac无需联网的本地聊天应用;多模态语言模型(MLM)基准测试的引擎;Yolo DotNet版本

✨ 1: Glyph-ByT5 10 种语言文本准确渲染,将文本渲染的准确性从提高到近 90% ,同时还能实现段落渲染自动布局 Glyph-ByT5是一种定制的文本编码器,旨在实现准确的文字视觉渲染。其核心思想是通过细致的字形-文本配对数据集的微调&#xff0c…

VBA技术资料MF161:按需要显示特定工作表

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…

最新AI智能聊天对话问答系统源码(详细图文搭建部署教程)+AI绘画系统(Midjourney),DALL-E3文生图,TTS语音识别输入,文档分析

一、文章前言 随着人工智能技术的持续进步,AI绘画已经发展成为一个日益成熟的领域。越来越多的人开始尝试使用AI绘画软件来创作艺术作品。尽管这些AI绘画软件对绘画领域产生了显著影响,但它们并不会完全取代画师。与传统手绘不同,AI绘画可以…

ELISA Flex: Monkey IFN-γ (HRP)

ELISA Flex: Monkey IFN-γ (HRP)该ELISA试剂盒能够检测溶液样本比如细胞培养上清或者血清/血浆中猴子γ干扰素(IFN-γ)的含量。 产品组分: 捕获抗体:克隆号MT126L(0.5mg/ml) 检测抗体:克隆号7…

3d模型有个虚拟外框怎么去除?---模大狮模型网

在3D建模和渲染过程中,虚拟外框(Bounding Box)是一个常见的显示元素,用于表示模型的包围盒或选择状态。尽管虚拟外框在一些情况下有其作用,但在最终渲染或呈现阶段,我们通常希望清除这些辅助显示,以展示纯粹的模型效果…

深入了解 Android 中的 ViewStub

在 Android 开发中,性能优化一直是一个重要的话题。ViewStub 作为一种轻量级视图容器,可以帮助我们在合适的时机延迟加载视图,从而优化应用性能。本文将详细介绍 ViewStub 的概念、使用方法以及在实际开发中的应用场景。 什么是 ViewStub&am…

一个简单、快速用于训练和微调中等规模GPT模型的开源项目

大家好,今天给大家分享的是一个简单、快速用于训练和微调中等规模GPT模型的开源项目,该项目旨在拓宽深度学习领域的应用,特别是为深度学习的入门者提供便利。 Nano GPT是一个基于PyTorch的开源项目,由前特斯拉AI负责人Andrej Ka…

linux搭建sftp服务

1. 添加用户及用户组 使用 groupadd sftpgroup 添加sftpgroup 用户组; 使用useradd -G sftpgroup -s /sbin/nologin cmssftp给sftpgroup 添加cmssftp用户; 使用passwd cmssftp给用户cmssftp进行设置密码(默认为:654321)。具体如下图所示: 2.…

运维篇-配置高级

黑马程序员Spring Boot2 文章目录 1、临时属性1.1 命令行中使用临属性1.2 开发环境设定临时属性 2、配置文件分类3、自定义配置文件 1、临时属性 1.1 命令行中使用临属性 使用jar命令启动Sprigboot工程师可以使用临时属性替换配置文件中的属性临时属性添加方式:ja…

vue3 页面左右滑动钩子封装

// useSwiper.js文件 import { ref, onMounted, onUnmounted } from "vue"; export function useSwiper({tabList, //tab数据curTabId,// 当前tab idcurTabIndex,// 当前tab 索引tabChange,// tab改变事件animation,// 动画animationData,// 动画 }) {let minOffset …

jeecg spring数据源用户名和密码加密 避免明文安全漏洞

1.目的 由于系统部署在互联网,配置文件中的数据库账号密码使用明文,存在安全隐患,做等保测试时要求对其加密。 2.实现方法 Jeecg框架本身有PasswordUtil可以使用PBEWITHMD5andDES进行加密,这里为方便改造,且安全性较…

探索数据分析无限潜能:vividime Desktop助力企业智能决策

在数字化浪潮席卷全球的今天,数据已经成为企业最宝贵的资产之一。通过对海量数据的深度挖掘和分析,企业能够洞察市场趋势、优化运营流程、提升用户体验,从而在激烈的市场竞争中脱颖而出。永洪科技的vividime Desktop作为一款功能强大、操作简…

Scala语言:大数据开发的未来之星 - 零基础到精通入门指南

前言 随着大数据时代的到来,数据量的急剧增长为软件开发带来了新的挑战和机遇。Scala语言因其函数式编程和面向对象的特性,以及与Apache Spark的完美协作,在大数据开发领域迅速崛起,成为该领域的新兴宠儿。本篇将从零基础开始&…

【Java】Object、Objects、包装类、StringBuilder、StringJoiner

目录 1.API2.Object类3.Objects类4.包装类4.1包装类概述4.2包装类的其他常见操作 5.StringBuilder 可变字符串5.1概述5.2StringBuilder案例 6.StringJoiner 1.API API:应用程序编程接口,全称application programing interface,即Java已经写好…

从粉丝基础到带货数据:全方位解读TikTok带货达人的选择之道

在如今的数字营销时代,TikTok已成为品牌推广和产品销售的重要平台。通过与合适的TikTok带货达人合作,品牌可以迅速吸引大量的潜在客户,实现销售转化。然而,选择合适的TikTok达人需要慎重考虑多个因素。本文Nox聚星将和大家详细阐述…