详解梯度消失和梯度爆炸(反向传播)?

什么是梯度消失?

梯度消失(Gradient Vanishing) 是指在训练神经网络时,反向传播过程中计算得到的梯度(用于更新参数的重要信息)随着网络层数的增加而急剧减小,甚至趋近于零的现象。这会导致深层网络中靠近输入层的参数难以被有效更新,模型训练困难,甚至无法收敛。

梯度消失的核心原因

梯度消失的本质与反向传播的计算机制激活函数的特性密切相关:

  1. 反向传播的链式法则 神经网络的参数更新依赖反向传播算法,而梯度的计算遵循链式法则。对于一个深层网络,某一层参数的梯度需要通过其后续所有层的梯度相乘得到。例如,对于一个 3 层网络(输入层→隐藏层 1→隐藏层 2→输出层),隐藏层 1 的参数梯度需要乘以隐藏层 2 的梯度和输出层的梯度。 如果这些梯度的乘积小于 1(且层数较多),多次相乘后会导致梯度趋近于 0,即: 梯度1\times梯度2\times梯度3 \times\cdots 梯度n 当 n 很大且每个梯度小于 1 时,结果会 “消失”。

  2. 激活函数的选择 早期神经网络常用 sigmoid 或 tanh 等饱和激活函数,其导数特性会加剧梯度消失。若网络中多层使用这类激活函数,反向传播时梯度会被反复乘以小于 1 的值,导致深层梯度快速衰减。

梯度消失的危害

  • 深层参数难以更新:靠近输入层的参数梯度几乎为 0,无法通过训练优化,导致这些层的参数近似 “冻结”,失去学习能力。
  • 模型欠拟合:深层网络的优势(捕捉复杂特征)无法发挥,模型可能退化为浅层网络的效果。
  • 训练不稳定:梯度过小会导致参数更新缓慢,模型收敛速度极慢,甚至停滞在较差的局部最优解。

梯度消失的解决方法

为缓解梯度消失问题,研究者提出了多种方案:

  1. 使用非饱和激活函数 用 ReLU(Rectified Linear Unit) 及其变体(如 Leaky ReLU、ELU)替代 sigmoid/tanh。ReLU 的导数在正区间为 1,避免了梯度衰减(但需注意 “死亡 ReLU” 问题)。

  2. 权重初始化策略 合理的参数初始化可减少梯度消失的概率,例如:

    • Xavier 初始化:适用于 tanh/sigmoid 等激活函数,使各层输入和输出的方差一致,避免梯度过度衰减或爆炸。
    • He 初始化:适用于 ReLU,考虑了 ReLU 会将一半输入置零的特性,进一步平衡梯度。
  3. 批量归一化(Batch Normalization) 通过对每一层的输入进行标准化(调整均值和方差),使激活值分布更稳定,避免进入激活函数的饱和区域,从而维持梯度大小。

  4. 残差网络(ResNet) 引入 “跳跃连接”(Skip Connection),让梯度可以直接从深层传递到浅层,绕过中间层的链式乘法,有效缓解深层网络的梯度消失。

  5. 梯度裁剪(Gradient Clipping) 虽然主要用于解决梯度爆炸,但适度裁剪也能避免梯度在反向传播中因过度衰减而消失(通过限制梯度的范围)。

示例:sigmoid 激活函数导致的梯度消失

        假设一个深层网络使用 sigmoid 激活函数,其导数为: 

\sigma {}'\left ( x \right )= \sigma \left ( x \right )\cdot (1-\sigma \left ( x \right )) \leq 0.25

        若网络有 10 层,每层梯度均为 0.25,则输入层的梯度为 0.25^{10} \approx 10^{-6},几乎为 0,导致参数无法更新。

什么是梯度爆炸?

梯度爆炸(Gradient Explosion)是深度学习中一种常见的优化问题,指在模型训练过程中,梯度(损失函数对参数的偏导数)的数值变得异常巨大,导致模型参数更新幅度过大,甚至超出合理范围,最终使模型无法收敛或性能严重下降。

梯度爆炸的本质与表现

在反向传播算法中,模型参数的更新依赖于梯度的计算。对于深层神经网络,梯度需要从输出层反向传播到输入层,过程中可能涉及多个矩阵乘法(或链式求导)。如果梯度在传播过程中被不断放大(例如,每次乘法都乘以一个大于 1 的数值),就会导致梯度数值呈指数级增长,最终超出计算机可表示的数值范围(如浮点数溢出)。

常见表现
  • 模型参数值急剧增大,甚至变成NaN(非数值)或inf(无穷大)。
  • 损失函数值剧烈波动,无法稳定下降,甚至突然飙升。
  • 模型输出结果异常(如数值极大),预测毫无意义。
  • 训练过程早期就出现收敛失败(如损失为NaN)。

