当前位置: 首页 > news >正文

【深度学习-Day 38】破解深度网络退化之谜:残差网络(ResNet)核心原理与实战

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

深度学习系列文章目录

01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
03-【深度学习-Day 3】搞懂微积分关键:导数、偏导数、链式法则与梯度详解
04-【深度学习-Day 4】掌握深度学习的“概率”视角:基础概念与应用解析
05-【深度学习-Day 5】Python 快速入门:深度学习的“瑞士军刀”实战指南
06-【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
07-【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战
08-【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程
09-【深度学习-Day 9】机器学习核心概念入门:监督、无监督与强化学习全解析
10-【深度学习-Day 10】机器学习基石:从零入门线性回归与逻辑回归
11-【深度学习-Day 11】Scikit-learn实战:手把手教你完成鸢尾花分类项目
12-【深度学习-Day 12】从零认识神经网络:感知器原理、实现与局限性深度剖析
13-【深度学习-Day 13】激活函数选型指南:一文搞懂Sigmoid、Tanh、ReLU、Softmax的核心原理与应用场景
14-【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
15-【深度学习-Day 15】告别“盲猜”:一文读懂深度学习损失函数
16-【深度学习-Day 16】梯度下降法 - 如何让模型自动变聪明?
17-【深度学习-Day 17】神经网络的心脏:反向传播算法全解析
18-【深度学习-Day 18】从SGD到Adam:深度学习优化器进阶指南与实战选择
19-【深度学习-Day 19】入门必读:全面解析 TensorFlow 与 PyTorch 的核心差异与选择指南
20-【深度学习-Day 20】PyTorch入门:核心数据结构张量(Tensor)详解与操作
21-【深度学习-Day 21】框架入门:神经网络模型构建核心指南 (Keras & PyTorch)
22-【深度学习-Day 22】框架入门:告别数据瓶颈 - 掌握PyTorch Dataset、DataLoader与TensorFlow tf.data实战
23-【深度学习-Day 23】框架实战:模型训练与评估核心环节详解 (MNIST实战)
24-【深度学习-Day 24】过拟合与欠拟合:深入解析模型泛化能力的核心挑战
25-【深度学习-Day 25】告别过拟合:深入解析 L1 与 L2 正则化(权重衰减)的原理与实战
26-【深度学习-Day 26】正则化神器 Dropout:随机失活,模型泛化的“保险丝”
27-【深度学习-Day 27】模型调优利器:掌握早停、数据增强与批量归一化
28-【深度学习-Day 28】告别玄学调参:一文搞懂网格搜索、随机搜索与自动化超参数优化
29-【深度学习-Day 29】PyTorch模型持久化指南:从保存到部署的第一步
30-【深度学习-Day 30】从MLP的瓶颈到CNN的诞生:卷积神经网络的核心思想解析
31-【深度学习-Day 31】CNN基石:彻底搞懂卷积层 (Convolutional Layer) 的工作原理
32-【深度学习-Day 32】CNN核心组件之池化层:解密最大池化与平均池化
33-【深度学习-Day 33】从零到一:亲手构建你的第一个卷积神经网络(CNN)
34-【深度学习-Day 34】CNN实战:从零构建CIFAR-10图像分类器(PyTorch)
35-【深度学习-Day 35】实战图像数据增强:用PyTorch和TensorFlow扩充你的数据集
36-【深度学习-Day 36】CNN的开山鼻祖:从LeNet-5到AlexNet的架构演进之路
37-【深度学习-Day 37】VGG与GoogLeNet:当深度遇见宽度,CNN架构的演进之路
38-【深度学习-Day 38】破解深度网络退化之谜:残差网络(ResNet)核心原理与实战


