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

深度学习——ResNet 卷积神经网络


ResNet 网络教学文章

一、背景介绍

在深度学习发展早期,研究者发现:更深的神经网络往往拥有更强的拟合能力。但在实际实验中,当网络层数不断加深时,效果却出现了瓶颈甚至退化现象:

  • 梯度消失/爆炸:反向传播时梯度越来越小或越来越大,导致训练困难。

  • 退化问题:在相同训练数据和优化策略下,增加网络深度反而导致训练误差升高。

针对这一问题,微软研究院的 Kaiming He 等人提出了 残差网络(Residual Network,ResNet),并在 2015 年的 ImageNet 比赛中夺得冠军。ResNet 的核心思想是 残差学习(Residual Learning),通过引入 快捷连接(skip connection) 来缓解梯度消失和退化问题,从而让深层网络训练成为可能。


二、核心思想:残差学习

传统的深层神经网络可以表示为:

其中,H(x)H(x) 是期望学习的映射,F(x)F(x) 是堆叠层实现的函数

ResNet 的创新点是:与其直接学习 H(x)H(x),不如让网络去学习 残差函数

也就是说,网络学习的不是直接的输出,而是输入和输出的差异(残差)。

这种设计有两个好处:

  1. 如果最优映射接近恒等函数,学习残差更容易。

  2. 快捷连接保证了信息和梯度可以直接跨层传播,避免梯度消失。


三、ResNet 的基本结构

1. 残差模块(Residual Block)

残差模块是 ResNet 的核心。其基本结构为:

  • 两层卷积(Conv-BN-ReLU),负责提取特征。

  • 一条 shortcut connection,将输入直接加到输出上。

公式:

结构图示:

输入 x│
[卷积-BN-ReLU]│
[卷积-BN]│+──────→ 输出 y│输入 x

2. 瓶颈结构(Bottleneck Block)

在更深层的 ResNet(如 ResNet-50/101/152)中,引入了 瓶颈结构 来减少计算量:

  • 先用 1×1 卷积降维。

  • 再用 3×3 卷积进行特征提取。

  • 最后用 1×1 卷积升维。

这样既能减少参数量,又能保持特征表达能力。


四、经典 ResNet 网络结构

常见的 ResNet 网络深度有 18、34、50、101、152 层。其区别主要在于残差模块的堆叠数量和是否使用瓶颈结构。

ResNet-18 为例,整体结构:

  • Conv1:7×7 卷积 + 最大池化

  • Conv2_x:2 个残差模块

  • Conv3_x:2 个残差模块

  • Conv4_x:2 个残差模块

  • Conv5_x:2 个残差模块

  • 全局平均池化 + 全连接层

ResNet-50、101、152 则采用瓶颈残差模块,并堆叠更多层数。


五、PyTorch 实现示例

下面给出一个简化版的 ResNet 实现代码(以 ResNet-18 为例):

import torch
import torch.nn as nn
import torch.nn.functional as F# 基本残差模块
class BasicBlock(nn.Module):expansion = 1def __init__(self, in_channels, out_channels, stride=1, downsample=None):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.downsample = downsample  # 用于通道数不一致时的调整def forward(self, x):identity = xif self.downsample is not None:identity = self.downsample(x)out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out += identityout = self.relu(out)return out# ResNet 主体
class ResNet(nn.Module):def __init__(self, block, layers, num_classes=1000):super(ResNet, self).__init__()self.in_channels = 64self.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, layers[0])self.layer2 = self._make_layer(block, 128, layers[1], stride=2)self.layer3 = self._make_layer(block, 256, layers[2], stride=2)self.layer4 = self._make_layer(block, 512, layers[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, blocks, stride=1):downsample = Noneif stride != 1 or self.in_channels != out_channels * block.expansion:downsample = nn.Sequential(nn.Conv2d(self.in_channels, out_channels * block.expansion,kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(out_channels * block.expansion),)layers = []layers.append(block(self.in_channels, out_channels, stride, downsample))self.in_channels = out_channels * block.expansionfor _ in range(1, blocks):layers.append(block(self.in_channels, out_channels))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avgpool(x)x = torch.flatten(x, 1)x = self.fc(x)return xdef ResNet18(num_classes=1000):return ResNet(BasicBlock, [2, 2, 2, 2], num_classes)# 测试
if __name__ == "__main__":model = ResNet18(num_classes=10)print(model)x = torch.randn(1, 3, 224, 224)y = model(x)print(y.shape)

六、ResNet 的应用

ResNet 已成为计算机视觉任务中的经典网络结构,被广泛应用于:

  • 图像分类(ImageNet、CIFAR-10)

  • 目标检测(Faster R-CNN, YOLO 的 backbone)

  • 图像分割(Mask R-CNN, U-Net 的变体)

  • 医学影像分析(CT/MRI 分类、分割)

  • 语音和自然语言处理(Transformer 前的深层特征提取)


七、总结

  • ResNet 的核心思想:通过残差学习和快捷连接解决深层网络的退化问题。

  • 残差模块:基础块(BasicBlock)和瓶颈块(Bottleneck)。

  • 效果:ResNet 让网络层数从几十层突破到上百层,极大推动了深度学习的发展。

  • 应用:几乎所有计算机视觉主流模型都与 ResNet 有关。

http://www.xdnf.cn/news/20146.html

相关文章:

  • Python快速入门专业版(二):print 函数深度解析:不止于打印字符串(含10+实用案例)
  • Docker多阶段构建Maven项目
  • K8s资源管理:高效管控CPU与内存
  • React学习之路永无止境:下一步,去向何方?
  • Jmeter基础教程详解
  • STM32H750 RTC介绍及应用
  • 国产GEO工具哪家强?巨推集团、SEO研究协会网、业界科技三强对比
  • 用C++实现日期类
  • upload-labs通关笔记-第17关文件上传关卡之二次渲染jpg格式
  • 关于如何在PostgreSQL中调整数据库参数和配置的综合指南
  • Vue基础知识-脚手架开发-子传父(props回调函数实现和自定义事件实现)
  • Win11 解决访问网站525 问题 .
  • 【RK3576】【Android14】如何在Android kernel-6.1 的版本中添加一个ko驱动并编译出来?
  • Django 常用功能完全指南:从核心基础到高级实战
  • [光学原理与应用-401]:设计 - 深紫外皮秒脉冲激光器 - 元件 - 布拉格衍射在深紫外皮秒声光调制器(AOM)中的核心作用与系统实现
  • 小程序:12亿用户的入口,企业数字化的先锋军
  • Linux编程——网络编程(UDP)
  • 计算机网络模型入门指南:分层原理与各层作用
  • 对接旅游行业安全需求:旅游安全急救实训室的功能构建与育人目标
  • 网络安全初级-渗透测试
  • 用AI做TikTok影视解说,全流程全自动成片,不懂外语也能做全球矩阵!
  • 办公任务分发项目 laravel vue mysql 第一章:核心功能构建 API
  • 系统越拆越乱?你可能误解了微服务的本质!
  • 【Linux系统】线程同步
  • 正则表达式与转义符的区别。注意输入的东西经过了一次转义,一次正则表达式。\\转义是单斜杠\\在正则表达式也是单斜杠所以\\\\经过两道门才是字符单斜杠
  • MongoDB Change Streams:实时监听数据变化的实战场景
  • clickhouse迁移工具clickhouse-copier
  • Python EXCEL 小技巧:最快重新排列dataframe函数
  • 工业机器人标杆的数字化突围,珞石机器人如何以CRM实现业务重塑
  • 技术视界 | 跨域机器人通信与智能系统:打破壁垒的开源探索