【RT-DETR有效改进】轻量级下采样方法ContextGuided(参数量下降700W,轻量又涨点)

本文主要是介绍【RT-DETR有效改进】轻量级下采样方法ContextGuided(参数量下降700W,轻量又涨点),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

👑欢迎大家订阅本专栏,一起学习RT-DETR👑    

 一、本文介绍

本文给大家带来的是改进机制是一种替换Conv的模块Context Guided Block (CG block) ,其是在CGNet论文中提出的一种模块,其基本原理是模拟人类视觉系统依赖上下文信息来理解场景。CG block 用于捕获局部特征、周围上下文和全局上下文,并将这些信息融合起来以提高准确性。本文改进是基于ResNet18、ResNet34、ResNet50、ResNet101,文章中均以提供,本专栏的改进内容全网独一份深度改进RT-DETR非那种无效Neck部分改进,同时本文的改进也支持主干上的即插即用,本文内容也支持PP-HGNetV2版本的修改。

专栏链接:RT-DETR剑指论文专栏,持续复现各种顶会内容——论文收割机RT-DETR  

目录

 一、本文介绍

二、ContextGuidedBlock_Down模块原理

2.1  ContextGuidedBlock_Down的基本原理

2.2  局部特征提取器

2.3  周围上下文提取器

2.4  联合特征提取器

2.5  全局上下文提取器

三、ContextGuided的核心代码

四、 手把手教你添加ContextGuided(注意看此处)

4.1 修改Basicclock/Bottleneck的教程

4.1.1 修改一

4.1.2 修改二 

4.2 修改主干上即插即用的教程

4.2.1 修改一(如果修改了4.1教程此步无需修改)

4.2.2 修改二 

4.2.3 修改三 

4.2.4 修改四 

五、ContextGuided的yaml文件

5.1 替换ResNet的yaml文件1(ResNet18版本)

5.2 替换ResNet的yaml文件1(ResNet50版本)

5.3 即插即用的yaml文件(HGNetV2版本)

六、成功运行记录 

6.1 ResNet18运行成功记录截图

​6.2 ResNet50运行成功记录截图

6.3 HGNetv2运行成功记录截图

七、全文总结 


二、ContextGuidedBlock_Down模块原理

论文地址:官方论文地址

代码地址:官方代码地址


2.1  ContextGuidedBlock_Down的基本原理

Context Guided Block (CG block) 在CGNet中的基本原理是模拟人类视觉系统依赖上下文信息来理解场景。CG block 用于捕获局部特征、周围上下文和全局上下文,并将这些信息融合起来以提高语义分割的准确性。这一模块包含以下部分:

1. 局部特征提取器(floc): 使用标准卷积层学习局部特征。
2. 周围上下文提取器(fsur): 使用空洞/膨胀卷积层来学习更大接收野的周围上下文。
3. 联合特征提取器(fjoi): 通过连接层和批量归一化(BN)以及参数化ReLU(PReLU)操作来融合局部特征和周围上下文的输出,获取联合特征。
4. 全局上下文提取器(fglo):使用全局平均池化层聚合全局上下文,并通过多层感知器来进一步提取全局上下文。然后,使用缩放层以提取的全局上下文对联合特征进行加权,以强调有用的组件并抑制无用的组件。

这个过程是自适应的,因为提取的全局上下文是基于输入图像生成的。CG block 的设计允许CGNet能够有效地从底层到顶层聚合上下文信息,并在语义层面(来自深层)空间层面(来自浅层)捕获上下文信息,这对于语义分割至关重要。

下面就为大家展示了三种用于语义分割的不同架构:

(a) FCN-shape(全卷积网络形状): 此模型遵循图像分类的设计原则,忽略了上下文信息。它可能使用一系列卷积和池化层来处理输入图像,并生成输出,但没有显式地对各个层次的特征周围上下文进行建模。

(b) FCN-CM(全卷积网络-上下文模块): 此模型只在编码阶段后捕获上下文信息,通过执行一个上下文模块来从语义层次提取上下文信息。

(c) 我们提出的CGNet(上下文引导网络): 捕获所有阶段的上下文特征,从语义层次和空间层次两方面进行。

总结:CGB_Down的设计旨在充分利用局部特征、周围上下文和全局上下文,通过这种结构设计,CGNet能够在局部和全局上下文之间建立联系,这对于准确分类图像中的每个像素至关重要。此外,CGB_Down还采用了残差学习来帮助学习复杂特征并在训练期间改善梯度的反向传播。


2.2  局部特征提取器