文章目录

  • Langchain系列文章目录
  • Python系列文章目录
  • PyTorch系列文章目录
  • 机器学习系列文章目录
  • 深度学习系列文章目录
  • Java系列文章目录
  • JavaScript系列文章目录
  • 深度学习系列文章目录
  • 摘要
  • 一、引言:当网络越来越深
    • 1.1 深度学习的“深度”崇拜
    • 1.2 意想不到的瓶颈:网络退化(Degradation)
      • 1.2.1 什么是网络退化问题?
      • 1.2.2 退化 vs. 过拟合
      • 1.2.3 问题的根源
  • 二、ResNet 的核心思想:残差学习
    • 2.1 另辟蹊径:学习“残差”而非“目标”
      • 2.1.1 恒等映射的挑战
      • 2.1.2 残差学习的提出
    • 2.2 革命性设计:残差块(Residual Block)
      • 2.2.1 残差块的结构
      • 2.2.2 数学表达
      • 2.2.3 快捷连接的重要性
  • 三、ResNet 网络架构解析
    • 3.1 ResNet 的整体构建
    • 3.2 两种残差块:BasicBlock 与 Bottleneck
      • 3.2.1 BasicBlock(用于浅层ResNet)
      • 3.2.2 Bottleneck Block(用于深层ResNet)
    • 3.3 PyTorch 实战:构建一个 ResNet-18
      • 3.3.1 定义 BasicBlock
      • 3.3.2 搭建 ResNet-18 主体
  • 四、ResNet 的深远影响与优势
    • 4.1 解决了深度难题
    • 4.2 缓解梯度消失
    • 4.3 成为现代CNN的基石
  • 五、总结


摘要

随着深度学习的发展,研究者们发现简单地堆叠网络层数并不能保证性能的持续提升,反而可能导致“网络退化”问题——即更深的网络在训练集上的表现甚至不如较浅的网络。为解决这一瓶颈,何恺明等研究员在2015年提出了革命性的残差网络(Residual Network, ResNet)。ResNet的核心在于引入了“残差学习”框架和“快捷连接”(Shortcut Connection),它巧妙地改变了网络的学习目标,使得优化深层网络变得异常容易。本文将深入剖析网络退化问题的本质,详细阐述ResNet的设计哲学、核心组件“残差块”的工作原理,并提供基于PyTorch的实现代码。通过理解ResNet,你将掌握构建超深神经网络的关键,并洞悉其为何能成为计算机视觉乃至整个深度学习领域的里程碑式工作。

一、引言:当网络越来越深

在卷积神经网络(CNN)的发展史上,从LeNet到AlexNet,再到VGG,一个清晰的趋势是:网络变得越来越深。理论上,更深的网络拥有更强的特征提取和函数拟合能力。然而,当研究者们尝试构建百层甚至千层的网络时,却遇到了一个意想不到的障碍。

1.1 深度学习的“深度”崇拜

在VGG网络中,研究者们通过反复堆叠简单的3x3卷积层和2x2池化层,成功构建了16到19层深的网络,并在ImageNet竞赛中取得了优异成绩。这似乎印证了一个朴素的认知:网络越深,模型看到的特征层次越丰富(从边缘、纹理到部件、对象),表达能力就越强,性能也应该越好。这激发了社群探索更深层次网络的热情。

1.2 意想不到的瓶颈:网络退化(Degradation)

然而,实践结果却令人困惑。当网络深度从几十层增加到更多层时,模型的性能开始出现饱和,甚至迅速下降。

1.2.1 什么是网络退化问题?

网络退化现象指的是:对于一个已经训练好的较浅层网络,当在其基础上增加更多的网络层来构建一个更深的网络时,这个更深的网络在训练集上的错误率(Training Error)反而更高了。

下图直观地展示了这一现象。在一个实验中,56层的网络无论是在训练集还是测试集上,其表现都逊色于20层的网络。

1.2.2 退化 vs. 过拟合

初学者很容易将“退化”与“过拟合”混淆,但它们是两个截然不同的问题:

  • 过拟合(Overfitting): 模型在训练集上表现优异,但在测试集上表现糟糕。这是因为模型过度学习了训练数据的噪声和细节,泛化能力差。
  • 网络退化(Degradation): 模型在训练集上的表现就已经不佳了。更深的模型甚至无法达到较浅模型的训练效果。

既然更深的模型连训练集都无法很好地拟合,这说明问题并非出在泛化能力上,而是出在**优化(Optimization)**上——即我们无法有效地训练这个更深的网络。

1.2.3 问题的根源