梯度爆炸的典型原因

  1. 深层网络的链式求导
    深层网络中,梯度通过多层反向传播时,若每一层的权重矩阵的谱范数(最大特征值)大于 1,梯度会随网络深度增加而呈指数级放大。例如,对于一个 10 层网络,若每层梯度放大 1.1 倍,最终梯度将是初始值的1.1^10 ≈ 2.6倍;若每层放大 2 倍,10 层后将达到2^10 = 1024倍,极易爆炸。

  2. 权重初始化不当
    若初始权重值设置过大,会导致前向传播的输出值过大,反向传播时梯度也会随之放大,形成恶性循环。

  3. 激活函数选择
    使用某些激活函数(如sigmoid在输入值过大时导数接近 0,但早期未标准化的输入可能导致中间层输出过大)或未对输入数据进行标准化处理,可能间接加剧梯度放大。

  4. 批量归一化(Batch Normalization)缺失
    若未使用批量归一化稳定各层输入的分布,深层网络中每层的输入值可能随训练不断放大,进一步导致梯度爆炸。

梯度爆炸的危害

  • 模型无法收敛:参数更新幅度过大,导致损失函数在最小值附近剧烈震荡,甚至偏离最优解。
  • 数值不稳定:梯度或参数值超出浮点数表示范围,出现NaNinf,使训练中断。
  • 泛化能力差:即使模型勉强收敛,参数值过大也可能导致过拟合,或输出对输入变化过于敏感(鲁棒性差)。

解决梯度爆炸的常用方法

  1. 权重初始化
    采用合适的初始化方法(如 Xavier 初始化、He 初始化),使各层输入和梯度的方差保持在合理范围,避免初始权重过大。

  2. 梯度裁剪(Gradient Clipping)
    设定梯度的阈值,当梯度超过阈值时,将其缩放至阈值范围内(如按范数裁剪),强制限制梯度的最大值。

  3. 批量归一化(Batch Normalization)
    对每层的输入进行标准化(使均值为 0、方差为 1),稳定各层输入分布,减少梯度波动。

  4. 使用残差连接(Residual Connections)
    在深层网络(如 ResNet)中加入跳跃连接,使梯度可直接从后层传播到前层,避免梯度被多层乘法放大。

  5. 降低学习率
    较小的学习率可减少参数更新幅度,缓解梯度爆炸导致的参数剧烈波动。

  6. 选择合适的激活函数
    避免使用易导致输出值过大的激活函数,例如用 ReLU 及其变体(如 Leaky ReLU)替代 sigmoid 或 tanh(在极端值处梯度更稳定)。

梯度爆炸与梯度消失的关系? 

