【使用Pytorch实现ResNet网络模型:ResNet50、ResNet101和ResNet152】

article/2025/10/6 15:45:03

使用Pytorch实现Resnet网络模型:ResNet50、ResNet101和ResNet152

  • 介绍
  • 什么是 ResNet?
  • ResNet 的架构
  • 使用Pytorch构建 ResNet网络

介绍

在深度学习和计算机视觉领域取得了一系列突破。尤其是随着非常深的卷积神经网络的引入,这些模型有助于在图像识别和图像分类等问题上取得最先进的结果。

因此,多年来,深度学习架构变得越来越深(添加更多层)以解决越来越复杂的任务,这也有助于提高分类和识别任务的性能并使其变得健壮。

但是当我们继续向神经网络添加更多层时,训练变得非常困难,并且模型的准确性开始饱和,然后也会下降。ResNet 将我们从这种情况中解救出来,并帮助解决了这个问题。

什么是 ResNet?

Residual Network (ResNet) 是著名的深度学习模型之一,由 Shaoqing Ren、Kaiming He、Jian Sun 和 Xiangyu Zhang 在他们的论文中提出。该论文在 2015 年被命名为“Deep Residual Learning for Image Recognition” 。ResNet 模型是迄今为止流行和最成功的深度学习模型之一。

残块:
随着这些 Residual 块的引入,训练非常深的网络的问题得到了缓解,ResNet 模型由这些块组成。

在这里插入图片描述

在上图中,我们首先注意到的是有一个直接连接跳过了模型的某些层,这种连接称为“跳过连接”,是残差块的核心。由于此跳过连接,输出不一样。如果没有跳过连接,输入 X 将乘以层的权重,然后添加一个偏置项。然后是激活函数 f(),我们得到输出为 H(x)。

H(x)=f( wx + b ) 或 H(x)=f(x)

现在引入了一种新的跳跃连接技术,输出为 H(x) 变为

H(x)=f(x)+x

但是输入的维度可能与卷积层或池化层输出的维度不同。因此,可以通过以下两种方法处理此问题:

·用跳跃连接填充零以增加其尺寸。·1×1 卷积层被添加到输入以匹配维度。在这种情况下,输出为:H(x)=f(x)+w1.x

这里添加了一个额外的参数 w1 而使用第一种方法时没有添加额外的参数。

ResNet 中的这些跳跃连接技术通过允许梯度流过的替代捷径来解决深度 CNN 中梯度消失的问题,此外,如果任何层损害了架构的性能,则跳过连接会有所帮助,那么它将被正则化跳过。

ResNet 的架构

该架构中有一个 34 层的普通网络,其灵感来自 VGG-19,其中添加了快捷连接或跳过连接,这些跳过连接或残差块将架构转换为残差网络,如下图所示。

在这里插入图片描述

使用Pytorch构建 ResNet网络

在这里插入图片描述
让我们保留上面的图像作为参考并开始构建网络,ResNet 架构多次使用 CNN 块,所以让我们为 CNN 块创建一个类,它接受输入通道和输出通道。每个 conv 层之后都有一个 batchnorm2d,然后创建一个 ResNet 类,该类接受多个块、层、图像通道和类数的输入。函数“_make_layer”创建了 ResNet 层,它接受块的输入、残差块的数量、输出通道和步幅。然后定义不同版本的ResNet

–对于 ResNet50,层序列为 [3, 4, 6, 3]。

–对于 ResNet101,层序列为 [3, 4, 23, 3]。

–对于 ResNet152,层序列为 [3, 8, 36, 3]。

然后编写一个test()函数来检查模型是否工作正常,完整实例代码如下:

