Pytorch实现ResNet50网络结构,包含ResNet18,ResNet34,ResNet50,ResNet101,ResNet152

article/2025/10/6 13:50:14

创建各版本的ResNet模型,ResNet18,ResNet34,ResNet50,ResNet101,ResNet152

原文地址: https://arxiv.org/pdf/1512.03385.pdf


论文就不解读了,大部分解读都是翻译,看的似懂非懂,自己搞懂就行了。

最近想着实现一下经典的网络结构,看了原文之后,根据原文代码结构开始实现。

起初去搜了下各种版本的实现,发现很多博客都是错误百出,有些博文都发布几年了,错误还是没人发现,评论区几十号人不知道是真懂还是装懂,颇有些无奈啊。

因此打算自己手动实现网络结构,锻炼下自己的代码能力,也加深对网络结构的理解。

写完之后也很欣慰,毕竟一直认为自己是个菜鸡,最近竟然接连不断的发现很多博文的错误之处,而且很多人看后都没发现的,想想自己似乎还有点小水平。

最后在一套代码里,实现了各版本ResNet,为了方便。

其实最后还是觉得应该每个网络分开写比较好。因为不同版本的网络内部操作是有很大差异的,本文下面的代码是将ResidualBlock和 BottleNeckBlock分开写的,但是在维度的变换上差异还是很复杂,一方面想提高代码的复用性,另一方面也受制于复杂度。所以最后写出的算不上高复用性的精简代码。勉强能用。关于ResNet的结构,除各版本分开写之外,重复的block其实也可以分开写,因为BottleNeckBlock的维度变换太复杂,参数变换多,能分开就分开,复杂度小的地方可以复用。


以下是网络结构和实现代码,检验后都是对的;水平有限,如发现有错误,欢迎评论告知!

1 残差结构图

2 VGG-19与ResNet34结构比较

在这里插入图片描述

3 ResNet各版本的结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qLEx5XJg-1602504703995)(C:\Users\tony\AppData\Roaming\Typora\typora-user-images\image-20201012200856046.png)]

4 代码实现各版本