局部特征提取器(记为floc(*))是上下文引导块(CG block)的一个组成部分,专门用于学习输入数据中的局部特征。在CGNet的设计中,这个局部特征提取器通过标准的3×3卷积层实现,其目的是从图像中的局部区域提取特征。这些局部特征随后与周围上下文特征结合,形成了网络对各个区域的全面理解,这对于语义分割尤为重要。

CGNet使用的局部特征提取器与周围上下文提取器(fsur(*)一起工作,确保模型不仅能够理解每个像素或局部区域的信息,而且还能理解这些区域在整体上下文中的关系。这种提取器能够捕捉到的细节和局部变化信息对于精确地分类图像中的每个像素至关重要,特别是在需要细粒度预测的任务中,如在复杂场景中区分不同的物体和表面。

CGNet的结构设计还包括减少参数数量,其中局部特征提取器和周围上下文提取器采用了通道卷积(channel-wise convolutions),以减少跨通道的计算成本并大幅节约内存。这种设计允许CGNet即使在资源受限的环境中(如移动设备)也能有效运行,同时保持高准确率和实时性。


2.3  周围上下文提取器

周围上下文提取器f_{sur}(*))在CGNet架构中的作用和原理包括:

1. 提取更广泛的上下文信息:周围上下文提取器使用扩展卷积(例如空洞卷积)来增加感受野的大小,从而捕获更宽广的上下文信息。这允许模型观察到更大区域的特征,而不仅仅是局部的细节。

2. 辅助局部特征理解:通过结合局部特征和周围上下文,f_{sur}(*)能够提供额外的信息,帮助模型更好地理解复杂的场景。例如,在辨识一个物体时,除了物体本身的特征外,它的周围环境也提供了重要的线索。

3. 改进语义分割的准确性:研究表明,周围上下文的信息对于提高语义分割的准确性非常有益。在不同的架构实验中,引入f_{sur}(*)都能显著提升分割的准确率。

4. 在网络的所有块中使用:为了充分利用周围上下文的优势,f_{sur}(*)在CGNet的所有块中都有应用,以保证整个网络都能受益于周围上下文信息的提取。

5. 空间金字塔池化:在一些变体中,f_{sur}(*)可能会采用空间金字塔池化来聚合不同尺度的上下文信息,这有助于模型捕捉从最小的细节到整体布局的不同层面的信息。

总结:通过这些设计,周围上下文提取器加强了CGNet处理各种尺度信息的能力,这在处理高分辨率图像和复杂场景的语义分割任务中尤其重要。 


2.4  联合特征提取器

联合特征提取器f_{joi}(*))在CGNet中的作用是整合由局部特征提取器和周围上下文提取器提取的特征。这些特征分别捕捉到了输入数据的细节(局部特征)和更广阔区域内的信息(周围上下文)。联合特征提取器的设计目的是为了使得网络能够同时考虑局部和上下文信息,从而提高语义分割的准确性。下面是它的一些关键点:

1. 特征融合:联合特征提取器通过连接(concatenation)操作将局部特征和周围上下文特征结合起来,形成一个综合的特征表示。

2. 增强特征表示:联合后的特征通过批量归一化(Batch Normalization, BN)和参数化的线性单元(Parametric ReLU, PReLU)等操作进行进一步的加工,以增强特征表示的能力。

3. 全局上下文的整合:在某些设计中,联合特征还会与全局上下文特征(f_{glo}(*))结合,以利用整个输入图像的信息来进一步优化特征。

联合特征提取器是上下文引导网络实现其高效语义分割能力的关键连接点,它允许网络在局部精细度和全局上下文间达到平衡.

下图为大家展示了上下文引导网络(Context Guided Network, CGNet)的架构。这个网络通过以下阶段处理输入图像来生成预测:

1. Stage 1:包含连续的3x3卷积层,这些层负责提取输入图像的初步特征。

2. Stage 2:由多个CG块组成,数量用"M"表示。每个CG块都结合了局部特征提取器和周围上下文提取器,它们一起工作以捕获更复杂的局部和上下文信息。

3. Stage 3:包含更多的CG块,数量用"N"表示,这一阶段进一步提炼特征,以捕捉更高层次的上下文信息。

4. 1x1 Conv:一个1x1的卷积层用于将特征映射到目标类别的数量,为最终的上采样和分类做准备。

5. 上采样(Upsample):使用上采样或逆卷积操作将特征图尺寸扩大回输入图像的尺寸。

6. 预测(Prediction):最终的预测图,其中每个像素被分配了一个类别标签,展示了对输入图像进行语义分割的结果。