理论上,一个更深的网络至少应该能达到和较浅网络一样的性能。假设我们有一个训练好的 NNN 层网络,我们可以构建一个更深的 MMM 层网络(MNM \> NMN),只需让前 NNN 层复制原网络的参数,而后 M−NM-NMN 层只进行“恒等映射”(Identity Mapping),即输入是什么,输出就是什么(H(x)=xH(x) = xH(x)=x)。这样,这个更深的网络至少能获得与 NNN 层网络完全相同的性能。

然而,事实证明,让多个堆叠的非线性层(如CONV -> ReLU)去拟合一个恒等映射,在优化上是极其困难的。优化器很难找到合适的参数,使得这些新增的层能够“什么都不做”。这正是网络退化问题的症结所在。

二、ResNet 的核心思想:残差学习

面对网络退化这一棘手问题,ResNet的作者没有从优化算法本身入手,而是巧妙地改变了网络层的学习目标,让“什么都不做”变得轻而易举。

2.1 另辟蹊径:学习“残差”而非“目标”

2.1.1 恒等映射的挑战

如前所述,让一叠网络层学习恒等函数 H(x)=xH(x) = xH(x)=x 是非常困难的。那么,有没有一种方法能让网络“天生”就更容易学习恒等映射呢?

2.1.2 残差学习的提出

ResNet的精髓在于,它不让网络层直接学习目标映射 H(x)H(x)H(x),而是学习该映射与输入 xxx 之间的残差(Residual),即 F(x):=H(x)−xF(x) := H(x) - xF(x):=H(x)x

这样,原始的目标映射就被重新表述为:
H(x)=F(x)+xH(x) = F(x) + xH(x)=F(x)+x
这个简单的变换带来了巨大的优势。如果某个网络层的最优选择是恒等映射,那么优化器不再需要费力地将权重调整到拟合 H(x)=xH(x)=xH(x)=x,而只需要将残差部分 F(x)F(x)F(x) 的权重和偏置参数推向零即可。学习一个零映射(F(x)=0F(x)=0F(x)=0)远比学习一个恒等映射(H(x)=xH(x)=xH(x)=x)要容易得多。

2.2 革命性设计:残差块(Residual Block)

为了在网络结构中实现 H(x)=F(x)+xH(x) = F(x) + xH(x)=F(x)+x 的思想,ResNet设计了标志性的残差块

2.2.1 残差块的结构

一个残差块由两部分组成:

  1. 主路(Main Path): 即传统的卷积路径,由若干个卷积层和激活函数构成。这部分用于学习残差函数 F(x)F(x)F(x)
  2. 快捷连接/跳跃连接(Shortcut/Skip Connection): 将块的输入 xxx 直接“跳过”主路,与主路的输出 F(x)F(x)F(x) 进行逐元素相加。

2.2.2 数学表达

残差块的输出 yyy 可以用以下公式表示:
y=F(x,{Wi})+xy = F(x, \{W_i\}) + xy=F(x,{Wi})+x
其中:

  • xxx 是残差块的输入。
  • yyy 是残差块的输出。
  • F(x,W_i)F(x, {W\_i})F(x,W_i) 代表主路的网络层(例如,两个卷积层),W_i{W\_i}W_i 是这些层的权重。
  • + 操作是逐元素的加法。

注意:为了保证 F(x,W_i)F(x, {W\_i})F(x,W_i)xxx 能够相加,它们的维度必须相同。如果维度不同(例如,由于卷积的步幅或通道数变化),需要对 xxx 进行一个线性变换(通常是一个1x1卷积)来匹配维度。

2.2.3 快捷连接的重要性

快捷连接是ResNet的灵魂,它至少带来了两个核心优势:

  1. 简化恒等映射学习:如前所述,如果恒等映射是最优的,网络只需将主路 F(x)F(x)F(x) 的权重学习为零,这比直接学习 H(x)=xH(x)=xH(x)=x 容易得多。这直接解决了网络退化问题。
  2. 缓解梯度消失:在反向传播过程中,梯度可以通过快捷连接直接从后层传递到前层,形成一条“高速公路”。这保证了即使在非常深的网络中,梯度也能够有效地回传,极大地缓解了梯度消失问题,使得训练百层甚至千层网络成为可能。

三、ResNet 网络架构解析