import torch.nn as nn
from torch.nn import functional as Fclass ResNetModel(nn.Module):"""实现通用的ResNet模块,可根据需要定义"""def __init__(self, num_classes=1000, layer_num=[],bottleneck = False):super(ResNetModel, self).__init__()#conv1self.pre = nn.Sequential(#in 224*224*3nn.Conv2d(3,64,7,2,3,bias=False),   #输入通道3,输出通道64,卷积核7*7*64,步长2,根据以上计算出padding=3#out 112*112*64nn.BatchNorm2d(64),     #输入通道C = 64nn.ReLU(inplace=True),   #inplace=True, 进行覆盖操作# out 112*112*64nn.MaxPool2d(3,2,1),    #池化核3*3,步长2,计算得出padding=1;# out 56*56*64)if bottleneck:  #resnet50以上使用BottleNeckBlockself.residualBlocks1 = self.add_layers(64, 256, layer_num[0], 64, bottleneck=bottleneck)self.residualBlocks2 = self.add_layers(128, 512, layer_num[1], 256, 2,bottleneck)self.residualBlocks3 = self.add_layers(256, 1024, layer_num[2], 512, 2,bottleneck)self.residualBlocks4 = self.add_layers(512, 2048, layer_num[3], 1024, 2,bottleneck)self.fc = nn.Linear(2048, num_classes)else:   #resnet34使用普通ResidualBlockself.residualBlocks1 = self.add_layers(64,64,layer_num[0])self.residualBlocks2 = self.add_layers(64,128,layer_num[1])self.residualBlocks3 = self.add_layers(128,256,layer_num[2])self.residualBlocks4 = self.add_layers(256,512,layer_num[3])self.fc = nn.Linear(512, num_classes)def add_layers(self, inchannel, outchannel, nums, pre_channel=64, stride=1, bottleneck=False):layers = []if bottleneck is False:#添加大模块首层, 首层需要判断inchannel == outchannel ?#跨维度需要stride=2,shortcut也需要1*1卷积扩维layers.append(ResidualBlock(inchannel,outchannel))#添加剩余nums-1层for i in range(1,nums):layers.append(ResidualBlock(outchannel,outchannel))return nn.Sequential(*layers)else:   #resnet50使用bottleneck#传递每个block的shortcut,shortcut可以根据是否传递pre_channel进行推断#添加首层,首层需要传递上一批blocks的channellayers.append(BottleNeckBlock(inchannel,outchannel,pre_channel,stride))for i in range(1,nums): #添加n-1个剩余blocks,正常通道转换,不传递pre_channellayers.append(BottleNeckBlock(inchannel,outchannel))return nn.Sequential(*layers)def forward(self, x):x = self.pre(x)x = self.residualBlocks1(x)x = self.residualBlocks2(x)x = self.residualBlocks3(x)x = self.residualBlocks4(x)x = F.avg_pool2d(x, 7)x = x.view(x.size(0), -1)return self.fc(x)class ResidualBlock(nn.Module):'''定义普通残差模块resnet34为普通残差块,resnet50为瓶颈结构'''def __init__(self, inchannel, outchannel, stride=1, padding=1, shortcut=None):super(ResidualBlock, self).__init__()#resblock的首层,首层如果跨维度,卷积stride=2,shortcut需要1*1卷积扩维if inchannel != outchannel:stride= 2shortcut=nn.Sequential(nn.Conv2d(inchannel,outchannel,1,stride,bias=False),nn.BatchNorm2d(outchannel))# 定义残差块的左部分self.left = nn.Sequential(nn.Conv2d(inchannel, outchannel, 3, stride, padding, bias=False),nn.BatchNorm2d(outchannel),nn.ReLU(inplace=True),nn.Conv2d(outchannel, outchannel, 3, 1, padding, bias=False),nn.BatchNorm2d(outchannel),)#定义右部分self.right = shortcutdef forward(self, x):out = self.left(x)residual = x if self.right is None else self.right(x)out = out + residualreturn F.relu(out)class BottleNeckBlock(nn.Module):'''定义resnet50的瓶颈结构'''def __init__(self,inchannel,outchannel, pre_channel=None, stride=1,shortcut=None):super(BottleNeckBlock, self).__init__()#首个bottleneck需要承接上一批blocks的输出channelif pre_channel is None:     #为空则表示不是首个bottleneck,pre_channel = outchannel    #正常通道转换else:   # 传递了pre_channel,表示为首个block,需要shortcutshortcut = nn.Sequential(nn.Conv2d(pre_channel,outchannel,1,stride,0,bias=False),nn.BatchNorm2d(outchannel))self.left = nn.Sequential(#1*1,inchannelnn.Conv2d(pre_channel, inchannel, 1, stride, 0, bias=False),nn.BatchNorm2d(inchannel),nn.ReLU(inplace=True),#3*3,inchannelnn.Conv2d(inchannel,inchannel,3,1,1,bias=False),nn.BatchNorm2d(inchannel),nn.ReLU(inplace=True),#1*1,outchannelnn.Conv2d(inchannel,outchannel,1,1,0,bias=False),nn.BatchNorm2d(outchannel),nn.ReLU(inplace=True),)self.right = shortcutdef forward(self,x):out = self.left(x)residual = x if self.right is None else self.right(x)return F.relu(out+residual)if __name__ == '__main__':# channel_nums = [64,128,256,512,1024,2048]num_classes = 6#layers = 18, 34, 50, 101, 152layer_nums = [[2,2,2,2],[3,4,6,3],[3,4,6,3],[3,4,23,3],[3,8,36,3]]#选择resnet版本,# resnet18 ——0;resnet34——1,resnet-50——2,resnet-101——3,resnet-152——4i = 3;bottleneck = i >= 2   #i<2, false,使用普通的ResidualBlock; i>=2,true,使用BottleNeckBlockmodel = ResNetModel(num_classes,layer_nums[i],bottleneck)print(model)

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

相关文章

mindspore-ResNet101使用GPU进行训练时报错

multiprocessing.context.TimeoutError RuntimeError: mindspore/ccsrc/backend/session/kernel_build_client.h:109 Response] Response is empty 1、修改resnet101_imagenet2012_config.yaml中的训练集路径&#xff0c;更改类数量以适应新数据集 2、在models/official/cv/r…

官方代码 Deeplab v3+ resnet101 做backbone

大年初一我居然在更博客。今年过年由于病毒横行&#xff0c;没有串门没有聚餐&#xff0c;整个人闲的没事干。。。医生真是不容易&#xff0c;忙得团团转还有生命危险&#xff0c;新希望他们平安。 本篇不属于初级教程。如果完全看不懂请自行谷歌或搜索作者博客。 deeplab官方…

基于pytorch+Resnet101加GPT搭建AI玩王者荣耀

本源码模型主要用了SamLynnEvans Transformer 的源码的解码部分。以及pytorch自带的预训练模型"resnet101-5d3b4d8f.pth" 本资源整理自网络&#xff0c;源地址&#xff1a;https://github.com/FengQuanLi/ResnetGPT 注意运行本代码需要注意以下几点 注意&#xff01;…

