首页 > 编程语言 >ResNet50算法

ResNet50算法

时间:2024-04-16 15:58:24浏览次数:35  
标签:ResNet50 nn self stride 算法 midplane block out

ResNet (Residual net)是残差网络的通用概念,而 ResNet50 是一个具体的网络结构,其由50个卷积层组成。ResNet50 是指包含了50个卷积层(包括卷积层、池化层、全连接层等)的 ResNet 网络。ResNet50 是基于 ImageNet 数据集上的训练所提出的一个具体网络结构。
ResNet 核心:在最终输出中,除了包含对输入 x 的通过传统的通过各卷积层得到的结果,还引入了 x 本身,保证了不会产生因为卷积层的加深而导致的梯度消失以及原有特征的消失的问题
ResNet 核心有两种 Block:Conv Block 和 Identify Block。Conv 块的目标是学习特征的非线性映射,从而提取图像的高级特征,Identify 块的目的是跳跃地将输入传递到输出口,方便和卷积后的结果线性相加。

代码具体如下 :

导入库:

import torch  
from torch import nn

写一个名为 Bottleneck 的残差 Block:

'''  
Block的各个plane值:  
inplane:输出block的之前的通道数  
midplane:在block中间处理的时候的通道数(这个值是输出维度的1/4)  
midplane*self.extention:输出的维度  
'''  
class Bottleneck(nn.Module):  
#定义了一个名为 Bottleneck 的 PyTorch 模型类,该类继承自 nn.Module
  
extention=4  
#定义extention变量,表示 Bottleneck 残差块中维度拓展的倍数,即输出通道数相对于中间通道数的倍数,也即每个stage中维度拓展的倍数  
  
#定义初始化的网络和参数  
def __init__(self,inplane,midplane,stride,downsample=None):  
super(Bottleneck,self).__init__()  
#四个参数:inplane 表示输入通道数,midplane 表示中间处理时的通道数,stride 表示步长,downsample 用于定义跳跃连接中的下采样层。这里使用了可选参数的形式,并且选择了不传入 downsample,写为 None
#接着调用了父类 nn.Module 的初始化函数,确保正确地初始化 Bottleneck 类
  
self.conv1=nn.Conv2d(inplane,midplane,kernel_size=1,stride=stride,bias=False)  
self.bn1=nn.BatchNorm2d(midplane)  
#这两行定义了第一个卷积层 conv1 和批量归一化层 bn1。Conv2d 表示二维卷积层,inplane 为输入通道数,midplane 为输出通道数,kernel_size=1 表示卷积核大小为 1x1,stride=stride 表示步长与参数传入的 stride 相同,bias=False 表示不使用偏置。BatchNorm2d 则是二维批量归一化层,对 midplane 通道进行批量归一化
#批量归一化层(Batch Normalization)对于每个训练小批量数据,批量归一化层计算该批量数据的均值和标准差,并使用这些统计量对数据进行标准化处理,使得数据的均值接近于零,标准差接近于一

self.conv2=nn.Conv2d(midplane,midplane,kernel_size=3,stride=1,padding=1,bias=False)
self.bn2=nn.BatchNorm2d(midplane)  
#这两行定义了第二个卷积层 conv2 和批量归一化层 bn2。这个卷积层的输入和输出通道数都是 midplane,kernel_size=3 表示卷积核大小为 3x3,stride=1 表示步长为 1,padding=1 表示在图像周围填充一个像素,保持输入输出大小相同

self.conv3=nn.Conv2d(midplane,midplane*self.extention,kernel_size=1,stride=1,bias=False)  
self.bn3=nn.BatchNorm2d(midplane*self.extention)  
#这两行定义了第三个卷积层 conv3 和批量归一化层 bn3。这个卷积层的输入通道数是 midplane,输出通道数是 midplane*self.extention,即 midplane 乘以类变量 extention 的值,相当于对中间通道数进行了拓展

self.relu=nn.ReLU(inplace=False)  
#定义了 ReLU 激活函数
  
self.downsample=downsample  
self.stride=stride  
#这两行分别将初始化函数的参数 downsample 和 stride 分配给类的属性
  
def forward(self,x):  
#参差数据  
residual=x  
#将输入 x 赋值给变量 residual,用于后续的跳跃连接
  
out=self.relu(self.bn1(self.conv1(x)))  
out=self.relu(self.bn2(self.conv2(out)))  
out=self.relu(self.bn3(self.conv3(out)))  
#卷积操作,依次经过了三个卷积层和批量归一化层,并使用 ReLU 激活函数 
  
#是否直连(如果时Identity block就是直连;如果是Conv Block就需要对参差边进行卷积,改变通道数和size)  
if(self.downsample!=None):  
residual=self.downsample(x)  
  
#将参差部分和卷积部分相加  
out+=residual  
out=self.relu(out)  
  