对比维度梯度消失(Gradient Vanishing)梯度爆炸(Gradient Exploding)
定义反向传播时,梯度随着网络层数增加逐渐减小至接近 0,导致深层参数几乎无法更新。反向传播时,梯度随着网络层数增加急剧增大,导致深层参数更新幅度过大,模型不稳定。
核心成因激活函数选择不当(如 sigmoid、tanh),其导数范围较小(sigmoid 导数最大 0.25),多层乘积后梯度趋近于 0。权重初始化过大,或激活函数导数大于 1(如 ReLU 在正区间导数为 1,但极端情况下权重累积可能导致梯度剧增),多层乘积后梯度呈指数级增长。
模型表现- 模型收敛缓慢或无法收敛
- 深层网络学习不到有效特征,性能差
- 训练后期 loss 下降停滞
- 模型参数剧烈波动,loss 震荡甚至发散
- 梯度值过大导致数值溢出(如出现infnan
- 模型权重值异常大,输出结果不稳定
常见场景- 深层神经网络(如早期的多层感知机)
- 使用 sigmoid/tanh 作为激活函数的网络
- 循环神经网络(RNN/LSTM/GRU)处理长序列时
- 权重初始化不合理的深层网络
- 未使用梯度裁剪的复杂网络
解决方法共性1. 合理初始化权重(如 Xavier 初始化、He 初始化)
2. 使用批量归一化(Batch Normalization)
3. 采用残差连接(Residual Connection)
4. 避免过度深的网络结构
1. 合理初始化权重(如 Xavier 初始化、He 初始化)
2. 使用批量归一化(Batch Normalization)
3. 采用残差连接(Residual Connection)
4. 避免过度深的网络结构
针对性解决方法1. 替换激活函数为 ReLU 及其变体(如 Leaky ReLU、Swish)
2. 使用 LSTM/GRU 替代传统 RNN(针对序列模型)
1. 梯度裁剪(Gradient Clipping):限制梯度的最大阈值
2. 权重正则化(如 L1/L2 正则化):约束权重大小
本质联系两者均为深层神经网络反向传播中梯度异常的问题,根源是链式法则下梯度的累积效应,仅在梯度变化方向上相反(一个趋近于 0,一个趋近于无穷)。两者均依赖网络深度放大梯度问题:层数越多,梯度消失或爆炸的可能性越高;且均会导致模型训练困难,无法有效学习特征。

梯度消失和梯度爆炸是深度网络中常见的问题。在参数初始化时需要非常小心,以确保梯度和参数可以得到很好的控制。

完整代码

"""
文件名: 4.8  数值稳定性和模型初始化
作者: 墨尘
日期: 2025/7/12
项目名: dl_env
备注: 
"""import torch
from torch import nn
from d2l import torch as d2l
# 手动显示图像(关键)
import matplotlib.pyplot as plt
import matplotlib.text as text  # 新增:用于修改文本绘制# -------------------------- 核心解决方案:替换减号 --------------------------
# 定义替换函数:将Unicode减号U+2212替换为普通减号-
def replace_minus(s):if isinstance(s, str):return s.replace('\u2212', '-')return s# 安全重写Text类的set_text方法,避免super()错误
original_set_text = text.Text.set_text  # 保存原始方法
def new_set_text(self, s):s = replace_minus(s)  # 替换减号return original_set_text(self, s)  # 调用原始方法
text.Text.set_text = new_set_text  # 应用新方法
# -------------------------------------------------------------------------# -------------------------- 字体配置(关键修改)--------------------------
# 解决中文显示和 Unicode 减号(U+2212)显示问题
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["text.usetex"] = True  # 使用Latex渲染
plt.rcParams["axes.unicode_minus"] = True  # 正确显示负号
plt.rcParams["mathtext.fontset"] = "cm"    # 确保数学符号(如减号)正常显示
d2l.plt.rcParams.update(plt.rcParams)      # 让 d2l 绘图工具继承字体配置
# -------------------------------------------------------------------------if __name__ == '__main__':# 1. 生成输入张量 x,范围从 -8 到 8,步长 0.1# requires_grad=True 表示需要计算关于 x 的梯度x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)# 2. 计算 sigmoid 函数值 y# sigmoid(x) = 1 / (1 + e^(-x))y = torch.sigmoid(x)# 3. 计算梯度(导数)# y.backward() 需要传入与 y 形状相同的张量,表示初始梯度# 这里传入全 1 张量,表示对每个元素的梯度权重为 1y.backward(torch.ones_like(x))# 4. 绘制 sigmoid 函数曲线和梯度曲线# x.detach().numpy():将 x 转换为 numpy 数组(绘图需要)# y.detach().numpy():sigmoid 函数值# x.grad.numpy():sigmoid 导数(梯度)值  # 梯度消失的现象集中体现在梯度(导数)值上d2l.plot(x.detach().numpy(), [y.detach().numpy(), x.grad.numpy()],legend=['sigmoid', 'gradient'], figsize=(4.5, 2.5))# 显示图像plt.show(block=True)  # block=True 确保窗口阻塞,直到手动关闭# 梯度爆炸M = torch.normal(0, 1, size=(4, 4))print('一个矩阵 \n', M)for i in range(100):M = torch.mm(M, torch.normal(0, 1, size=(4, 4)))print('乘以100个矩阵后\n', M)

实验结果 

梯度消失

梯度爆炸

 

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

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

相关文章

端到端自动驾驶:挑战与前沿

端到端自动驾驶:挑战与前沿 End-to-End Autonomous Driving: Challenges and Frontiers 自动驾驶研究社区已见证了越来越多采用端到端算法框架的方法的快速增长,这些方法利用原始传感器输入生成车辆的运动规划,而不是专注于诸如检测和运动预测…

rust cargo 编译双架构的库

这个错误表明你的 Rust 工具链没有安装 aarch64-apple-darwin 目标平台。以下是完整的解决方案: 解决方案 ​​安装目标平台​​ (必须步骤) rustup target add aarch64-apple-darwin​​验证安装​​ (可选但推荐) rustup target list --installed # 应该能看到 aa…

Apache Shiro 框架详解

文章目录一、Shiro 核心功能二、Shiro 架构2.1 三层架构2.2 核心组件(SecurityManager 内部)三、核心流程详解3.1 认证流程(登录)流程步骤:认证流程序列图:3.2 授权流程(权限校验)流…

【保姆级喂饭教程】Windows下安装Git Flow

目录前言一、SourceTree二、Git for Windows (previously MSysGit)1. 下载补丁1.1 getopt.exe1.2 libintl3.dll1.3 libiconv2.dll1.4 安装补丁2. 安装Git Flow3. 测试3.1 初始化(Initialize)3.2 设置远程3.3 创建分支3.4 功能开发3.5 功能提交3.6 推送分…

manifest.json只有源码视图没其他配置

项目场景:提示:这里简述项目相关背景:有时候我们从git上面拉下代码,第一次运行时发现,没运行项,再看manifest.json文件,就只有json文件,没有其他配置项原因分析:提示&…

数据分析-名词

一、网页访问数据指标1.IP (Internet Protocol)独立IP 通常采用独立IP数, 理论上指00:00-24:00内相同IP地址重复访问只被计算一次。而不同的商业统计工具,缩短去 掉重复统计的时间,也是数据统计放大的一个常用套路。 &…

UDP属于是一种什么服务器?

UDP是一种传输层协议,通常会被应用在计算机网络中,为企业与用户提供无连接的数据信息传输功能,与TCP协议相比较来说,UDP会更加的简单但是UDP在可靠性方面没有一定的保证,属于是一种基于UDP协议进行通信的服务器。UDP服…

ARM单片机OTA解析(一)

文章目录一、单片机烧写程序的几种方法二、Bootloader如何加载启动App一、单片机烧写程序的几种方法 在线应用编程,由开发者实现Bootloader功能,比如ARM单片机的Code分区中的Flash本是存储用户应用程序的区间(上电从此处执行用户代码),开发者…

C语言基础教程--从入门到精通

C语言基础教程–从入门到精通(总体概括) 接下来会对每一个章节进行详细的总结与整理,希望对大家有用!大家一起学习! 目录C语言基础教程--从入门到精通(总体概括)**接下来会对每一个章节进行详细…

单细胞分析教程 | (二)标准化、特征选择、降为、聚类及可视化

在完成质控(QC)后,我们已经过滤掉了低质量细胞、双细胞和低表达基因,获得了较为干净的单细胞数据集单细胞分析教程 | (一)Python单细胞质控全流程。接下来,我们将进行以下关键步骤: …

大模型 Agent(智能体)技术简介

大模型 Agent(智能体)技术 是当前人工智能领域的前沿方向,它赋予大型语言模型(LLM)自主感知、规划、决策和行动的能力,使其不再局限于“被动应答”,而是能主动完成复杂任务。简单来说&#xff0…

OneCode 3.0架构深度剖析:工程化模块管理与自治UI系统的设计与实现

引言 OneCode 3.0作为新一代低代码开发平台,其架构设计围绕"工程模块化"与"UI自主化"两大核心目标展开。本文将从底层接口到上层应用,全面解析OneCode 3.0的技术架构,包括核心工厂类、工程管理接口、数据仓库设计以及动态…

功耗校准数据PowerProfile测试方法建议

场景步骤版本:xxxxA1A2结果(mA)screen,full1.打开飞行模式,灭屏时间最长,其他的基础功能关2.进入到日历应用界面3.将亮度设置至最大(4095),待电流稳定后,测试5分钟,记录电…

[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+vue实现的供电公司安全生产考试管理系统,推荐!

摘 要 使用旧方法对安全生产考试信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在安全生产考试信息的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。 这次开发的供电公…

输入框过滤选项列表,el-checkbox-group单选

需求:根据输入的文本动态过滤选项列表,并在下方显示匹配到的选项。当用户勾选匹配到的选项时,把该选项的值赋值给输入框中绑定的值。当用户取消选择时,输入框中的字段可以随意编辑。组件:el-input、el-checkbox-group、…

身份认证缺陷

Authentication Bypasses审计创建AccountVerificationHelper实例,用于处理账户验证逻辑parseSecQuestions函数的作用是从请求体中遍历参数名,找到包含secQuestion的参数,将其值存入Map中并返回这里直接把AccountVerificationHelper整个分析一…

火山引擎:字节跳动的技术赋能初解

火山引擎是字节跳动旗下的企业级智能技术服务平台,于2020年6月正式上线。它通过开放字节跳动在大数据、人工智能、视频云等领域的核心技术,助力企业实现数字化转型与业务增长。火山引擎界面核心能力与技术亮点:1.全栈云服务公有云与混合云:提…

VUE 带有搜索功能的穿梭框(简单demo)

一、template/ 组件代码<el-dialog :title"title" :visible.sync"dialogVisible" width"60%" :before-close"handleClose" class"custom-dialog-line" ><div style"text-align: center ; width: 100%; height…

写个扫雷小游戏

1.test.c&#xff08;测试源文件&#xff09;2.game.c&#xff08;游戏源文件&#xff09;3.头文件

【Linux庖丁解牛】— system V共享内存!

1. 什么是system VSystem V IPC&#xff08;Interprocess Communication&#xff0c;进程间通信&#xff09;是Unix系统中一种经典的进程间通信机制&#xff0c;由AT&T在System V.2版本中引入&#xff0c;并广泛应用于Linux等现代操作系统中。它通过三种核心机制实现进程间…