总结:CGNet的设计旨在实现高效的语义分割,通过在网络的不同阶段利用局部和全局上下文信息来提高准确率,同时保持模型的轻量级特性。这使CGNet特别适合于资源受限的设备,如移动设备或嵌入式系统。在图中的预测示例中,可以看到网络已经将不同的交通参与者和背景要素成功地分割出来,用不同的颜色标记不同的类别。


2.5  全局上下文提取器

全局上下文提取器f_{glo}(*))在CGNet中的作用是捕获并利用整个输入图像的全局信息,以增强联合特征提取器学习到的特征。以下是它的基本原理

1. 全局特征汇总:全局上下文提取器通过全局平均池化(Global Average Pooling, GAP)来聚合整个特征图的全局信息。这个步骤产生一个全局特征向量,它捕获了输入图像中每个通道的平均响应。

2. 多层感知机处理:全局特征向量随后通过一个多层感知机(Multilayer Perceptron, MLP)进一步处理。MLP能够学习特征间的复杂非线性关系,进一步细化全局上下文特征。

3. 特征重标定:提取的全局上下文通过缩放层(scale layer)与联合特征结合。这个操作相当于将全局上下文信息作为权重,通道级别地重新标定联合特征,强调有用的特征部分,抑制不重要的特征部分。

4. 自适应性:全局上下文提取器的操作是自适应的,因为提取的全局上下文是根据输入图像生成的,使得网络能够针对不同的图像生成定制化的全局上下文。

5. 提高分割准确性:在消融研究中,使用全局上下文提取器可以提高分割的准确性。这证明了全局上下文在提升模型性能方面的价值。

提供了上下文引导块(Context Guided block)的概览。在图中的全局上下文提取器f_{glo}(*)部分,展示了使用全局平均池化(GAP)来提取全图的上下文信息,然后通过两个全连接层(FC)对这些信息进行进一步的处理。这有助于网络理解整个图像的全局信息,这对于分类图像中的局部区域特别重要,尤其是在这些局部区域的类别可能依赖于全局上下文的情况下。

这些组件共同工作,提高了网络对复杂场景中各种尺度的特征的理解能力,使得CGNet能够更准确地进行语义分割。通过这样的设计,CGNet能够在局部和全局上下文之间建立联系,这对于准确分类图像中的每个像素至关重要。


三、ContextGuided的核心代码

核心代码的使用方式看章节四!

