赞
踩
本文给大家带来的是改进机制是一种替换Conv的模块Context Guided Block (CG block) ,其是在CGNet论文中提出的一种模块,其基本原理是模拟人类视觉系统依赖上下文信息来理解场景。CG block 用于捕获局部特征、周围上下文和全局上下文,并将这些信息融合起来以提高准确性,同时本文的修改方法和之前的普通卷积模块也有所不同,大家需要注意看章节四进行修改。同时欢迎大家订阅本专栏,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家。同时本专栏目前改进基于yolov9.yaml文件,后期如果官方放出轻量化版本,专栏内所有改进也会同步更新,请大家放心。
目录
2.1 ContextGuidedBlock_Down的基本原理
四、 手把手教你添加ContextGuided(注意看此处)
4.2.1 ContextGuided的yaml版本一(推荐)
论文地址:官方论文地址
代码地址:官方代码地址
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还采用了残差学习来帮助学习复杂特征并在训练期间改善梯度的反向传播。
局部特征提取器(记为)是上下文引导块(CG block)的一个组成部分,专门用于学习输入数据中的局部特征。在CGNet的设计中,这个局部特征提取器通过标准的3×3卷积层实现,其目的是从图像中的局部区域提取特征。这些局部特征随后与周围上下文特征结合,形成了网络对各个区域的全面理解,这对于语义分割尤为重要。
CGNet使用的局部特征提取器与周围上下文提取器()一起工作,确保模型不仅能够理解每个像素或局部区域的信息,而且还能理解这些区域在整体上下文中的关系。这种提取器能够捕捉到的细节和局部变化信息对于精确地分类图像中的每个像素至关重要,特别是在需要细粒度预测的任务中,如在复杂场景中区分不同的物体和表面。
CGNet的结构设计还包括减少参数数量,其中局部特征提取器和周围上下文提取器采用了通道卷积(channel-wise convolutions),以减少跨通道的计算成本并大幅节约内存。这种设计允许CGNet即使在资源受限的环境中(如移动设备)也能有效运行,同时保持高准确率和实时性。
周围上下文提取器()在CGNet架构中的作用和原理包括:
1. 提取更广泛的上下文信息:周围上下文提取器使用扩展卷积(例如空洞卷积)来增加感受野的大小,从而捕获更宽广的上下文信息。这允许模型观察到更大区域的特征,而不仅仅是局部的细节。
2. 辅助局部特征理解:通过结合局部特征和周围上下文,能够提供额外的信息,帮助模型更好地理解复杂的场景。例如,在辨识一个物体时,除了物体本身的特征外,它的周围环境也提供了重要的线索。
3. 改进语义分割的准确性:研究表明,周围上下文的信息对于提高语义分割的准确性非常有益。在不同的架构实验中,引入都能显著提升分割的准确率。
4. 在网络的所有块中使用:为了充分利用周围上下文的优势,在CGNet的所有块中都有应用,以保证整个网络都能受益于周围上下文信息的提取。
5. 空间金字塔池化:在一些变体中,可能会采用空间金字塔池化来聚合不同尺度的上下文信息,这有助于模型捕捉从最小的细节到整体布局的不同层面的信息。
总结:通过这些设计,周围上下文提取器加强了CGNet处理各种尺度信息的能力,这在处理高分辨率图像和复杂场景的语义分割任务中尤其重要。
联合特征提取器()在CGNet中的作用是整合由局部特征提取器和周围上下文提取器提取的特征。这些特征分别捕捉到了输入数据的细节(局部特征)和更广阔区域内的信息(周围上下文)。联合特征提取器的设计目的是为了使得网络能够同时考虑局部和上下文信息,从而提高语义分割的准确性。下面是它的一些关键点:
1. 特征融合:联合特征提取器通过连接(concatenation)操作将局部特征和周围上下文特征结合起来,形成一个综合的特征表示。
2. 增强特征表示:联合后的特征通过批量归一化(Batch Normalization, BN)和参数化的线性单元(Parametric ReLU, PReLU)等操作进行进一步的加工,以增强特征表示的能力。
3. 全局上下文的整合:在某些设计中,联合特征还会与全局上下文特征()结合,以利用整个输入图像的信息来进一步优化特征。
联合特征提取器是上下文引导网络实现其高效语义分割能力的关键连接点,它允许网络在局部精细度和全局上下文间达到平衡.
下图为大家展示了上下文引导网络(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特别适合于资源受限的设备,如移动设备或嵌入式系统。在图中的预测示例中,可以看到网络已经将不同的交通参与者和背景要素成功地分割出来,用不同的颜色标记不同的类别。
全局上下文提取器()在CGNet中的作用是捕获并利用整个输入图像的全局信息,以增强联合特征提取器学习到的特征。以下是它的基本原理:
1. 全局特征汇总:全局上下文提取器通过全局平均池化(Global Average Pooling, GAP)来聚合整个特征图的全局信息。这个步骤产生一个全局特征向量,它捕获了输入图像中每个通道的平均响应。
2. 多层感知机处理:全局特征向量随后通过一个多层感知机(Multilayer Perceptron, MLP)进一步处理。MLP能够学习特征间的复杂非线性关系,进一步细化全局上下文特征。
3. 特征重标定:提取的全局上下文通过缩放层(scale layer)与联合特征结合。这个操作相当于将全局上下文信息作为权重,通道级别地重新标定联合特征,强调有用的特征部分,抑制不重要的特征部分。
4. 自适应性:全局上下文提取器的操作是自适应的,因为提取的全局上下文是根据输入图像生成的,使得网络能够针对不同的图像生成定制化的全局上下文。
5. 提高分割准确性:在消融研究中,使用全局上下文提取器可以提高分割的准确性。这证明了全局上下文在提升模型性能方面的价值。
提供了上下文引导块(Context Guided block)的概览。在图中的全局上下文提取器部分,展示了使用全局平均池化(GAP)来提取全图的上下文信息,然后通过两个全连接层(FC)对这些信息进行进一步的处理。这有助于网络理解整个图像的全局信息,这对于分类图像中的局部区域特别重要,尤其是在这些局部区域的类别可能依赖于全局上下文的情况下。
这些组件共同工作,提高了网络对复杂场景中各种尺度的特征的理解能力,使得CGNet能够更准确地进行语义分割。通过这样的设计,CGNet能够在局部和全局上下文之间建立联系,这对于准确分类图像中的每个像素至关重要。
使用方法看第四章,大家需要仔细看章节四的内容。
- import torch
- import torch.nn as nn
-
- __all__ = ['ContextGuidedBlock_Down', 'RepNCSPELAN4_ContextGuidedBlock']
-
- class ConvBNPReLU(nn.Module):
- def __init__(self, nIn, nOut, kSize, stride=1):
- """
- args:
- nIn: number of input channels
- nOut: number of output channels
- kSize: kernel size
- stride: 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 map
- return: transformed feature map
- """
- output = self.conv(input)
- output = self.bn(output)
- output = self.act(output)
- return output
-
-
- class 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 map
- return: normalized and thresholded feature map
- """
- output = self.bn(input)
- output = self.act(output)
- return output
-
-
- class ConvBN(nn.Module):
- def __init__(self, nIn, nOut, kSize, stride=1):
- """
- args:
- nIn: number of input channels
- nOut: number of output channels
- kSize: kernel size
- stride: 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 map
- return: transformed feature map
- """
- output = self.conv(input)
- output = self.bn(output)
- return output
-
-
- class Conv(nn.Module):
- def __init__(self, nIn, nOut, kSize, stride=1):
- """
- args:
- nIn: number of input channels
- nOut: number of output channels
- kSize: kernel size
- stride: 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 map
- return: transformed feature map
- """
- output = self.conv(input)
- return output
-
-
- class ChannelWiseConv(nn.Module):
- def __init__(self, nIn, nOut, kSize, stride=1):
- """
- Args:
- nIn: number of input channels
- nOut: number of output channels, default (nIn == nOut)
- kSize: kernel size
- stride: 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 map
- return: transformed feature map
- """
- output = self.conv(input)
- return output
-
-
- class DilatedConv(nn.Module):
- def __init__(self, nIn, nOut, kSize, stride=1, d=1):
- """
- args:
- nIn: number of input channels
- nOut: number of output channels
- kSize: kernel size
- stride: optional stride rate for down-sampling
- d: dilation rate
- """
- super().__init__()
- if isinstance(kSize, tuple):
- kSize = kSize[0]
- padding = int((kSize - 1) / 2) * d
- self.conv = nn.Conv2d(nIn, nOut, (kSize, kSize), stride=stride, padding=(padding, padding), bias=False,
- dilation=d)
-
- def forward(self, input):
- """
- args:
- input: input feature map
- return: transformed feature map
- """
- output = self.conv(input)
- return output
-
-
- class ChannelWiseDilatedConv(nn.Module):
- def __init__(self, nIn, nOut, kSize, stride=1, d=1):
- """
- args:
- nIn: number of input channels
- nOut: number of output channels, default (nIn == nOut)
- kSize: kernel size
- stride: optional stride rate for down-sampling
- d: dilation rate
- """
- super().__init__()
- if isinstance(kSize, tuple):
- kSize = kSize[0]
- padding = int((kSize - 1) / 2) * d
- self.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 map
- return: transformed feature map
- """
- output = self.conv(input)
- return output
-
- class 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 * y
-
- class 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 map
- nOut: the channel of output feature map, and nOut=2*nIn
- """
- super().__init__()
-
- nOut = nIn
-
- self.conv1x1 = ConvBNPReLU(nIn, nOut, 3, 2) # size/2, channel: nIn--->nOut
-
- self.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--->nOut
-
- self.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 feature
- joi_feat = self.bn(joi_feat)
- joi_feat = self.act(joi_feat)
- joi_feat = self.reduce(joi_feat) # channel= nOut
-
- output = self.F_glo(joi_feat) # F_glo is employed to refine the joint feature
-
- return output
-
-
- class ContextGuidedBlock(nn.Module):
- def __init__(self, nIn, nOut, dilation_rate=2, reduction=16, add=True):
- """
- args:
- nIn: number of input channels
- nOut: 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 computation
- self.F_loc = ChannelWiseConv(n, n, 3, 1) # local feature
- self.F_sur = ChannelWiseDilatedConv(n, n, 3, 1, dilation_rate) # surrounding context
- self.bn_prelu = BNPReLU(nOut)
- self.add = add
- self.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 version
- if self.add:
- output = input + output
- return output
-
-
- def autopad(k, p=None, d=1): # kernel, padding, dilation
- # Pad to 'same' shape outputs
- if d > 1:
- k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k] # actual kernel-size
- if p is None:
- p = k // 2 if isinstance(k, int) else [x // 2 for x in k] # auto-pad
- return p
-
-
- class Conv(nn.Module):
- # Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)
- default_act = nn.SiLU() # default activation
-
- def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
- super().__init__()
- self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
- self.bn = nn.BatchNorm2d(c2)
- self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
-
- def forward(self, x):
- return self.act(self.bn(self.conv(x)))
-
- def forward_fuse(self, x):
- return self.act(self.conv(x))
-
-
- class RepNBottleneck(nn.Module):
- # Standard bottleneck
- def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5): # ch_in, ch_out, shortcut, kernels, groups, expand
- super().__init__()
- c_ = int(c2 * e) # hidden channels
- self.cv1 = ContextGuidedBlock(c1, c_)
- self.cv2 = Conv(c_, c2, k[1], 1, g=g)
- self.add = shortcut and c1 == c2
-
- def forward(self, x):
- return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
-
-
- class RepNCSP(nn.Module):
- # CSP Bottleneck with 3 convolutions
- def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
- super().__init__()
- c_ = int(c2 * e) # hidden channels
- self.cv1 = Conv(c1, c_, 1, 1)
- self.cv2 = Conv(c1, c_, 1, 1)
- self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2)
- self.m = nn.Sequential(*(RepNBottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
-
- def forward(self, x):
- return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
-
-
- class RepNCSPELAN4_ContextGuidedBlock(nn.Module):
- # csp-elan
- def __init__(self, c1, c2, c3, c4, c5=1): # ch_in, ch_out, number, shortcut, groups, expansion
- super().__init__()
- self.c = c3//2
- self.cv1 = Conv(c1, c3, 1, 1)
- self.cv2 = nn.Sequential(RepNCSP(c3//2, c4, c5), Conv(c4, c4, 3, 1))
- self.cv3 = nn.Sequential(RepNCSP(c4, c4, c5), Conv(c4, c4, 3, 1))
- self.cv4 = Conv(c3+(2*c4), c2, 1, 1)
-
- def forward(self, x):
- y = list(self.cv1(x).chunk(2, 1))
- y.extend((m(y[-1])) for m in [self.cv2, self.cv3])
- return self.cv4(torch.cat(y, 1))
-
- def forward_split(self, x):
- y = list(self.cv1(x).split((self.c, self.c), 1))
- y.extend(m(y[-1]) for m in [self.cv2, self.cv3])
- return self.cv4(torch.cat(y, 1))
-
-
- if __name__ == "__main__":
- # Generating Sample image
- image_size = (1, 64, 240, 240)
- image = torch.rand(*image_size)
-
- # Model
- mobilenet_v3 = RepNCSPELAN4_ContextGuidedBlock(64, 64, 32, 32, 1)
-
- out = mobilenet_v3(image)
- print(out.size())
首先我们找到如下的目录'yolov9-main/models',然后在这个目录下在创建一个新的目录然后这个就是存储改进的仓库,大家可以在这里新建所有的改进的py文件,对应改进的文件名字可以根据你自己的习惯起(不影响任何但是下面导入的时候记住改成你对应的即可),然后将ContextGuided的核心代码复制进去。
然后在新建的目录里面我们在新建一个__init__.py文件(此文件大家只需要建立一个即可),然后我们在里面添加导入我们模块的代码。注意标记一个'.'其作用是标记当前目录。
然后我们找到如下文件''models/yolo.py''在开头的地方导入我们的模块按照如下修改->
(如果你看了我多个改进机制此处只需要添加一个即可,无需重复添加)
注意的添加位置要放在common的导入上面!!!!!
然后我们找到''models/yolo.py''文件中的parse_model方法,按照如下修改->
- elif m in {ContextGuidedBlock_Down}:
- c2 = ch[f]
- args = [c2, *args]
到此就修改完成了,复制下面的ymal文件即可运行。
下面推荐几个版本的yaml文件给大家,大家可以复制进行训练,但是组合用很多具体那种最有效果都不一定,针对不同的数据集效果也不一样,我不可能每一种都做实验,所以我下面推荐了几种我自己认为可能有效果的配合方式,你也可以自己进行组合。
下面的添加ContextGuided是我实验结果的版本,
- # YOLOv9
-
- # parameters
- nc: 80 # number of classes
- depth_multiple: 1 # model depth multiple
- width_multiple: 1 # layer channel multiple
- #activation: nn.LeakyReLU(0.1)
- #activation: nn.ReLU()
-
- # anchors
- anchors: 3
-
- # YOLOv9 backbone
- backbone:
- [
- [-1, 1, Silence, []],
- # conv down
- [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 2-P2/4
- # elan-1 block
- [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 3
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 4-P3/8
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 5
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 6-P4/16
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 7
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 8-P5/32
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 9
- ]
-
- # YOLOv9 head
- head:
- [
- # elan-spp block
- [-1, 1, SPPELAN, [512, 256]], # 10
-
- # up-concat merge
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
- [[-1, 7], 1, Concat, [1]], # cat backbone P4
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 13
-
- # up-concat merge
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
- [[-1, 5], 1, Concat, [1]], # cat backbone P3
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [256, 256, 128, 1]], # 16 (P3/8-small)
-
- # conv-down merge
- [-1, 1, ContextGuidedBlock_Down, []],
- [[-1, 13], 1, Concat, [1]], # cat head P4
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 19 (P4/16-medium)
-
- # conv-down merge
- [-1, 1, ContextGuidedBlock_Down, []],
- [[-1, 10], 1, Concat, [1]], # cat head P5
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 22 (P5/32-large)
-
- # routing
- [5, 1, CBLinear, [[256]]], # 23
- [7, 1, CBLinear, [[256, 512]]], # 24
- [9, 1, CBLinear, [[256, 512, 512]]], # 25
-
- # conv down
- [0, 1, Conv, [64, 3, 2]], # 26-P1/2
-
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 27-P2/4
-
- # elan-1 block
- [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 28
-
- # conv down fuse
- [-1, 1, Conv, [256, 3, 2]], # 29-P3/8
- [[23, 24, 25, -1], 1, CBFuse, [[0, 0, 0]]], # 30
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 31
-
- # conv down fuse
- [-1, 1, ContextGuidedBlock_Down, []], # 32-P4/16
- [[24, 25, -1], 1, CBFuse, [[1, 1]]], # 33
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 34
-
- # conv down fuse
- [-1, 1, ContextGuidedBlock_Down, []], # 35-P5/32
- [[25, -1], 1, CBFuse, [[2]]], # 36
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 37
-
- # detect
- [[31, 34, 37, 16, 19, 22], 1, DualDDetect, [nc]], # DualDDetect(A3, A4, A5, P3, P4, P5)
- ]
添加的版本二具体那种适合你需要大家自己多做实验来尝试。
-
- # YOLOv9
-
- # parameters
- nc: 80 # number of classes
- depth_multiple: 1 # model depth multiple
- width_multiple: 1 # layer channel multiple
- #activation: nn.LeakyReLU(0.1)
- #activation: nn.ReLU()
-
- # anchors
- anchors: 3
-
- # YOLOv9 backbone
- backbone:
- [
- [-1, 1, Silence, []],
- # conv down
- [-1, 1, Conv, [64, 3, 2]], # 1-P1/2
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 2-P2/4
- # elan-1 block
- [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 3
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 4-P3/8
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 5
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 6-P4/16
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 7
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 8-P5/32
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 9
- ]
-
- # YOLOv9 head
- head:
- [
- # elan-spp block
- [-1, 1, SPPELAN, [512, 256]], # 10
-
- # up-concat merge
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
- [[-1, 7], 1, Concat, [1]], # cat backbone P4
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 13
-
- # up-concat merge
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
- [[-1, 5], 1, Concat, [1]], # cat backbone P3
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [256, 256, 128, 1]], # 16 (P3/8-small)
-
- # conv-down merge
- [-1, 1, ContextGuidedBlock_Down, []],
- [[-1, 13], 1, Concat, [1]], # cat head P4
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 19 (P4/16-medium)
-
- # conv-down merge
- [-1, 1, ContextGuidedBlock_Down, []],
- [[-1, 10], 1, Concat, [1]], # cat head P5
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 22 (P5/32-large)
-
- # routing
- [5, 1, CBLinear, [[256]]], # 23
- [7, 1, CBLinear, [[256, 512]]], # 24
- [9, 1, CBLinear, [[256, 512, 512]]], # 25
-
- # conv down
- [0, 1, Conv, [64, 3, 2]], # 26-P1/2
-
- # conv down
- [-1, 1, ContextGuidedBlock_Down, []], # 27-P2/4
-
- # elan-1 block
- [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 28
-
- # conv down fuse
- [-1, 1, Conv, [256, 3, 2]], # 29-P3/8
- [[23, 24, 25, -1], 1, CBFuse, [[0, 0, 0]]], # 30
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 31
-
- # conv down fuse
- [-1, 1, ContextGuidedBlock_Down, []], # 32-P4/16
- [[24, 25, -1], 1, CBFuse, [[1, 1]]], # 33
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 34
-
- # conv down fuse
- [-1, 1, ContextGuidedBlock_Down, []], # 35-P5/32
- [[25, -1], 1, CBFuse, [[2]]], # 36
-
- # elan-2 block
- [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 37
-
- # detect
- [[31, 34, 37, 16, 19, 22], 1, DualDDetect, [nc]], # DualDDetect(A3, A4, A5, P3, P4, P5)
- ]
-
-
大家可以看下面的运行结果和添加的位置所以不存在我发的代码不全或者运行不了的问题大家有问题也可以在评论区评论我看到都会为大家解答(我知道的)。
到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv9改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~
希望大家阅读完以后可以给文章点点赞和评论支持一下这样购买专栏的人越多群内人越多大家交流的机会就更多了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。