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 * 2
    print(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,输出维度为1

    def 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个epoch
    optimizer.zero_grad()  # 清零梯度

    output = model(data)  # 前向传播
    loss = criterion(output, target)  # 计算损失
    loss.backward()  # 反向传播计算梯度

    optimizer.step()  # 更新参数

进一步说明

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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

Ceph入门到精通-ceph边缘集群你听说过嘛?

边缘集群是一种经济高效的对象存储配置解决方案。 Red Hat 支持以下 Red Hat Ceph Storage 集群的最低配置: 具有两个 SSD 副本的三节点集群。 具有三个 HDD 副本的四节点群集。 具有 EC 池的四节点集群,具有 2+2 配置。 对于较小的群集,由于使用量和复原能力的损失,利用率…

瓦罗兰特教你怎么玩低价区+超适配低价区的免费加速器

《无畏契约》(VALORANT)是一款款英雄为核心的5V5第一人称战术射击PC游戏。在瓦罗兰特游戏中,玩家完成每日任务即可以获得大量的经验升级,另外我们也可以多多完成主线和支线任务,来加快升级的速度。玩家通过挑战副本&am…

朋友圈新功能:实现定时发圈,自动跟圈

1.多号同时发圈 可以选择多个号同时发圈,提高工作效率。 2.定时发布 可以一次性设置完很多天的朋友圈,选好发送时间就可以解放双手。 3.一键转发 点击转发,可直接跳转到编辑页面。无需复制粘贴。 4.自动转发(跟圈) …

Ubuntu server 24 (Linux) 安装客户端(windows/linux) Zabbix 7.0 LTS Zabbix agent2

一 Ubuntu(linux)安装客户端 1 Ubuntu 24 安装Zabbix agent2 #安装agent库 sudo wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_7.0-1ubuntu24.04_all.deb sudo dpkg -i zabbix-release_7.0-1ubuntu24.04_all.deb sudo apt u…

极具吸引力的小程序 UI 风格

极具吸引力的小程序 UI 风格

mfc140.dll电脑文件丢失的处理方法,这4种方法能快速修复mfc140.dll

mfc140.dll文件是一个非常重要的dll文件,如果它丢失了,那么会严重的影响程序的运行,这时候我们要找方法去修复mfc140.dll这个文件,那么你知道怎么修复么?如果不知道,那么不妨看看下面的mfc140.dll文件丢失的…

ADS1220芯片写寄存器失败

1)场景:最近调试ADS1220 的芯片,需要读取不同通道的AD值,修改寄存器0的值时一直失败 但是在单片机启动时,写寄存器0时,值能正确写入,并正确读出,之后写完读取出的都是FF或其他异常值…

【Linux】基础IO——理解文件系统

1.理解文件系统 1.1.ls与stat 磁盘文件由两部分构成,分别是文件内容和文件属性。 文件内容就是文件当中存储的数据,文件属性就是文件的一些基本信息, 例如文件名、文件大小以及文件创建时间等信息都是文件属性,文件属性又被称…

使用源代码编译方式升级内核【笔记】

为什么要升级内核 升级内核有多个重要的原因,主要包括以下几点: 安全性:随着技术的发展,旧版本的内核可能会存在安全漏洞。黑客或恶意用户可能会利用这些漏洞进行攻击。升级内核可以修复这些已知的安全漏洞,从而提高系统的安全性。性能优化:新版本的内核通常会包含对性能…

四连杆机构运动学仿真 | Matlab源码+理论文本【超详细】

【程序简介】💻🔍 本程序通过matlab实现了四连杆机构的运动学仿真编程,动态展现了四连杆机构的角位移、角速度和角加速度的时程曲线,除了程序本身,还提供了机构运动学详细的公式推导文档,从而帮助大家更好…

【Spine学习14】之 人物死亡动作 思路总结

其实大致过程跟攻击那个流程一样了 没什么特别的 就只是K帧不一样: 记录一下,姿势参考就好 0s还是跟攻击一样的站立姿势 10s帧 22s帧 40s帧 不同的是把角色倒地时间延长了许多 这样看起来更合适一点 剑和盾在人物死亡的时候或脱离手心 移动开一些距离…

newtonsoft.json动态读取json以及动态生成

问题 同一个接口返回不同类型的json&#xff0c;json结构相差比较大转换为C#对象不太合适&#xff0c;想着是否可以动态解析。 newtonsoft类 JTokenType类型 namespace Newtonsoft.Json.Linq {/// <summary>/// Specifies the type of token./// </summary>publ…

2024年618成交额达7428亿 淘宝京东618交易额数据对比排名

2024年618年中大促已经基本落下帷幕&#xff0c;作为上半年最重要的电商节日&#xff0c;今年的618交易额有多少&#xff1f;今年的交易数据有哪些变化&#xff1f;我们来一起看一下&#xff01; 根据星图监测数据显示&#xff0c;2024年618期间&#xff08;天猫5月20日20: 00-…

2024年一年一度的618正式结束了,苹果与华为手机销量看看谁是大赢家?

一年一度的618正式结束了&#xff0c;各品牌基本上都发布了相应的战报。但是要告诉大家一点看战报要看定语&#xff0c;定语最少的才是真正的第一。现在给大家汇总下京东平台的数据&#xff0c;看看谁是最大赢家&#xff0c;谁又是国产荣光。注&#xff1a;所有数据截至6月18日…

关于app爬虫的环境准备

摘要 有些数据需要在手机应用中才能查看&#xff0c;没有网页版&#xff0c;所以学习移动端的爬虫是有必要的。 手机系统分为安卓和苹果两大系统&#xff0c;本次讲解主要以安卓手机为例 有安卓手机的可以使用手机&#xff0c;没有的可以使用模拟器&#xff0c;本次以夜神模…

打破数据分析壁垒:SPSS复习必备(二)

一、变量级别的数据管理 操作内容主要集中于“转换”菜单中&#xff0c;包括新变量的生成、记录的排序、对变量进行计数等。 (1)计算新变量&#xff1a;是菜单最上方的“计算变量”过程&#xff0c;这是该菜单中最为常用和重要的过程。 (2)变量转换&#xff1a;包括从菜单第2项…

【玩儿】TX应用宝模拟器安装第三方APK

TX应用宝模拟器安装第三方APK 前言应用宝下载安装三方APK安装审核应用安装自研应用安装执行 adb 命令创建应用快捷方式 前言 腾讯应用开放平台公布了应用宝电脑版的产品详情&#xff0c;应用宝电脑版支持从PC桌面直接打开安卓应用&#xff0c;无需感知应用市场打开界面&#x…

视频智能分析平台智能边缘分析一体机视频监控业务平台区域人数不足检测算法

智能边缘分析一体机区域人数不足检测算法是一种集成了先进图像处理、目标检测、跟踪和计数等功能的算法&#xff0c;专门用于实时监测和统计指定区域内的人数&#xff0c;并在人数不足时发出警报。以下是对该算法的详细介绍&#xff1a; 一、算法概述 智能边缘分析一体机区域…

centos7安装FTP服务器

目录 实验背景 一、配置yum源 1、本地yum 2、阿里云yum 二、安装vsftpd 1、安装vsftp服务 2、启动服务并设置开机自启动 3、开放防火墙和SELinux 三、创建用户和FTP目录 1、创建文件目录并配置权限 2、创建ftp组以及用户 四、修改vsftpd.conf文件 1、备份 vsftpd.c…