import torch
import torch.nn as nnclass block(nn.Module):def __init__(self, in_channels, intermediate_channels, identity_downsample=None, stride=1):super(block, self).__init__()self.expansion = 4self.conv1 = nn.Conv2d(in_channels, intermediate_channels, kernel_size=1, stride=1, padding=0, bias=False)self.bn1 = nn.BatchNorm2d(intermediate_channels)self.conv2 = nn.Conv2d(intermediate_channels,intermediate_channels,kernel_size=3,stride=stride,padding=1,bias=False)self.bn2 = nn.BatchNorm2d(intermediate_channels)self.conv3 = nn.Conv2d(intermediate_channels,intermediate_channels * self.expansion,kernel_size=1,stride=1,padding=0,bias=False)self.bn3 = nn.BatchNorm2d(intermediate_channels * self.expansion)self.relu = nn.ReLU()self.identity_downsample = identity_downsampleself.stride = stridedef forward(self, x):identity = x.clone()x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.conv2(x)x = self.bn2(x)x = self.relu(x)x = self.conv3(x)x = self.bn3(x)if self.identity_downsample is not None:identity = self.identity_downsample(identity)x += identityx = self.relu(x)return xclass ResNet(nn.Module):def __init__(self, block, layers, image_channels, num_classes):super(ResNet, self).__init__()self.in_channels = 64self.conv1 = nn.Conv2d(image_channels, 64, kernel_size=7, stride=2, padding=3, bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU()self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(block, layers[0], intermediate_channels=64, stride=1)self.layer2 = self._make_layer(block, layers[1], intermediate_channels=128, stride=2)self.layer3 = self._make_layer(block, layers[2], intermediate_channels=256, stride=2)self.layer4 = self._make_layer(block, layers[3], intermediate_channels=512, stride=2)self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(512 * 4, num_classes)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 = x.reshape(x.shape[0], -1)x = self.fc(x)return xdef _make_layer(self, block, num_residual_blocks, intermediate_channels, stride):identity_downsample = Nonelayers = []if stride != 1 or self.in_channels != intermediate_channels * 4:identity_downsample = nn.Sequential(nn.Conv2d(self.in_channels,intermediate_channels * 4,kernel_size=1,stride=stride,bias=False),nn.BatchNorm2d(intermediate_channels * 4),)layers.append(block(self.in_channels, intermediate_channels, identity_downsample, stride))self.in_channels = intermediate_channels * 4for i in range(num_residual_blocks - 1):layers.append(block(self.in_channels, intermediate_channels))return nn.Sequential(*layers)def ResNet50(img_channel=3, num_classes=1000):return ResNet(block, [3, 4, 6, 3], img_channel, num_classes)def ResNet101(img_channel=3, num_classes=1000):return ResNet(block, [3, 4, 23, 3], img_channel, num_classes)def ResNet152(img_channel=3, num_classes=1000):return ResNet(block, [3, 8, 36, 3], img_channel, num_classes)def test():net = ResNet101(img_channel=3, num_classes=1000)print(net)device = "cuda" if torch.cuda.is_available() else "cpu"y = net(torch.randn(4, 3, 224, 224)).to(device)print(y.size())test()

对于上述测试用例,输出应为:

在这里插入图片描述


http://chatgpt.dhexx.cn/article/aq4OfRMU.shtml

相关文章

使用PyTorch搭建ResNet101、ResNet152网络

ResNet18的搭建请移步:使用PyTorch搭建ResNet18网络并使用CIFAR10数据集训练测试 ResNet34的搭建请移步:使用PyTorch搭建ResNet34网络 ResNet34的搭建请移步:使用PyTorch搭建ResNet50网络 参照我的ResNet50的搭建,由于50层以上几…

Java中的数组

数组 1.什么是数组 数组就是存储相同数据类型的一组数据,且长度固定 基本数据类型4类8种:byte/char/short/int/long/float/double/boolean 数组,是由同一种数据类型按照一定的顺序排序的集合,给这个数组起一个名字。是一种数据类型&#…

java输出数组(java输出数组)

多维数组在Java里如何创建多维数组? 这从第四个例子可以看出,它向我们演示了用花括号收集多个new表达式的能力: Integer[][] a4 { { new Integer (1), new Integer (2)}, { new Integer (3), new Integer (4)}, { new Integer (5), new…

java怎么输出数组(Java怎么给数组赋值)

Java中数组输出的三种方式。第一种方式,传统的for循环方式,第二种方式,for each循环,  第三种方式,利用Array类中的toString方法. 定义一个int类型数组,用于输出 int[] array={1,2,3,4,5}; 第一种方式,传统的for循环方式 for(int i=0;i {System.out.println(a[i]); } 第…

数组的输入与输出

前言: 我们知道对一个字符数组进行输入与输出时会用到: 输入:scanf,getchar,gets 输出:printf,putchar,puts 然而可能还有很多的朋友对这些还不是很了解,今天让我们共同学习数组的输入与输出吧。 %c格式是用于输入…

Java二维数组的输出

1. Java二维数组的输出<1> (1) 输出结果右对齐"%5d" public class HelloWorld {public static void main(String[] args){int myArray[ ][ ] { {1,2}, {7,2}, {3,4} };for(int i0; i<3; i){for (int j0; j<2; j)System.out.printf("%5d",my…

Java中数组的输入输出

数组的输入 首先声明一个int型数组 int[] a 或者 int a[] 给数组分配空间 anew int[10]; 和声明连起来就是int[] anew int[10]; 或者是 int a[]new int[10]; 给数组赋值 a[0]1;//0代表的是数组的第1个元素 ,元素下标为0 a[1]1;//1代表的是数组的第2个元素 ,元素下标为0 …

Java 数组的输入输出

Java中要对控制台进行输入操作的话要调用Scanner类&#xff0c;定义一个扫描的对象&#xff0c;例&#xff1a; //要导入java.util.Scanner; Scanner scanner new Scanner(System.in); 这样便打开了输入流&#xff0c;接下来定义数组&#xff1a; int[] n new int[4];//使…

Java中字符串数组的输入与输出

今天刷题遇到一个坑&#xff0c;老是接收不到字符串数组。即用str[i]sc.nextLine();这样的方式去接收数组的话&#xff0c;打印的时候总是会少一个。 import java.util.Scanner;public class test {public static void main(String[] args) {Scanner sc new Scanner(System.i…

java中打印输出数组内容的三种方式

今天输出数组遇到问题&#xff0c;学习一下打印输出数组内容的几种方式 错误示范&#xff1a;System.out.println(array);  //这样输出的是数组的首地址&#xff0c;而不能打印出数组数据。&#xff08;唉&#xff0c;我开始就是这么写的。。。&#xff09; 一维数组&#…

NTP协议之旅

NTP协议之旅 What---啥是NTPWhy---为什么需要NTPHow---NTP实现原理Do---NTP实战使用HCL 华三模拟器进行NTP配置抓包分析 What—啥是NTP NTP是在分布式网络中&#xff0c;进行时钟同步的协议&#xff0c;其具有较高的时间同步精度。所使用的传输层协议为UDP&#xff0c;使用端口…

ntrip协议

https://blog.csdn.net/wandersky0822/article/details/88558456这篇介绍的是RTK精确定位的原理&#xff0c;及影响精确定位的各种条件。 这一篇介绍的就比较细&#xff0c;仅仅介绍RTK 差分信息的 产生 申请与分发。 最近要做一个GPS RTK基站&#xff0c;也就是为RTK客户端提…

Ntrip协议简介

Ntrip通讯协议1.0 1 什么是Ntrip&#xff1f; CORS&#xff08;Continuously Operating Reference Stations&#xff09;就是网络基准站&#xff0c;通过网络收发GPS差分数据。用户访问CORS后&#xff0c;不用单独架设GPS基准站&#xff0c;即可实现GPS流动站的差分定位。 访问…

NTP技术介绍

NTP 简介 NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;是由RFC 1305定义的时间同步协议&#xff0c;用来在分布式时间服务器和客户端之间进行时间同步。NTP基于UDP报文进行传输&#xff0c;使用的UDP端口号为123。 使用NTP的目的是对网络内所…

NTPv4协议解析

前言 本文的撰写基于RFC5905.NTP 是时间网络控制协议&#xff0c;V4版本相交V3版本&#xff0c;修复了V3存在的一些问题。尤其是NTPV4的拓展时间戳鼓励使用浮动双数据类型&#xff0c;这样使得NTP能够更好的支持1ns的场景&#xff0c;轮询间隔也从上一代的最多1024s拓展到了36…

NTP 网络时间协议

目录 基本原理 结构 工作模式 单播C/S模式 对等体模式 广播模式 组播模式 多播模式 NTP访问控制 访问权限 KOD 认证功能 配置 NTP用于在一系列分布式时间服务器与客户端之间同步时钟。基于IP和UDP。NTP报文通过UDP传输&#xff0c;端口号是123. NTP主要应用于网络中…

NTP协议简介

NTP协议简介 一. datec dates分析1. 同步流程2. 缺陷 二. NTP(**Network Time Protocol**)1. NTP概述 [1、2、3、7]2. NTP的时钟同步原理与授时精度分析 [3、1、10]NTP的时钟同步原理NTP的授时精度分析 3. NTP中其它的提高授时精度的措施[1、6]参考资料 三. 对NTP改进以获得更高…

ntp同步详解

一、ntp服务是什么 1.定义 NTP是网络时间协议(Network Time Protocol)&#xff0c;它是用来同步网络中各个计算机的时间的协议。 2.发展 首次记载在Internet Engineering Note之中&#xff0c;其精确度为数百毫秒。 稍后出现了首个时间协议的规范RFC-778&#xff0c;它被命…

NTP协议代码实现

本文将讲解NTP的代码实现和调试过程的一些记录。 首先&#xff0c;进行NTP报文结构体的构建。 //宏定义 #define NTP_TIMESTAMP_DELTA 2208988800ull //number of seconds between 1900 and 1970&#xff0c;1900-1970的时间差 #define SEC_TIME_ZONE (8*60*60) //B…

什么是Ntrip?Ntrip协议简介

文章目录 Ntrip通讯协议1.0Ntrip是什么&#xff1f;Ntrip系统组成NtripServerNtripClient4.1 获取源列表4.2 获取差分数据 其他资料 Ntrip通讯协议1.0 Ntrip是什么&#xff1f; NTRIP是在互联网上进行RTK数据传输的协议。所有的 RTK数据格式&#xff08;NCT&#xff0c;RTCM&…