【深度学习】resnet-50网络结构

article/2025/9/18 5:33:17

最近许多目标检测网络的backbone都有用到resnet-50的部分结构,于是找到原论文,看了一下网络结构,在这里做一个备份,需要的时候再来看看。

整体结构

在这里插入图片描述

layer0

首先是layer0,这部分在各个网络都一样,如图,由一个7x7,步距为2的卷积+BN+relu,加上3x3最大值池化,步长为2的池化层构成。在这里插入图片描述

layer1

以18和50举例
18的basicblock如下,layer1共有2个下图的basicblock
resnet-18的block称为basicblock
resnet-50称为bottleneck
identity和卷积之后的输出对应数值相加!
在这里插入图片描述

resnet-50的bottleneck如下,layer1共有3个bottleneck,
第2个和第3个block的输入channel为256
在这里插入图片描述

layer2及layer3,4,5

layer2以及之后的3,4,5与layer1的结构大致上相同,只不过每个layer的第一个block,resnet-18的第一个conv层的stride=2,resnet-50的3x3conv层stride=2。其他的block都与layer1一致。

例如resnet-50的layer2第一个bottleneck:

identity的卷积核大小应为3x3,为了保证residual前后的shape一致,能够相加,进行了下采样
在这里插入图片描述

第2,3,4个bottleneck为
在这里插入图片描述

将block和整体结构对应,理解resnet50结构并不难,

34与18类似,101,152与50类似,只是block数量不一样。

代码实现

import torch.nn as nn# bottleneck多次用到,所以封装成类调用 这是layer2及之后的Bottleneck
class Bottleneck(nn.Module):def __init__(self, inchannels, outchannels, stride=1, identity=None):""":param inchannels: 输入维度:param outchannels: 输出维度:param stride: 第二个卷积层的步长:param identity: 输入到输出的处理,维度相同直接相加,维度不同要1x1卷积"""super(Bottleneck, self).__init__()# 第一个卷积和第二个卷积的channelself.mid_channels = outchannels // 4;# 定义三个卷积层self.conv1 = nn.Conv2d(inchannels, self.mid_channels, kernel_size=1, stride=1)self.bn1 = nn.BatchNorm2d(self.mid_channels)self.conv2 = nn.Conv2d(self.mid_channels, self.mid_channels, kernel_size=3, stride=stride, padding=1)self.bn2 = nn.BatchNorm2d(self.mid_channels)self.conv3 = nn.Conv2d(self.mid_channels, outchannels, kernel_size=1, stride=1)self.bn3 = nn.BatchNorm2d(outchannels)# inplace=True 新的值直接代替旧的值 节省内存self.relu = nn.ReLU(inplace=True)self.stride = strideif identity is not None:self.identity = identityelse:# 卷积然后BN,RELU,stride和3x3卷积的一致,保持shape一致self.identity = nn.Sequential(nn.Conv2d(inchannels,outchannels,kernel_size=1,stride=stride,bias=False),nn.BatchNorm2d(outchannels),nn.ReLU(inplace=True))def forward(self,x):# 走identity线resduial=xout = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out = self.relu(out)out = self.conv3(out)out = self.bn3(out)out = self.relu(out)if self.identity is not None:resduial = self.identity(resduial)out += resduialout = self.bn3(out)out = self.relu(out)return outclass resnet_50(nn.Module):def __init__(self,image_shape):super(resnet_50, self).__init__()# 一般后接BN层不需要偏置self.layer_0_conv1 = nn.Conv2d(3,64,kernel_size=7,stride=2,padding=3,bias=False)self.layer_0_bn1 = nn.BatchNorm2d(64)self.layer_0_pool = nn.MaxPool2d(kernel_size=3,stride=2,padding=1)self.layer_1 = self.makelayer(3,64,256,1)self.layer_2 = self.makelayer(4,256,512,2)self.layer_3 = self.makelayer(6,512,1024,2)self.layer_4 = self.makelayer(3,1024,2048,2)self.a_pool = nn.AvgPool2d(3,stride=1,padding=1)self.fc = nn.Linear(7*7*2048,1000)def forward(self,x):out = self.layer_0_conv1(x)out = self.layer_0_bn1(out)out = self.layer_0_pool(out)out = self.layer_1(out)out = self.layer_2(out)out = self.layer_3(out)out = self.layer_4(out)out = self.a_pool(out)out = out.view(-1,7*7*2048)out = self.fc(out)return out# 生成layerdef makelayer(self,number,inchannels, last_channels, stride=1):""":param number: 由几个bottleneck构成:param last_channels: bottleneck的最后一个卷积层输出的channel:param stride: bottleneck 3x3卷积的步长:param is_layer1: 是否为第一层:return:"""layer = []# 构建生成每一层layer的方法# 每个layer的第一层的stride为2 单独构造bottle = Bottleneck(inchannels,last_channels,stride=stride)layer.append(bottle)for i in range(number-1):bottle = Bottleneck(last_channels,last_channels,stride=1,)layer.append(bottle)# *list 提取list中的每一个元素return nn.Sequential(*layer)

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

相关文章

一张图看懂Resnet50与Resnet101算法

直接上流程图,算法很清晰。 仅包括卷积层和全连接层,不包括池化层,正好50层。 相比于ResNet_50,ResNet_101就是在上图第3个大虚线框多了17个bottleneck,17*350101,说白了就是将下图复制17个加入上图的第3个…

