台州网站建设蓝渊,个人网站怎么做支付功能,哪里卖网站模板,极简wordpress主题、一、本文介绍
本文记录的是利用GnConv优化YOLOv9的目标检测方法研究。YOLOv9在进行目标检测时#xff0c;需要对不同层次的特征进行融合。GnConv可以考虑更高阶的空间交互#xff0c;能够更好地捕捉特征之间的复杂关系#xff0c;从而增强特征融合的效果#xff0c;提高模…一、本文介绍
本文记录的是利用GnConv优化YOLOv9的目标检测方法研究。YOLOv9在进行目标检测时需要对不同层次的特征进行融合。GnConv可以考虑更高阶的空间交互能够更好地捕捉特征之间的复杂关系从而增强特征融合的效果提高模型对目标的检测能力。 文章目录 一、本文介绍二、HorNet原理介绍2.1、GnConv设计原理2.2、GnConv计算公式2.3、优势 三、GnConv的实现代码四、添加步骤4.1 修改common.py4.1.1 创新模块⭐ 4.2 修改yolo.py 五、yaml模型文件5.1 模型改进⭐ 六、成功运行结果 二、HorNet原理介绍
HorNet 利用递归门控卷积实现高效高阶空间交互
GnConvRecursive Gated Convolution递归门控卷积是论文中提出的一种高效操作用于实现长期和高阶空间交互其设计原理、计算公式和优势如下
2.1、GnConv设计原理
输入自适应交互与门控卷积Vision Transformer的成功主要依赖于对视觉数据中空间交互的适当建模与简单使用静态卷积核聚合相邻特征的CNN不同Vision Transformer应用多头自注意力来动态生成权重以混合空间标记但自注意力关于输入大小的二次复杂度在很大程度上阻碍了其应用尤其是在需要更高分辨率特征图的下游任务中。在这项工作中作者寻求一种更有效和高效的方法来执行空间交互使用门控卷积gConv来实现输入自适应的空间混合。高阶交互与递归门控在通过gConv实现了高效的一阶空间交互后作者设计了递归门控卷积GnConv来通过引入高阶交互进一步增强模型容量。具体来说首先使用多个线性投影层 ϕ i n \phi_{in} ϕin获得一组投影特征 p 0 p_0 p0和 q k q_k qk然后通过递归的方式执行门控卷积 p k 1 f k ( q k ) ⊙ g k ( p k ) / α p_{k 1} f_k(q_k) \odot g_k(p_k) / \alpha pk1fk(qk)⊙gk(pk)/α其中 f k f_k fk是一组深度卷积层 g k g_k gk用于匹配不同阶的维度最后将最后一次递归步骤的输出 q n q_n qn送入投影层 ϕ o u t \phi_{out} ϕout以获得 g n C o n v g^{n}Conv gnConv的结果。从递归公式可以看出 p k p_k pk的交互阶数在每一步后都会增加1因此 g n C o n v gnConv gnConv实现了 n n n阶空间交互。大核卷积与长期交互为了使 G n C o n v GnConv GnConv能够捕捉长期交互作者采用了两种实现方式来处理深度卷积 f f f 7×7卷积7×7是Swin Transformers和ConvNext的默认窗口/核大小研究表明该核大小在ImageNet分类和各种下游任务中产生良好性能因此作者遵循此配置以公平地与代表性的Vision Transformer和现代CNN进行比较。全局滤波器GFGF层通过将频域特征与可学习的全局滤波器相乘相当于在空间域中进行具有全局核大小和循环填充的卷积。作者使用了GF层的修改版本即处理一半的通道与全局滤波器相乘另一半与3×3深度卷积相乘并仅在后期阶段使用GF层以保留更多局部细节。
2.2、GnConv计算公式
门控卷积输出
令 x ∈ R H W × C x \in \mathbb{R}^{H W \times C} x∈RHW×C为输入特征门控卷积 y g C o n v ( x ) y gConv(x) ygConv(x)的输出可写为 [ p 0 H W × C , q 0 H W × C ] ϕ i n ( x ) ∈ R H W × 2 C , y f ( q 0 ) ⊙ p 0 ∈ R H W × C , y ϕ o u t ( p 1 ) ∈ R H W × C , \begin{array}{r} {\left[p_{0}^{H W \times C}, q_{0}^{H W \times C}\right]\phi_{in }(x) \in \mathbb{R}^{H W \times 2 C},} \\ y f\left(q_{0}\right) \odot p_{0} \in \mathbb{R}^{H W \times C}, \\ y \phi_{out }\left(p_{1}\right) \in \mathbb{R}^{H W \times C}, \end{array} [p0HW×C,q0HW×C]ϕin(x)∈RHW×2C,yf(q0)⊙p0∈RHW×C,yϕout(p1)∈RHW×C,
其中 ϕ i n \phi_{in} ϕin和 ϕ o u t \phi_{out} ϕout是线性投影层以执行通道混合 f f f是深度卷积。注意到 p 1 ( i , c ) ∑ j ∈ Ω i w i → j c q 0 ( j , c ) p 0 ( i , c ) p_{1}^{(i, c)}\sum_{j \in \Omega_{i}} w_{i \to j}^{c} q_{0}^{(j, c)} p_{0}^{(i, c)} p1(i,c)∑j∈Ωiwi→jcq0(j,c)p0(i,c)其中 Ω i \Omega_{i} Ωi是以为 i i i中心的局部窗口 w i → j w_{i \to j} wi→j代表卷积权重。
递归门控卷积 [ p 0 H W × C 0 , q 0 H W × C 0 , … , q n − 1 H W × C n − 1 ] ϕ i n ( x ) ∈ R H W × ( C 0 ∑ 0 ≤ k ≤ n − 1 C k ) , p k 1 f k ( q k ) ⊙ g k ( p k ) / α , k 0 , 1 , … , n − 1 , \begin{aligned} \left[p_{0}^{H W \times C_{0}}, q_{0}^{H W \times C_{0}}, \ldots, q_{n - 1}^{H W \times C_{n - 1}}\right]\phi_{in }(x) \in \mathbb{R}^{H W \times\left(C_{0} \sum_{0 \leq k \leq n - 1} C_{k}\right)}, \\ p_{k 1} f_{k}\left(q_{k}\right) \odot g_{k}\left(p_{k}\right) / \alpha, k 0, 1, \ldots, n - 1, \end{aligned} [p0HW×C0,q0HW×C0,…,qn−1HW×Cn−1]ϕin(x)∈RHW×(C0∑0≤k≤n−1Ck),pk1fk(qk)⊙gk(pk)/α,k0,1,…,n−1, 其中 g k g_{k} gk的定义为 g k { I d e n t i t y , k 0 L i n e a r ( C k − 1 , C k ) , 1 ≤ k ≤ n − 1 g_{k}\begin{cases}Identity, k 0 \\Linear\left(C_{k - 1}, C_{k}\right), 1 \leq k \leq n - 1\end{cases} gk{Identity,Linear(Ck−1,Ck),k01≤k≤n−1。计算复杂度总FLOPs为 F L O P s ( g n C o n v ) H W C ( 2 K 2 11 3 × C 2 ) FLOPs\left(g^{n}Conv\right) HW C\left(2K^{2} \frac{11}{3} \times C 2\right) FLOPs(gnConv)HWC(2K2311×C2)其中 K K K是深度卷积的核大小。 2.3、优势
高效基于卷积的实现避免了自注意力的二次复杂度。在执行空间交互时逐渐增加通道宽度的设计也使能够以有限的复杂度实现更高阶的交互。可扩展将自注意力中的二阶交互扩展到任意阶以进一步提高建模能力。由于不对空间卷积的类型做假设因此(gnConv)与各种核大小和空间混合策略兼容。平移等变性完全继承了标准卷积的平移等变性这为主要视觉任务引入了有益的归纳偏差并避免了局部注意力带来的不对称性。 论文https://arxiv.org/pdf/2207.14284 源码https://github.com/raoyongming/HorNet 三、GnConv的实现代码
GnConv模块的实现代码如下 def get_dwconv(dim, kernel, bias):return nn.Conv2d(dim, dim, kernel_sizekernel, padding(kernel-1)//2 ,biasbias, groupsdim)class gnConv(nn.Module):def __init__(self, dim, order5, gflayerNone, h14, w8, s1.0):super().__init__()self.order orderself.dims [dim // 2 ** i for i in range(order)]self.dims.reverse()self.proj_in nn.Conv2d(dim, 2*dim, 1)if gflayer is None:self.dwconv get_dwconv(sum(self.dims), 7, True)else:self.dwconv gflayer(sum(self.dims), hh, ww)self.proj_out nn.Conv2d(dim, dim, 1)self.pws nn.ModuleList([nn.Conv2d(self.dims[i], self.dims[i1], 1) for i in range(order-1)])self.scale sdef forward(self, x, maskNone, dummyFalse):# B, C, H, W x.shape gnconv [512]by iscyy/airfused_x self.proj_in(x)pwa, abc torch.split(fused_x, (self.dims[0], sum(self.dims)), dim1)dw_abc self.dwconv(abc) * self.scaledw_list torch.split(dw_abc, self.dims, dim1)x pwa * dw_list[0]for i in range(self.order -1):x self.pws[i](x) * dw_list[i1]x self.proj_out(x)return x四、添加步骤
4.1 修改common.py
此处需要修改的文件是models/common.py
common.py中定义了网络结构的通用模块我们想要加入新的模块就只需要将模块代码放到这个文件内即可。
4.1.1 创新模块⭐
模块改进方法1️⃣先加入gnConv模块。 将上方的实现代码粘贴到common.py文件夹下gnConv模块添加后如下 2️⃣基于gnConv的RepNCSPELAN4。
第二种改进方法是对YOLOv9中的RepNCSPELAN4模块进行改进。将gnConv模块与 RepNCSPELAN4 结合后替换其中的普通卷积可以使YOLOv9实现更高阶的空间交互更好地捕捉特征之间的复杂关系从而提高模型的建模能力。
改进代码如下
class GnRepNCSPELAN4(nn.Module):# csp-elandef __init__(self, c1, c2, c3, c4, c51): # ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()self.c c3//2self.cv1 Conv(c1, c3, 1, 1)self.cv2 nn.Sequential(RepNCSP(c3//2, c4, c5), gnConv(c4))self.cv3 nn.Sequential(RepNCSP(c4, c4, c5), gnConv(c4))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))注意❗在4.2小节中的yolo.py文件中需要声明的模块名称为gnConv和GnRepNCSPELAN4。
4.2 修改yolo.py
此处需要修改的文件是models/yolo.py
yolo.py用于函数调用我们只需要将common.py中定义的新的模块名添加到parse_model函数下即可。
gnConv模块以及GnRepNCSPELAN4模块添加后如下 五、yaml模型文件
5.1 模型改进⭐
在代码配置完成后配置模型的YAML文件。
此处以models/detect/yolov9-c.yaml为例在同目录下创建一个用于自己数据集训练的模型文件yolov9-c-GnRepNCSPELAN4.yaml。
将yolov9-c.yaml中的内容复制到yolov9-c-GnRepNCSPELAN4.yaml文件下修改nc数量等于自己数据中目标的数量。 在骨干网络中将四个RepNCSPELAN4模块替换成GnRepNCSPELAN4模块。
# YOLOv9# parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # 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, Conv, [128, 3, 2]], # 2-P2/4# elan-1 block[-1, 1, GnRepNCSPELAN4, [256, 128, 64, 1]], # 3# avg-conv down[-1, 1, ADown, [256]], # 4-P3/8# elan-2 block[-1, 1, GnRepNCSPELAN4, [512, 256, 128, 1]], # 5# avg-conv down[-1, 1, ADown, [512]], # 6-P4/16# elan-2 block[-1, 1, GnRepNCSPELAN4, [512, 512, 256, 1]], # 7# avg-conv down[-1, 1, ADown, [512]], # 8-P5/32# elan-2 block[-1, 1, GnRepNCSPELAN4, [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)# avg-conv-down merge[-1, 1, ADown, [256]],[[-1, 13], 1, Concat, [1]], # cat head P4# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 19 (P4/16-medium)# avg-conv-down merge[-1, 1, ADown, [512]],[[-1, 10], 1, Concat, [1]], # cat head P5# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 22 (P5/32-large)# multi-level reversible auxiliary branch# 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, Conv, [128, 3, 2]], # 27-P2/4# elan-1 block[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 28# avg-conv down fuse[-1, 1, ADown, [256]], # 29-P3/8[[23, 24, 25, -1], 1, CBFuse, [[0, 0, 0]]], # 30 # elan-2 block[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 31# avg-conv down fuse[-1, 1, ADown, [512]], # 32-P4/16[[24, 25, -1], 1, CBFuse, [[1, 1]]], # 33 # elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 34# avg-conv down fuse[-1, 1, ADown, [512]], # 35-P5/32[[25, -1], 1, CBFuse, [[2]]], # 36# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 37# detection head# detect[[31, 34, 37, 16, 19, 22], 1, DualDDetect, [nc]], # DualDDetect(A3, A4, A5, P3, P4, P5)] 六、成功运行结果
分别打印网络模型可以看到GnRepNCSPELAN4模块已经加入到模型中并可以进行训练了。
yolov9-c-GnRepNCSPELAN4 from n params module arguments 0 -1 1 0 models.common.Silence [] 1 -1 1 1856 models.common.Conv [3, 64, 3, 2] 2 -1 1 73984 models.common.Conv [64, 128, 3, 2] 3 -1 1 212864 models.common.RepNCSPELAN4 [128, 256, 128, 64, 1] 4 -1 1 164352 models.common.ADown [256, 256] 5 -1 1 847616 models.common.RepNCSPELAN4 [256, 512, 256, 128, 1] 6 -1 1 656384 models.common.ADown [512, 512] 7 -1 1 2857472 models.common.RepNCSPELAN4 [512, 512, 512, 256, 1] 8 -1 1 656384 models.common.ADown [512, 512] 9 -1 1 2209152 models.common.GnRepNCSPELAN4 [512, 512, 512, 256, 1]
10 -1 1 656896 models.common.SPPELAN [512, 512, 256]
11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, nearest]
12 [-1, 7] 1 0 models.common.Concat [1]
13 -1 1 3119616 models.common.RepNCSPELAN4 [1024, 512, 512, 256, 1]
14 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, nearest]
15 [-1, 5] 1 0 models.common.Concat [1]
16 -1 1 912640 models.common.RepNCSPELAN4 [1024, 256, 256, 128, 1]
17 -1 1 164352 models.common.ADown [256, 256]
18 [-1, 13] 1 0 models.common.Concat [1]
19 -1 1 2988544 models.common.RepNCSPELAN4 [768, 512, 512, 256, 1]
20 -1 1 656384 models.common.ADown [512, 512]
21 [-1, 10] 1 0 models.common.Concat [1]
22 -1 1 3119616 models.common.RepNCSPELAN4 [1024, 512, 512, 256, 1]
23 5 1 131328 models.common.CBLinear [512, [256]]
24 7 1 393984 models.common.CBLinear [512, [256, 512]]
25 9 1 656640 models.common.CBLinear [512, [256, 512, 512]]
26 0 1 1856 models.common.Conv [3, 64, 3, 2]
27 -1 1 73984 models.common.Conv [64, 128, 3, 2]
28 -1 1 212864 models.common.RepNCSPELAN4 [128, 256, 128, 64, 1]
29 -1 1 164352 models.common.ADown [256, 256]
30 [23, 24, 25, -1] 1 0 models.common.CBFuse [[0, 0, 0]]
31 -1 1 847616 models.common.RepNCSPELAN4 [256, 512, 256, 128, 1]
32 -1 1 656384 models.common.ADown [512, 512]
33 [24, 25, -1] 1 0 models.common.CBFuse [[1, 1]]
34 -1 1 2857472 models.common.RepNCSPELAN4 [512, 512, 512, 256, 1]
35 -1 1 656384 models.common.ADown [512, 512]
36 [25, -1] 1 0 models.common.CBFuse [[2]]
37 -1 1 2857472 models.common.RepNCSPELAN4 [512, 512, 512, 256, 1]
38[31, 34, 37, 16, 19, 22] 1 21725312 DualDDetect [80, [512, 512, 512, 256, 512, 512]]
yolov9-c-GnRepNCSPELAN4 summary: 974 layers, 50533760 parameters, 50533728 gradients, 239.4 GFLOPs