ResNet并非单一模型,而是一个系列,包括ResNet-18, ResNet-34, ResNet-50, ResNet-101, ResNet-152等不同深度的版本。它们都遵循相似的设计原则,但使用了不同类型的残差块。

3.1 ResNet 的整体构建

ResNet的整体架构借鉴了VGG的简洁设计,主要由一个初始卷积层、多个阶段的残差块堆叠以及一个最终的全连接分类层组成。

  1. 初始卷积:使用一个较大的卷积核(如7x7)和步幅(如2)进行初步的特征提取和降采样。
  2. 残差块阶段:通常包含4个阶段,每个阶段由多个残差块串联而成。每个阶段开始时,通常会通过步幅为2的卷积将特征图尺寸减半,并将通道数翻倍。
  3. 全局平均池化与分类:在所有残差块之后,使用全局平均池化(Global Average Pooling)将每个特征图缩减为一个值,然后连接到全连接层进行分类。

3.2 两种残差块:BasicBlock 与 Bottleneck

为了适应不同深度的网络,ResNet设计了两种残差块。

3.2.1 BasicBlock(用于浅层ResNet)

BasicBlock 用于较浅的网络,如ResNet-18和ResNet-34。它由两个3x3的卷积层构成,结构相对简单。

BasicBlock
Shortcut
Conv 3x3
输入 x
BatchNorm
ReLU
Conv 3x3
BatchNorm
+
ReLU
输出 y

3.2.2 Bottleneck Block(用于深层ResNet)

对于ResNet-50及更深的网络,如果继续使用BasicBlock,计算成本会非常高。因此,作者设计了更高效的Bottleneck(瓶颈)结构。它使用“降维-卷积-升维”的策略:

  1. 1x1卷积:先将输入的通道数减少(例如,从256降到64),形成“瓶颈”。
  2. 3x3卷积:在降维后的特征图上进行标准的3x3卷积。
  3. 1x1卷积:再用一个1x1卷积将通道数恢复到原来的数量(例如,从64恢复到256)。

这种设计在保持相似感受野的同时,大大减少了参数量和计算量。

3.3 PyTorch 实战:构建一个 ResNet-18

下面我们使用PyTorch代码来定义BasicBlock并搭建一个简化的ResNet-18模型。

3.3.1 定义 BasicBlock

import torch
import torch.nn as nnclass BasicBlock(nn.Module):expansion = 1 # 通道数扩展倍数def __init__(self, in_channels, out_channels, stride=1):super(BasicBlock, self).__init__()# 主路self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)self.bn1 = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)self.bn2 = nn.BatchNorm2d(out_channels)# 快捷连接self.shortcut = nn.Sequential()# 如果输入输出维度不一致,需要通过1x1卷积调整if stride != 1 or in_channels != self.expansion * out_channels:self.shortcut = nn.Sequential(nn.Conv2d(in_channels, self.expansion * out_channels, kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(self.expansion * out_channels))def forward(self, x):out = self.relu(self.bn1(self.conv1(x)))out = self.bn2(self.conv2(out))# 将主路输出与快捷连接相加out += self.shortcut(x)out = self.relu(out)return out

3.3.2 搭建 ResNet-18 主体

class ResNet(nn.Module):def __init__(self, block, num_blocks, num_classes=1000):super(ResNet, self).__init__()self.in_channels = 64# 初始卷积层self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)# 四个残差块阶段self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)# 分类层self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(512 * block.expansion, num_classes)def _make_layer(self, block, out_channels, num_blocks, stride):strides = [stride] + [1] * (num_blocks - 1)layers = []for s in strides:layers.append(block(self.in_channels, out_channels, s))self.in_channels = out_channels * block.expansionreturn nn.Sequential(*layers)def forward(self, x):out = self.maxpool(self.relu(self.bn1(self.conv1(x))))out = self.layer1(out)out = self.layer2(out)out = self.layer3(out)out = self.layer4(out)out = self.avgpool(out)out = torch.flatten(out, 1)out = self.fc(out)return outdef ResNet18():# ResNet-18每个阶段的残差块数量为[2, 2, 2, 2]return ResNet(BasicBlock, [2, 2, 2, 2])# 实例化模型并查看结构
model = ResNet18()
# print(model)

四、ResNet 的深远影响与优势