import torch
from collections import OrderedDict
import torch.nn as nn
import torch.nn.functional as F__all__ = ['BottleNeck_ContextGuided', 'BasicBlock_ContextGuided', 'ContextGuidedBlock_Down']class ConvBNPReLU(nn.Module):def __init__(self, nIn, nOut, kSize, stride=1):"""args:nIn: number of input channelsnOut: number of output channelskSize: kernel sizestride: stride rate for down-sampling. Default is 1"""super().__init__()if isinstance(kSize, tuple):kSize = kSize[0]padding = int((kSize - 1) / 2)self.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), bias=False)self.bn = nn.BatchNorm2d(nOut, eps=1e-03)self.act = nn.PReLU(nOut)def forward(self, input):"""args:input: input feature mapreturn: transformed feature map"""output = self.conv(input)output = self.bn(output)output = self.act(output)return outputclass BNPReLU(nn.Module):def __init__(self, nOut):"""args:nOut: channels of output feature maps"""super().__init__()self.bn = nn.BatchNorm2d(nOut, eps=1e-03)self.act = nn.PReLU(nOut)def forward(self, input):"""args:input: input feature mapreturn: normalized and thresholded feature map"""output = self.bn(input)output = self.act(output)return outputclass ConvBN(nn.Module):def __init__(self, nIn, nOut, kSize, stride=1):"""args:nIn: number of input channelsnOut: number of output channelskSize: kernel sizestride: optinal stide for down-sampling"""super().__init__()if isinstance(kSize, tuple):kSize = kSize[0]padding = int((kSize - 1) / 2)self.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), bias=False)self.bn = nn.BatchNorm2d(nOut, eps=1e-03)def forward(self, input):"""args:input: input feature mapreturn: transformed feature map"""output = self.conv(input)output = self.bn(output)return outputclass Conv(nn.Module):def __init__(self, nIn, nOut, kSize, stride=1):"""args:nIn: number of input channelsnOut: number of output channelskSize: kernel sizestride: optional stride rate for down-sampling"""super().__init__()if isinstance(kSize, tuple):kSize = kSize[0]padding = int((kSize - 1) / 2)self.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), bias=False)def forward(self, input):"""args:input: input feature mapreturn: transformed feature map"""output = self.conv(input)return outputclass ChannelWiseConv(nn.Module):def __init__(self, nIn, nOut, kSize, stride=1):"""Args:nIn: number of input channelsnOut: number of output channels, default (nIn == nOut)kSize: kernel sizestride: optional stride rate for down-sampling"""super().__init__()if isinstance(kSize, tuple):kSize = kSize[0]padding = int((kSize - 1) / 2)self.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), groups=nIn,bias=False)def forward(self, input):"""args:input: input feature mapreturn: transformed feature map"""output = self.conv(input)return outputclass DilatedConv(nn.Module):def __init__(self, nIn, nOut, kSize, stride=1, d=1):"""args:nIn: number of input channelsnOut: number of output channelskSize: kernel sizestride: optional stride rate for down-samplingd: dilation rate"""super().__init__()if isinstance(kSize, tuple):kSize = kSize[0]padding = int((kSize - 1) / 2) * dself.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), bias=False,dilation=d)def forward(self, input):"""args:input: input feature mapreturn: transformed feature map"""output = self.conv(input)return outputclass ChannelWiseDilatedConv(nn.Module):def __init__(self, nIn, nOut, kSize, stride=1, d=1):"""args:nIn: number of input channelsnOut: number of output channels, default (nIn == nOut)kSize: kernel sizestride: optional stride rate for down-samplingd: dilation rate"""super().__init__()if isinstance(kSize, tuple):kSize = kSize[0]padding = int((kSize - 1) / 2) * dself.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), groups=nIn,bias=False, dilation=d)def forward(self, input):"""args:input: input feature mapreturn: transformed feature map"""output = self.conv(input)return outputclass FGlo(nn.Module):"""the FGlo class is employed to refine the joint feature of both local feature and surrounding context."""def __init__(self, channel, reduction=16):super(FGlo, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Sequential(nn.Linear(channel, channel // reduction),nn.ReLU(inplace=True),nn.Linear(channel // reduction, channel),nn.Sigmoid())def forward(self, x):b, c, _, _ = x.size()y = self.avg_pool(x).view(b, c)y = self.fc(y).view(b, c, 1, 1)return x * yclass ContextGuidedBlock_Down(nn.Module):"""the size of feature map divided 2, (H,W,C)---->(H/2, W/2, 2C)"""def __init__(self, nIn, dilation_rate=2, reduction=16):"""args:nIn: the channel of input feature mapnOut: the channel of output feature map, and nOut=2*nIn"""super().__init__()nOut = nInself.conv1x1 = ConvBNPReLU(nIn, nOut, 3, 2)  # size/2, channel: nIn--->nOutself.F_loc = ChannelWiseConv(nOut, nOut, 3, 1)self.F_sur = ChannelWiseDilatedConv(nOut, nOut, 3, 1, dilation_rate)self.bn = nn.BatchNorm2d(2 * nOut, eps=1e-3)self.act = nn.PReLU(2 * nOut)self.reduce = Conv(2 * nOut, nOut, 1, 1)  # reduce dimension: 2*nOut--->nOutself.F_glo = FGlo(nOut, reduction)def forward(self, input):output = self.conv1x1(input)loc = self.F_loc(output)sur = self.F_sur(output)joi_feat = torch.cat([loc, sur], 1)  # the joint featurejoi_feat = self.bn(joi_feat)joi_feat = self.act(joi_feat)joi_feat = self.reduce(joi_feat)  # channel= nOutoutput = self.F_glo(joi_feat)  # F_glo is employed to refine the joint featurereturn outputclass ContextGuidedBlock(nn.Module):def __init__(self, nIn, nOut, dilation_rate=2, reduction=16, add=False):"""args:nIn: number of input channelsnOut: number of output channels,add: if true, residual learning"""super().__init__()n = int(nOut / 2)self.conv1x1 = ConvBNPReLU(nIn, n, 1, 1)  # 1x1 Conv is employed to reduce the computationself.F_loc = ChannelWiseConv(n, n, 3, 1)  # local featureself.F_sur = ChannelWiseDilatedConv(n, n, 3, 1, dilation_rate)  # surrounding contextself.bn_prelu = BNPReLU(nOut)self.add = addself.F_glo = FGlo(nOut, reduction)def forward(self, input):output = self.conv1x1(input)loc = self.F_loc(output)sur = self.F_sur(output)joi_feat = torch.cat([loc, sur], 1)joi_feat = self.bn_prelu(joi_feat)output = self.F_glo(joi_feat)  # F_glo is employed to refine the joint feature# if residual versionif self.add:output = input + outputreturn outputclass ConvNormLayer(nn.Module):def __init__(self,ch_in,ch_out,filter_size,stride,groups=1,act=None):super(ConvNormLayer, self).__init__()self.act = actself.conv = nn.Conv2d(in_channels=ch_in,out_channels=ch_out,kernel_size=filter_size,stride=stride,padding=(filter_size - 1) // 2,groups=groups)self.norm = nn.BatchNorm2d(ch_out)def forward(self, inputs):out = self.conv(inputs)out = self.norm(out)if self.act:out = getattr(F, self.act)(out)return outclass SELayer(nn.Module):def __init__(self, ch, reduction_ratio=16):super(SELayer, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Sequential(nn.Linear(ch, ch // reduction_ratio, bias=False),nn.ReLU(inplace=True),nn.Linear(ch // reduction_ratio, ch, bias=False),nn.Sigmoid())def forward(self, x):b, c, _, _ = x.size()y = self.avg_pool(x).view(b, c)y = self.fc(y).view(b, c, 1, 1)return x * y.expand_as(x)class BasicBlock_ContextGuided(nn.Module):expansion = 1def __init__(self,ch_in,ch_out,stride,shortcut,act='relu',variant='b',att=False):super().__init__()self.shortcut = shortcutif not shortcut:if variant == 'd' and stride == 2:self.short = nn.Sequential()self.short.add_sublayer('pool',nn.AvgPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=True))self.short.add_sublayer('conv',ConvNormLayer(ch_in=ch_in,ch_out=ch_out,filter_size=1,stride=1))else:self.short = ConvNormLayer(ch_in=ch_in,ch_out=ch_out,filter_size=1,stride=stride)self.branch2a = ConvNormLayer(ch_in=ch_in,ch_out=ch_out,filter_size=3,stride=stride,act='relu')"""↓ 替换了此处的ConvNormLayer ↓"""# 有需要的上面的也可以替换self.branch2b = ContextGuidedBlock(ch_out,ch_out)#         self.branch2b = ConvNormLayer(#             ch_in=ch_out,#             ch_out=ch_out,#             filter_size=3,#             stride=1,#             act=None)"""↑ 替换了此处的ConvNormLayer ↑"""self.att = attif self.att:self.se = SELayer(ch_out)def forward(self, inputs):out = self.branch2a(inputs)out = self.branch2b(out)if self.att:out = self.se(out)if self.shortcut:short = inputselse:short = self.short(inputs)out = out + shortout = F.relu(out)return outclass BottleNeck_ContextGuided(nn.Module):expansion = 4def __init__(self, ch_in, ch_out, stride, shortcut, act='relu', variant='d', att=False):super().__init__()if variant == 'a':stride1, stride2 = stride, 1else:stride1, stride2 = 1, stridewidth = ch_outself.branch2a = ConvNormLayer(ch_in, width, 1, stride1, act=act)self.branch2b = ConvNormLayer(width, width, 3, stride2, act=act)"""↓ 替换了此处的ConvNormLayer ↓"""# 有需要的上面的也可以替换self.branch2c = ContextGuidedBlock(width, ch_out * self.expansion)# self.branch2c = ConvNormLayer(width, ch_out * self.expansion, 1, 1)"""↑ 替换了此处的ConvNormLayer ↑"""self.shortcut = shortcutif not shortcut:if variant == 'd' and stride == 2:self.short = nn.Sequential(OrderedDict([('pool', nn.AvgPool2d(2, 2, 0, ceil_mode=True)),('conv', ConvNormLayer(ch_in, ch_out * self.expansion, 1, 1))]))else:self.short = ConvNormLayer(ch_in, ch_out * self.expansion, 1, stride)self.att = attif self.att:self.se = SELayer(ch_out)def forward(self, x):out = self.branch2a(x)out = self.branch2b(out)out = self.branch2c(out)if self.att:out = self.se(out)if self.shortcut:short = xelse:short = self.short(x)out = out + shortout = F.relu(out)return outif __name__ == '__main__':x = torch.rand(2, 64, 4, 7)dys = ContextGuidedBlock(64, 256)print(dys(x).shape)


四、 手把手教你添加ContextGuided(注意看此处)

修改教程分两种,一种是替换修改ResNet中的Basicclock/Bottleneck模块的,一种是在主干上即插即用的修改教程,如果你只需要一种那么修改对应的就行,互相之间并不影响,需要注意的是即插即用的需要修改ResNet改进才行,链接如下:

ResNet文章地址:【RT-DETR改进涨点】ResNet18、34、50、101等多个版本移植到ultralytics仓库(RT-DETR官方一比一移植)


4.1 修改Basicclock/Bottleneck的教程

4.1.1 修改一

第一还是建立文件,我们找到如下ultralytics/nn/modules文件夹下建立一个目录名字呢就是'Addmodules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。


4.1.2 修改二 

第二步此处需要注意,因为我这里默认大家修改了ResNet系列的模型了,同级目录下应该有一个ResNet.py的文件夹,我们这里需要找到我们'ultralytics/nn/Addmodules/ResNet.py'创建的ResNet的文件夹(默认大家已经创建了!!!)

我们只需要修改上面的两步即可,后面复制yaml文件进行运行即可了,修改方法大家只要仔细看是非常简单的。


4.2 修改主干上即插即用的教程

4.2.1 修改一(如果修改了4.1教程此步无需修改)

第一还是建立文件,我们找到如下ultralytics/nn/modules文件夹下建立一个目录名字呢就是'Addmodules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。


4.2.2 修改二 

第二步我们在该目录下创建一个新的py文件名字为'__init__.py'(用群内的文件的话已经有了无需新建),然后在其内部导入我们的检测头如下图所示。


4.2.3 修改三 

第三步我门中到如下文件'ultralytics/nn/tasks.py'进行导入和注册我们的模块(用群内的文件的话已经有了无需重新导入直接开始第四步即可)

从今天开始以后的教程就都统一成这个样子了,因为我默认大家用了我群内的文件来进行修改!!


4.2.4 修改四 

按照我的添加在parse_model里添加即可。

        elif m in {ContextGuidedBlock_Down}:c2 = ch[f]args = [c2, *args]

到此就修改完成了,大家可以复制下面的yaml文件运行。

 


五、ContextGuided的yaml文件

5.1 替换ResNet的yaml文件1(ResNet18版本)

需要修改如下的ResNet主干才可以运行本文的改进机制 !

 ResNet文章地址:【RT-DETR改进涨点】ResNet18、34、50、101等多个版本移植到ultralytics仓库(RT-DETR官方一比一移植)

# Ultralytics YOLO 🚀, AGPL-3.0 license
# RT-DETR-l object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'# [depth, width, max_channels]l: [1.00, 1.00, 1024]backbone:# [from, repeats, module, args]- [-1, 1, ConvNormLayer, [32, 3, 2, 1, 'relu']] # 0-P1- [-1, 1, ConvNormLayer, [32, 3, 1, 1, 'relu']] # 1- [-1, 1, ConvNormLayer, [64, 3, 1, 1, 'relu']] # 2- [-1, 1, nn.MaxPool2d, [3, 2, 1]] # 3-P2- [-1, 2, Blocks, [64,  BasicBlock_ContextGuided, 2, False]] # 4- [-1, 2, Blocks, [128, BasicBlock_ContextGuided, 3, False]] # 5-P3- [-1, 2, Blocks, [256, BasicBlock_ContextGuided, 4, False]] # 6-P4- [-1, 2, Blocks, [512, BasicBlock_ContextGuided, 5, False]] # 7-P5head:- [-1, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 8 input_proj.2- [-1, 1, AIFI, [1024, 8]]- [-1, 1, Conv, [256, 1, 1]]  # 10, Y5, lateral_convs.0- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 11- [6, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 12 input_proj.1- [[-2, -1], 1, Concat, [1]]- [-1, 3, RepC3, [256, 0.5]]  # 14, fpn_blocks.0- [-1, 1, Conv, [256, 1, 1]]  # 15, Y4, lateral_convs.1- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 16- [5, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 17 input_proj.0- [[-2, -1], 1, Concat, [1]]  # 18 cat backbone P4- [-1, 3, RepC3, [256, 0.5]]  # X3 (19), fpn_blocks.1- [-1, 1, Conv, [256, 3, 2]]  # 20, downsample_convs.0- [[-1, 15], 1, Concat, [1]]  # 21 cat Y4- [-1, 3, RepC3, [256, 0.5]]  # F4 (22), pan_blocks.0- [-1, 1, Conv, [256, 3, 2]]  # 23, downsample_convs.1- [[-1, 10], 1, Concat, [1]]  # 24 cat Y5- [-1, 3, RepC3, [256, 0.5]]  # F5 (25), pan_blocks.1- [[19, 22, 25], 1, RTDETRDecoder, [nc, 256, 300, 4, 8, 3]]  # Detect(P3, P4, P5)


5.2 替换ResNet的yaml文件1(ResNet50版本)

需要修改如下的ResNet主干才可以运行本文的改进机制 !

 ResNet文章地址:【RT-DETR改进涨点】ResNet18、34、50、101等多个版本移植到ultralytics仓库(RT-DETR官方一比一移植)

# Ultralytics YOLO 🚀, AGPL-3.0 license
# RT-DETR-l object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'# [depth, width, max_channels]l: [1.00, 1.00, 1024]backbone:# [from, repeats, module, args]- [-1, 1, ConvNormLayer, [32, 3, 2, 1, 'relu']] # 0-P1- [-1, 1, ConvNormLayer, [32, 3, 1, 1, 'relu']] # 1- [-1, 1, ConvNormLayer, [64, 3, 1, 1, 'relu']] # 2- [-1, 1, nn.MaxPool2d, [3, 2, 1]] # 3-P2- [-1, 3, Blocks, [64,  BottleNeck_ContextGuided, 2, False]] # 4- [-1, 4, Blocks, [128, BottleNeck_ContextGuided, 3, False]] # 5-P3- [-1, 6, Blocks, [256, BottleNeck_ContextGuided, 4, False]] # 6-P4- [-1, 3, Blocks, [512, BottleNeck_ContextGuided, 5, False]] # 7-P5head:- [-1, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 8 input_proj.2- [-1, 1, AIFI, [1024, 8]] # 9- [-1, 1, Conv, [256, 1, 1]]  # 10, Y5, lateral_convs.0- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 11- [6, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 12 input_proj.1- [[-2, -1], 1, Concat, [1]] # 13- [-1, 3, RepC3, [256]]  # 14, fpn_blocks.0- [-1, 1, Conv, [256, 1, 1]]   # 15, Y4, lateral_convs.1- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 16- [5, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 17 input_proj.0- [[-2, -1], 1, Concat, [1]]  # 18 cat backbone P4- [-1, 3, RepC3, [256]]    # X3 (19), fpn_blocks.1- [-1, 1, Conv, [256, 3, 2]]   # 20, downsample_convs.0- [[-1, 15], 1, Concat, [1]]  # 21 cat Y4- [-1, 3, RepC3, [256]]    # F4 (22), pan_blocks.0- [-1, 1, Conv, [256, 3, 2]]   # 23, downsample_convs.1- [[-1, 10], 1, Concat, [1]]  # 24 cat Y5- [-1, 3, RepC3, [256]]    # F5 (25), pan_blocks.1- [[19, 22, 25], 1, RTDETRDecoder, [nc, 256, 300, 4, 8, 6]]  # Detect(P3, P4, P5)


5.3 即插即用的yaml文件(HGNetV2版本)

此版本为HGNetV2-l的yaml文件!

# Ultralytics YOLO 🚀, AGPL-3.0 license
# RT-DETR-l object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'# [depth, width, max_channels]l: [1.00, 1.00, 1024]backbone:# [from, repeats, module, args]- [-1, 1, HGStem, [32, 48]]  # 0-P2/4- [-1, 6, HGBlock, [48, 128, 3]]  # stage 1- [-1, 1, DWConv, [128, 3, 2, 1, False]]  # 2-P3/8- [-1, 6, HGBlock, [96, 512, 3]]  # stage 2- [-1, 1, DWConv, [512, 3, 2, 1, False]]  # 4-P3/16- [-1, 6, HGBlock, [192, 1024, 5, True, False]]  # cm, c2, k, light, shortcut- [-1, 6, HGBlock, [192, 1024, 5, True, True]]- [-1, 6, HGBlock, [192, 1024, 5, True, True]]  # stage 3- [-1, 1, DWConv, [1024, 3, 2, 1, False]]  # 8-P4/32- [-1, 6, HGBlock, [384, 2048, 5, True, False]]  # stage 4head:- [-1, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 10 input_proj.2- [-1, 1, AIFI, [1024, 8]]- [-1, 1, Conv, [256, 1, 1]]  # 12, Y5, lateral_convs.0- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [7, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 14 input_proj.1- [[-2, -1], 1, Concat, [1]]- [-1, 3, RepC3, [256]]  # 16, fpn_blocks.0- [-1, 1, Conv, [256, 1, 1]]  # 17, Y4, lateral_convs.1- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [3, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 19 input_proj.0- [[-2, -1], 1, Concat, [1]]  # cat backbone P4- [-1, 3, RepC3, [256]]  # X3 (21), fpn_blocks.1- [-1, 1, ContextGuidedBlock_Down, []]  # 22, downsample_convs.0- [[-1, 17], 1, Concat, [1]]  # cat Y4- [-1, 3, RepC3, [256]]  # F4 (24), pan_blocks.0- [-1, 1, ContextGuidedBlock_Down, []]  # 25, downsample_convs.1- [[-1, 12], 1, Concat, [1]]  # cat Y5- [-1, 3, RepC3, [256]]  # F5 (27), pan_blocks.1- [[21, 24, 27], 1, RTDETRDecoder, [nc]]  # Detect(P3, P4, P5)


六、成功运行记录 

6.1 ResNet18运行成功记录截图


​6.2 ResNet50运行成功记录截图


6.3 HGNetv2运行成功记录截图


七、全文总结 

到此本文的正式分享内容就结束了,在这里给大家推荐我的RT-DETR改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

专栏链接:RT-DETR剑指论文专栏,持续复现各种顶会内容——论文收割机RT-DETR  

这篇关于【RT-DETR有效改进】轻量级下采样方法ContextGuided(参数量下降700W,轻量又涨点)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/684158

相关文章

Python将字符串转换为小写字母的几种常用方法

《Python将字符串转换为小写字母的几种常用方法》:本文主要介绍Python中将字符串大写字母转小写的四种方法:lower()方法简洁高效,手动ASCII转换灵活可控,str.translate... 目录一、使用内置方法 lower()(最简单)二、手动遍历 + ASCII 码转换三、使用 str.tr

Python处理超大规模数据的4大方法详解

《Python处理超大规模数据的4大方法详解》在数据的奇妙世界里,数据量就像滚雪球一样,越变越大,从最初的GB级别的小数据堆,逐渐演变成TB级别的数据大山,所以本文我们就来看看Python处理... 目录1. Mars:数据处理界的 “变形金刚”2. Dask:分布式计算的 “指挥家”3. CuPy:GPU

Java中的StringUtils.isBlank()方法解读

《Java中的StringUtils.isBlank()方法解读》:本文主要介绍Java中的StringUtils.isBlank()方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录所在库及依赖引入方法签名方法功能示例代码代码解释与其他方法的对比总结StringUtils.isBl

CentOS7增加Swap空间的两种方法

《CentOS7增加Swap空间的两种方法》当服务器物理内存不足时,增加Swap空间可以作为虚拟内存使用,帮助系统处理内存压力,本文给大家介绍了CentOS7增加Swap空间的两种方法:创建新的Swa... 目录在Centos 7上增加Swap空间的方法方法一:创建新的Swap文件(推荐)方法二:调整Sww

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

MySQL精准控制Binlog日志数量的三种方案

《MySQL精准控制Binlog日志数量的三种方案》作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就... 目录 一招修改配置文件:永久生效的控制术1.定位my.cnf文件2.添加核心参数不重启热更新:高手应

macOS Sequoia 15.5 发布: 改进邮件和屏幕使用时间功能

《macOSSequoia15.5发布:改进邮件和屏幕使用时间功能》经过常规Beta测试后,新的macOSSequoia15.5现已公开发布,但重要的新功能将被保留到WWDC和... MACOS Sequoia 15.5 正式发布!本次更新为 Mac 用户带来了一系列功能强化、错误修复和安全性提升,进一步增

Oracle 通过 ROWID 批量更新表的方法

《Oracle通过ROWID批量更新表的方法》在Oracle数据库中,使用ROWID进行批量更新是一种高效的更新方法,因为它直接定位到物理行位置,避免了通过索引查找的开销,下面给大家介绍Orac... 目录oracle 通过 ROWID 批量更新表ROWID 基本概念性能优化建议性能UoTrFPH优化建议注

Pandas进行周期与时间戳转换的方法

《Pandas进行周期与时间戳转换的方法》本教程将深入讲解如何在pandas中使用to_period()和to_timestamp()方法,完成时间戳与周期之间的转换,并结合实际应用场景展示这些方法的... 目录to_period() 时间戳转周期基本操作应用示例to_timestamp() 周期转时间戳基

在 PyQt 加载 UI 三种常见方法

《在PyQt加载UI三种常见方法》在PyQt中,加载UI文件通常指的是使用QtDesigner设计的.ui文件,并将其转换为Python代码,以便在PyQt应用程序中使用,这篇文章给大家介绍在... 目录方法一:使用 uic 模块动态加载 (不推荐用于大型项目)方法二:将 UI 文件编译为 python 模