resnet101网络_网络标准101

resnet101网络 让我告诉你一个故事。 一旦我为我们的设计系统构建了另一个日期选择器组件。 它由文本输入和带有日历的弹出窗口组成&#xff0c;单击可显示日历。 然后&#xff0c;可以在外部单击或选择日期来关闭弹出窗口。 外部点击逻辑的大多数实现都是通过将实际点击侦听器…

基于ResNet101实现猴痘病毒识别任务

前言 大家好,我是阿光。 本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPy…

使用ResNet101作为预训练模型训练Faster-RCNN-TensorFlow-Python3-master

使用VGG16作为预训练模型训练Faster-RCNN-TensorFlow-Python3-master的详细步骤→Windows10Faster-RCNN-TensorFlow-Python3-masterVOC2007数据集。 如果使用ResNet101作为预训练模型训练Faster-RCNN-TensorFlow-Python3-master&#xff0c;在之前使用VGG16作为预训练模型的训练…

TensorRT学习笔记--基于FCN-ResNet101推理引擎实现语义分割

目录 前言 1--Pytorch模型转换为Onnx模型 2--Onnx模型可视化及测试 2-1--可视化Onnx模型 2-2--测试Onnx模型 3--Onnx模型转换为Tensor RT推理模型 4--基于Tensor RT使用推理引擎实现语义分割 前言 基于Tensor RT的模型转换流程&#xff1a;Pytorch → Onnx → Tensor RT…

迁移学习之ResNet50和ResNet101(图像识别)

文章目录 1.实现的效果&#xff1a;2.主文件TransorResNet.py: 1.实现的效果&#xff1a; 实际的图片&#xff1a; &#xff08;1&#xff09;可以看到ResNet50预测的前三个结果中第一个结果为&#xff1a;whippet&#xff08;小灵狗&#xff09; &#xff08;2&#xff09;Re…

Mask-RCNN(2)Resnet101

1. 对应着图像中的CNN部分&#xff0c;其对输入进来的图片有尺寸要求&#xff0c;需要可以整除2的6次方。在进行特征提取后&#xff0c;利用长宽压缩了两次、三次、四次、五次的特征层来进行特征金字塔结构的构造。Mask-RCNN使用Resnet101作为主干特征提取网络 2.ResNet101有…

Pytorch-预训练网络

预训练网络 我们可以把预训练的神经网络看作一个接收输入并生成输出的程序&#xff0c;该程序的行为是由神经网络的结构以及它在训练过程中所看到的样本所决定的&#xff0c;即期望的输入-输出对&#xff0c;或者期望输出应该满足的特性。我们可以在Pytorch中加载和运行这些预…

基于ResNet-101深度学习网络的图像目标识别算法matlab仿真

目录 1.算法理论概述 1.1、ResNet-101的基本原理 1.2、基于深度学习框架的ResNet-101实现 1.3网络训练与测试 2.部分核心程序 3.算法运行软件版本 4.算法运行效果图预览 5.算法完整程序工程 1.算法理论概述 介绍ResNet-101的基本原理和数学模型&#xff0c;并解释其在图…

【深度学习】ResNet网络详解

文章目录 ResNet参考结构概况conv1与池化层残差结构Batch Normalization总结 ResNet 参考 ResNet论文&#xff1a; https://arxiv.org/abs/1512.03385 本文主要参考视频&#xff1a;https://www.bilibili.com/video/BV1T7411T7wa https://www.bilibili.com/video/BV14E411H7U…

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

使用Pytorch实现Resnet网络模型&#xff1a;ResNet50、ResNet101和ResNet152 介绍什么是 ResNet&#xff1f;ResNet 的架构使用Pytorch构建 ResNet网络 介绍 在深度学习和计算机视觉领域取得了一系列突破。尤其是随着非常深的卷积神经网络的引入&#xff0c;这些模型有助于在图…

使用PyTorch搭建ResNet101、ResNet152网络

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

Java中的数组

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

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

多维数组在Java里如何创建多维数组&#xff1f; 这从第四个例子可以看出&#xff0c;它向我们演示了用花括号收集多个new表达式的能力&#xff1a; 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]); } 第…

数组的输入与输出

前言&#xff1a; 我们知道对一个字符数组进行输入与输出时会用到&#xff1a; 输入&#xff1a;scanf,getchar,gets 输出&#xff1a;printf,putchar,puts 然而可能还有很多的朋友对这些还不是很了解&#xff0c;今天让我们共同学习数组的输入与输出吧。 %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 …