return out

写 ResNet 结构:

class ResNet(nn.Module):  
  
#初始化网络结构和参数  
def __init__(self,block,layers,num_classes=1000):  
#self.inplane为当前的fm的通道数,初始化值为64  
self.inplane=64  
  
super(ResNet,self).__init__()  
#调用了父类 nn.Module 的构造方法
  
#参数  
self.block=block  
self.layers=layers  
  
#stem的网络层  
self.conv1=nn.Conv2d(3,self.inplane,kernel_size=7,stride=2,padding=3,bias=False)  
#定义了第一个卷积层(conv1),使用了7x7的核大小,2的步长,3的填充。它接受具有3个通道(用于RGB图像)的输入,并产生self.inplane个输出通道
self.bn1=nn.BatchNorm2d(self.inplane)  
#初始化了第一个卷积层的批量归一化层
self.relu=nn.ReLU()  
#初始化了ReLU激活函数
self.maxpool=nn.MaxPool2d(kernel_size=3,padding=1,stride=2)  
#初始化了最大池化层,核大小为3x3,填充为1,步长为2
  
#64,128,256,512是指扩大4倍之前的维度,即Identity Block的中间维度  
self.stage1=self.make_layer(self.block,64,self.layers[0],stride=1)  
#使用make_layer方法创建了网络的第一个阶段。它采用了block类型,64作为中间平面维度,并采用layers[0]中指定的层数
#self.block指定了残差块类型,64是指此阶段中残差块的输出通道数,self.layers[0]是指这个阶段中残差块的数量,self.layers是一个列表,包含了每个阶段所包含的残差块的数量,[0]即代表这个第一个阶段
self.stage2=self.make_layer(self.block,128,self.layers[1],stride=2)  
self.stage3=self.make_layer(self.block,256,self.layers[2],stride=2)  
self.stage4=self.make_layer(self.block,512,self.layers[3],stride=2)  
#与第一阶段同理
  
#后续的网络  
self.avgpool=nn.AvgPool2d(7)  
#初始化了平均池化层,核大小为7x7
self.fc = nn.Linear(512 * block.extention, num_classes)  
#初始化了用于分类的全连接层(fc)。输入大小是根据最后一个阶段的输出通道数(512 * block.extention)和类别数(num_classes)计算得出的
  
  
  
  
  
def forward(self,x):  
#定义了模型,输入为 x
  
#stem部分:conv+bn+relu+maxpool  
out=self.conv1(x)  
#通过第一个卷积层处理输入 x,得到输出 out
out=self.bn1(out)  
#对输出进行批量归一化操作
out=self.relu(out)  
#对输出进行 ReLU 激活函数操作
out=self.maxpool(out)  
#对输出进行最大池化操作
  
#block  
out=self.stage1(out)  
out=self.stage2(out)  
out=self.stage3(out)  
out=self.stage4(out)  
#分别通过四个阶段(stage)的残差块处理输出
  
#分类  
out=self.avgpool(out)  
#对输出进行全局平均池化操作
out = torch.flatten(out, 1)  
#将输出展平为一维
out=self.fc(out)  
#通过全连接层进行分类预测
  
  
return out  
  
def make_layer(self,block,midplane,block_num,stride=1):  
'''  
block:block模块  
midplane:每个模块中间运算的维度,一般等于输出维度/4  
block_num:重复次数  
stride:Conv Block的步长  
'''  
  
block_list=[]  
#创建一个空列表,用于存储残差块
  
#先计算要不要加downsample模块  
downsample=None  
if(stride!=1or self.inplane!=midplane*block.extention):  
#判断是否需要添加下采样模块
downsample=nn.Sequential(  
nn.Conv2d(self.inplane,midplane*block.extention,stride=stride,kernel_size=1,bias=False),  
nn.BatchNorm2d(midplane*block.extention)  
) 
#如果需要下采样,则创建一个下采样模块,包括一个 1x1 的卷积层和批量归一化层
#下采样模块的作用是将输入的特征图的空间尺寸减小,同时增加通道数量,以便在网络的不同阶段进行特征图的匹配和组合
  
  
#Conv Block  
conv_block=block(self.inplane,midplane,stride=stride,downsample=downsample)  
block_list.append(conv_block)  
#创建一个 Conv Block,包括一个残差块,将 Conv Block 添加到 block_list 中
self.inplane=midplane*block.extention  
#更新输入平面大小
  
#Identity Block  
for i in range(1,block_num):  
#循环创建 Identity Block
block_list.append(block(self.inplane,midplane,stride=1))  
#创建一个 Identity Block 并添加到 block_list 中
  
return nn.Sequential(*block_list)
#返回由所有残差块组成的 Sequential 模块

实例调用:

resnet = ResNet(Bottleneck, [3, 4, 6, 3])  
#由4个阶段组成,每个阶段包含不同数量的块。数字[3, 4, 6, 3]表示每个阶段中的块数
x=torch.randn(1,3,224,224)  
#创建了一个张量x,其中包含从正态分布中采样的随机数。张量x的形状是(1, 3, 224, 224),表示它代表一个具有3个通道(RGB)和分辨率为224x224像素的图像
x=resnet(x)  
#通过ResNet模型resnet将张量x传递进去,从而实现了对网络的前向传播。输出的x将是ResNet模型进行分类的结果
print(x.shape)
#打印输出张量x的形状,表明x的维度,形式为(batch_size, num_classes),其中batch_size是在批处理中处理的输入样本数,num_classes是模型预测的输出类别数

结果显示:
啊

Torch. Size ([1,1000])
啊

标签:ResNet50,nn,self,stride,算法,midplane,block,out
From: https://www.cnblogs.com/jzzg/p/18138375

相关文章

  • 一种算法
          #!usr/bin/envpython#-*-coding:utf-8-*-"""@author:Suyue@file:speedeeinsert.py@time:2024/04/16@desc:"""#importnumpyasnpimportpandasaspddf1=pd.read_excel('G:/尺度速度.xls')file_path......
  • 每个程序员都应该知道的 40 个算法(二)
    原文:zh.annas-archive.org/md5/8ddea683d78e7bd756401ec665273969译者:飞龙协议:CCBY-NC-SA4.0第五章:图算法有一类计算问题最好以图的术语来表示。这类问题可以使用一类称为图算法的算法来解决。例如,图算法可以用于在数据的图形表示中高效搜索值。为了高效工作,这些算法首先......
  • 密码学中的RSA算法与椭圆曲线算法
    PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。在数字安全领域,加密算法扮演着至关重要的角色。它们确保了信息的机密性、完整性和不可否认性。RSA算法和椭圆曲线算法(ECC)是当前最广泛使用的两......
  • 28天【代码随想录算法训练营34期】第七章 回溯算法 (● 93.复原IP地址 ● 78.子集
    93.复原IP地址classSolution:defrestoreIpAddresses(self,s:str)->List[str]:result=[]self.backtracking(s,[],0,result)returnresultdefbacktracking(self,s,path,index,result):ifindex>=len(s......
  • 常见的排序算法——希尔排序
    本文记述了希尔排序的基本思想和一份参考实现代码,并在说明了算法的性能后用随机数据进行了验证。◆思想给定元素之间的间隔h,将所有间隔为h的元素作为独立的待排序范围,可以得到h个这样的子范围。针对每个子范围执行插入排序,使得任意间隔为h的元素是有序的。然后缩小间距......
  • 深度学习算法中的稀疏编码(Sparse Coding)
    【摘要】引言稀疏编码(SparseCoding)是深度学习算法中的一种重要技术,它在神经网络模型中发挥着重要的作用。本文将介绍稀疏编码的基本概念、原理以及在深度学习中的应用。稀疏编码的概念稀疏编码是一种通过寻找数据的稀疏表示来描述数据的方法。在深度学习中,稀疏编码可以将输入数......
  • 基于直方图相似性的图像分类算法FPGA实现,包括tb测试文件和MATLAB辅助验证
    1.算法运行效果图预览MATLAB测试结果:    FPGA测试结果:   上述仿真图中,红色XX表示图像读取完毕。因此输出XX。当图像输出完成之后,最下面的相似性指标 same1输出为11226,same2输出为67584.即图1和图2相似性较强,图1和图3相似性较弱。 2.算法运行软件版本vi......
  • 27天【代码随想录算法训练营34期】第七章 回溯算法part03(● 39. 组合总和 ● 40.组合
    39.组合总和怎么才能避免重复?比现在数小的数就别append到path里面了,之前肯定都试过了classSolution:defcombinationSum(self,candidates:List[int],target:int)->List[List[int]]:result=[]candidates.sort()self.backtracking(cand......
  • 算法相关读书笔记
    由于算法导论中涉及大量数学公式,在腾讯文档才能友好的展示,因此下面分享的为腾讯文档的链接个人能力有限,可能有的理解是错误的,请谅解,仅供分享和参考【腾讯文档】算法导论1~3部分【腾讯文档】算法导论第4~5部分【腾讯文档】算法导论第6部分22~24章【腾讯文档】算法导论第6部分2......
  • 深入理解DES算法:原理、实现与应用
    title:深入理解DES算法:原理、实现与应用date:2024/4/1421:30:21updated:2024/4/1421:30:21tags:DES加密对称加密分组密码密钥管理S盒P盒安全性分析替代算法DES算法简介历史DES(DataEncryptionStandard)算法是由IBM研发,并于1977年被美国国家标准局(NBS,现NIST......