ResNet的提出是深度学习发展史上的一个重要转折点。

4.1 解决了深度难题

ResNet通过残差学习直接攻克了网络退化问题,首次成功地将神经网络的深度扩展到了百层乃至千层,并观察到了性能的持续提升。

4.2 缓解梯度消失

快捷连接创建了梯度的“高速公路”,使得梯度能够更顺畅地在网络中传播,极大地缓解了在深层网络中常见的梯度消失问题。

4.3 成为现代CNN的基石

ResNet的设计理念影响了后续无数的CNN架构。它本身及其变种(如ResNeXt, Wide ResNet, Res2Net等)至今仍是各种计算机视觉任务(如图像分类、目标检测、语义分割)中最常用、最可靠的骨干网络(Backbone)。可以说,现代的深度CV模型,几乎都构建在残差连接的思想之上。

五、总结

本文深入探讨了经典而强大的ResNet架构,其核心贡献和要点可归纳如下:

  1. 直面核心痛点:ResNet的诞生是为了解决“网络退化”问题,即深度网络在训练集上的性能反而不如浅层网络的反常现象,其根源在于深度非线性层难以优化以拟合恒等映射。
  2. 创新的残差学习:ResNet巧妙地将学习目标从直接的映射 H(x)H(x)H(x) 转变为学习残差 F(x)=H(x)−xF(x) = H(x) - xF(x)=H(x)x。这使得当恒等映射为最优时,网络只需将残差部分的权重学习为零,极大降低了优化难度。
  3. 关键的快捷连接:残差块中的快捷连接(Shortcut Connection)是实现残差学习的结构基础。它不仅使得学习恒等映射变得容易,更重要的是,它为梯度的反向传播提供了“绿色通道”,有效缓解了梯度消失问题,为训练超深网络铺平了道路。
  4. 灵活的模块化设计:ResNet通过堆叠统一的残差块(BasicBlock或Bottleneck)来构建网络,设计清晰且易于扩展。针对不同深度需求,采用不同复杂度的残差块,在性能和计算效率之间取得了良好平衡。
  5. 里程碑式的意义:ResNet的成功不仅在于其卓越的性能,更在于它打破了人们对网络深度的限制认知,其“残差”思想深刻地影响了后续的神经网络架构设计,成为现代深度学习模型中不可或缺的基础组件。

http://www.dtcms.com/a/288317.html

相关文章:

  • openmv小车追小球
  • 如何设计一个软件项目管理系统:架构设计合集(六)
  • QGIS制作的仪表盘工程
  • Redisson RLocalCachedMap 核心参数详解
  • Python工厂方法模式详解:从理论到实战
  • Python绘制数据(三)
  • 创意 C++ 文本冒险战斗游戏代码
  • 2025年水安备考:水利水电安全员C类考试题
  • 高效检测数据突变的MDAM算法详解
  • 模电基础-电阻和功率
  • 网络通信之TCP协议
  • 深入解析HDFS读取流程:短路读优化、零拷贝技术与DFSClient本地缓存策略
  • 【ComfyUI学习笔记02】工作区的整理与注释办法 | 2个节点包推荐
  • 【Linux】如何理解 “一切皆文件”
  • 《一行注解解决重复提交:Spring Boot 接口幂等实战》
  • [硬件电路-40]:从物理世界到数字软件,信号处理的共通性
  • java基础(day11)
  • 突破 MySQL 性能瓶颈:死锁分析 + 慢查询诊断 + 海量数据比对实战
  • Redis布隆过滤器的学习(六)
  • 财务数字化——解读财务指标及财务分析的基本步骤与方法【附全文阅读】
  • 基于LSTM的时间序列到时间序列的回归模拟
  • 06-人机共生:Prompt之外的思考
  • Linux Shell 命令 + 项目场景
  • windows11下基于docker单机部署ceph集群
  • 同步队列阻塞器AQS的执行流程,案例图
  • 张量交换维度(转置),其实是交换了元素的排列顺序
  • lvs集群技术(Linux virual server)
  • MinIO深度解析:从核心特性到Spring Boot实战集成
  • 笔试大题20分值(用两个栈实现队列)
  • 基于densenet网络创新的肺癌识别研究