什么是Resnet50模型?

1 深度残差网络 随着CNN的不断发展,为了获取深层次的特征,卷积的层数也越来越多。一开始的 LeNet 网络只有 5 层,接着 AlexNet 为 8 层,后来 VggNet 网络包含了 19 层,GoogleNet 已经有了 22 层。但仅仅通过增加网络层…

resnet-50介绍(一)

这篇文章讲解的是使用Tensorflow实现残差网络resnet-50. 侧重点不在于理论部分,而是在于代码实现部分。在github上面已经有其他的开源实现,如果希望直接使用代码运行自己的数据,不建议使用本人的代码。但是如果希望学习resnet的代码实现思路&…

ResNet50 网络结构搭建(PyTorch)

ResNet50是一个经典的特征提取网络结构,虽然Pytorch已有官方实现,但为了加深对网络结构的理解,还是自己动手敲敲代码搭建一下。需要特别说明的是,笔者是以熟悉网络各层输出维度变化为目的的,只对建立后的网络赋予伪输入…

ResNet-50网络理解

本文主要针对ResNet-50对深度残差网络进行一个理解和分析 ResNet已经被广泛运用于各种特征提取应用中,当深度学习网络层数越深时,理论上表达能力会更强,但是CNN网络达到一定的深度后,再加深,分类性能不会提高&#xff…

庖丁解牛-Resnet50 深度剖析,细致讲解,深入理解

背景介绍 ResNet-50侧边输出形状 假设输入为352,则 output2 256x88x88 output3 512x44x44 output4 1024x22x22 output5 2048x11x11 VGG-16侧边输出形状 假设输入为352,则 output1 64x320x320 output2 128x160x160 output3 256x88x88 output4 512x44x44 output5 512x22…

Resnet-50网络结构详解

解决的问题: 梯度消失,深层网络难训练。 因为梯度反向传播到前面的层,重复相乘可能使梯度无穷小。结果就是,随着网络的层数更深,其性能趋于饱和,甚至迅速下降。 关于为什么残差结构(即多了一…

卷积神经网络学习—Resnet50(论文精读+pytorch代码复现)

前言一、Resnet论文精读引入残差残差块ResNet50模型基本构成BN层Resnet50总体结构 二、Resnet50代码复现完整代码 前言 如果说在CNN领域一定要学习一个卷积神经网络,那一定非Resnet莫属了。 接下来我将按照:Resnet论文解读、Pytorch实现ResNet50模型两部…

Java类加载器介绍

1.类加载器介绍 类加载器负责将class文件加载到内存中,并为之生成对应的java.lang.Class对象。对于任意一个类,都需要加载它的类加载器和这个类本身来确定该类在JVM中唯一性,也就是说,同一个class文件用两个不同的类加载器加载并…

类加载与类加载器概述

目录 一、类加载 类的加载: 类的连接: 类的初始化: 类初始化步骤: 类的初始化时机: 二、类加载器 类加载器的作用 JVM的类加载机制 Java运行时具有以下内置类加载器: 一、类加载 当程序要使用某…

十一、类加载器的作用

狂神说Java:https://www.bilibili.com/video/BV1p4411P7V3 1、类加载的作用 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据…

2.类加载器

回顾 上一节我们学习了JVM类加载机制,我们学习到大概的过程:通过类加载器将编译好的class文件加载到JVM进程中,通过字节码执行引擎去执行代码。这只是一个整体的过程,具体的细节我们从本节开始分析。 通过本节我们将掌握以下知识&…

Java类加载器

一.类的生命周期 1. 加载(Loading):找 Class 文件 1. 通过一个类的全限定名来获取定义此类的二进制字节流。 2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。 3.在内存中生成一个代表这个类的java.lang.Class对象&#xf…

Java类加载器的使用

Java类加载器 classloader顾名思义,即是类加载。虚拟机把描述类的数据从class字节码文件加载到内存,并对数据进行检验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。 先认识一下类加载…

JVM 类加载器

什么是类加载器 类加载器负责在运行时将Java类动态加载到Java虚拟机,他们也是JRE(Java运行时环境)的一部分。因此,借助类加载器,JVM无需了解底层文件或文件系统即可运行Java程序。此外,这些Java类不会一次…

类加载器深入理解

虚拟机设计团队把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的模块称为“类加载器”。 类加载器在类层次划分、OSGI、热部署、代码加密等领域…

java获取类加载器

获取类加载器的方法: //扩展类加载器MainClassLoader classLoader MainTest.class.getClassLoader();//表示当前线程的类加载器——应用程序类加载器ClassLoader contextClassLoader Thread.currentThread().getContextClassLoader();//—启动类加载器ClassLoader systemClas…

类加载器的种类

类加载器的种类有四种,如下图所示: 1.启动类加载器(引导类加载器,Bootstrap ClassLoader) 这个类加载使用C/C语言实现的,嵌套在JVM内部它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar、res…

Java类加载器详解

1 特点 双亲委派: 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载…

【类加载器】java类加载器

类装载器ClassLoader(一个抽象类) 描述一下JVM加载class文件的原理机制 类装载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件,在java中类装载器把一个类装入JVM,经过以下步骤: 1、装载&#xff…