网站开发 工作职责,济南网站建设公司晟创未来,网站做跳转教程,免费制作链接的软件一、本文介绍
本文给大家带来的改进机制是Damo-YOLO的RepGFPN#xff08;重参数化泛化特征金字塔网络#xff09;#xff0c;利用其优化YOLOv8的Neck部分#xff0c;可以在不影响计算量的同时大幅度涨点#xff08;亲测在小目标和大目标检测的数据集上效果均表现良好涨点…一、本文介绍
本文给大家带来的改进机制是Damo-YOLO的RepGFPN重参数化泛化特征金字塔网络利用其优化YOLOv8的Neck部分可以在不影响计算量的同时大幅度涨点亲测在小目标和大目标检测的数据集上效果均表现良好涨点幅度超级高。RepGFPN不同于以往提出的改进模块其更像是一种结构一种思想(一种处理事情的方法)RepGFPN相对于BiFPN和之前的FPN均有一定程度上的优化效果。
适用检测目标所有的目标检测均有一定的提点
推荐指数⭐⭐⭐⭐⭐ 专栏回顾YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备 效果回顾展示-
图片分析-在我的数据集上大家可以看到mAP50大概增长了0.12左右这个涨点幅度是非常的高了以及同时该模块是有二次创新的机会的后期我会在接下来的文章进行二次创新希望大家能够尽早关注我的专栏。 目录
一、本文介绍
二、GFPN的框架原理
编辑
三、GFPN的核心代码
四、手把手教你添加GFPN
4.1 修改一
4.2 修改二
五、GFPN的yaml文件
六、成功运行的截图
六、本文总结 二、GFPN的框架原理 官方论文地址 官方论文地址
官方代码地址 官方代码地址 RepGFPN重参数化泛化特征金字塔网络是DAMO-YOLO框架中用于实时目标检测的新方法。其主要主要原理是RepGFPN改善了用于目标检测的特征金字塔网络FPN的概念更高效地融合多尺度特征对于捕捉高层语义和低层空间细节至关重要。
其主要改进机制包括-
不同尺度通道它为不同尺度的特征图采用不同的通道维度优化了计算资源下的性能。优化的皇后融合机制该方法通过修改的皇后融合机制增强了特征交互通过去除额外的上采样操作减少延迟。整合CSPNet和ELAN它结合了CSPNet和高效层聚合网络ELAN以及重参数化改善了特征融合而不显著增加计算需求。 总结RepGFPN更像是一种结构一种思想其中的模块我们是可以用其它的机制替换的。 下面的图片是Damo-YOLO的网络结构图其中我用红框标出来的部分就是RepGFPN的路径聚合图。 根据图片我们来说一下GFPN(重参数化特征金字塔网络)作为“颈部也就是YOLOv8中的neck用于优化和融合高层语义和低层空间特征。
在左上角的融合块Fusion Block中我们可以看到反复出现的结构单元它们由多个1x1卷积一个3x3卷积组成这些卷积后面通常跟着批量归一化BN和激活函数Act。这个复合结构在训练时和推理时有所不同这是通过“简化Rep 3x3”结构来实现的它在训练时使用3x3卷积而在推理时则简化为1x1卷积以提高效率(现在很多结构都使用在何种思想训练时候用复杂的模块推理时换为简单的模块这在大家自己的改进中也可以是一种思想)。 三、GFPN的核心代码
下面的代码是GFPN的核心代码我们将其复制导ultralytics/nn/modules目录下在其中创建一个文件我这里起名为GFPN然后粘贴进去其余使用方式看章节四。
import torch
import torch.nn as nn
import numpy as npclass swish(nn.Module):def forward(self, x):return x * torch.sigmoid(x)def autopad(k, pNone, d1): # kernel, padding, dilationPad 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-sizeif p is None:p k // 2 if isinstance(k, int) else [x // 2 for x in k] # auto-padreturn pclass Conv(nn.Module):Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation).default_act swish() # default activationdef __init__(self, c1, c2, k1, s1, pNone, g1, d1, actTrue):Initialize Conv layer with given arguments including activation.super().__init__()self.conv nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groupsg, dilationd, biasFalse)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):Apply convolution, batch normalization and activation to input tensor.return self.act(self.bn(self.conv(x)))def forward_fuse(self, x):Perform transposed convolution of 2D data.return self.act(self.conv(x))class RepConv(nn.Module):default_act swish() # default activationdef __init__(self, c1, c2, k3, s1, p1, g1, d1, actTrue, bnFalse, deployFalse):Initializes Light Convolution layer with inputs, outputs optional activation function.super().__init__()assert k 3 and p 1self.g gself.c1 c1self.c2 c2self.act self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()self.bn nn.BatchNorm2d(num_featuresc1) if bn and c2 c1 and s 1 else Noneself.conv1 Conv(c1, c2, k, s, pp, gg, actFalse)self.conv2 Conv(c1, c2, 1, s, p(p - k // 2), gg, actFalse)def forward_fuse(self, x):Forward process.return self.act(self.conv(x))def forward(self, x):Forward process.id_out 0 if self.bn is None else self.bn(x)return self.act(self.conv1(x) self.conv2(x) id_out)def get_equivalent_kernel_bias(self):Returns equivalent kernel and bias by adding 3x3 kernel, 1x1 kernel and identity kernel with their biases.kernel3x3, bias3x3 self._fuse_bn_tensor(self.conv1)kernel1x1, bias1x1 self._fuse_bn_tensor(self.conv2)kernelid, biasid self._fuse_bn_tensor(self.bn)return kernel3x3 self._pad_1x1_to_3x3_tensor(kernel1x1) kernelid, bias3x3 bias1x1 biasiddef _pad_1x1_to_3x3_tensor(self, kernel1x1):Pads a 1x1 tensor to a 3x3 tensor.if kernel1x1 is None:return 0else:return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])def _fuse_bn_tensor(self, branch):Generates appropriate kernels and biases for convolution by fusing branches of the neural network.if branch is None:return 0, 0if isinstance(branch, Conv):kernel branch.conv.weightrunning_mean branch.bn.running_meanrunning_var branch.bn.running_vargamma branch.bn.weightbeta branch.bn.biaseps branch.bn.epselif isinstance(branch, nn.BatchNorm2d):if not hasattr(self, id_tensor):input_dim self.c1 // self.gkernel_value np.zeros((self.c1, input_dim, 3, 3), dtypenp.float32)for i in range(self.c1):kernel_value[i, i % input_dim, 1, 1] 1self.id_tensor torch.from_numpy(kernel_value).to(branch.weight.device)kernel self.id_tensorrunning_mean branch.running_meanrunning_var branch.running_vargamma branch.weightbeta branch.biaseps branch.epsstd (running_var eps).sqrt()t (gamma / std).reshape(-1, 1, 1, 1)return kernel * t, beta - running_mean * gamma / stddef fuse_convs(self):Combines two convolution layers into a single layer and removes unused attributes from the class.if hasattr(self, conv):returnkernel, bias self.get_equivalent_kernel_bias()self.conv nn.Conv2d(in_channelsself.conv1.conv.in_channels,out_channelsself.conv1.conv.out_channels,kernel_sizeself.conv1.conv.kernel_size,strideself.conv1.conv.stride,paddingself.conv1.conv.padding,dilationself.conv1.conv.dilation,groupsself.conv1.conv.groups,biasTrue).requires_grad_(False)self.conv.weight.data kernelself.conv.bias.data biasfor para in self.parameters():para.detach_()self.__delattr__(conv1)self.__delattr__(conv2)if hasattr(self, nm):self.__delattr__(nm)if hasattr(self, bn):self.__delattr__(bn)if hasattr(self, id_tensor):self.__delattr__(id_tensor)class BasicBlock_3x3_Reverse(nn.Module):def __init__(self,ch_in,ch_hidden_ratio,ch_out,shortcutTrue):super(BasicBlock_3x3_Reverse, self).__init__()assert ch_in ch_outch_hidden int(ch_in * ch_hidden_ratio)self.conv1 Conv(ch_hidden, ch_out, 3, s1)self.conv2 RepConv(ch_in, ch_hidden, 3, s1)self.shortcut shortcutdef forward(self, x):y self.conv2(x)y self.conv1(y)if self.shortcut:return x yelse:return yclass SPP(nn.Module):def __init__(self,ch_in,ch_out,k,pool_size):super(SPP, self).__init__()self.pool []for i, size in enumerate(pool_size):pool nn.MaxPool2d(kernel_sizesize,stride1,paddingsize // 2,ceil_modeFalse)self.add_module(pool{}.format(i), pool)self.pool.append(pool)self.conv Conv(ch_in, ch_out, k)def forward(self, x):outs [x]for pool in self.pool:outs.append(pool(x))y torch.cat(outs, axis1)y self.conv(y)return yclass CSPStage(nn.Module):def __init__(self,ch_in,ch_out,n,block_fnBasicBlock_3x3_Reverse,ch_hidden_ratio1.0,actsilu,sppFalse):super(CSPStage, self).__init__()split_ratio 2ch_first int(ch_out // split_ratio)ch_mid int(ch_out - ch_first)self.conv1 Conv(ch_in, ch_first, 1)self.conv2 Conv(ch_in, ch_mid, 1)self.convs nn.Sequential()next_ch_in ch_midfor i in range(n):if block_fn BasicBlock_3x3_Reverse:self.convs.add_module(str(i),BasicBlock_3x3_Reverse(next_ch_in,ch_hidden_ratio,ch_mid,shortcutTrue))else:raise NotImplementedErrorif i (n - 1) // 2 and spp:self.convs.add_module(spp, SPP(ch_mid * 4, ch_mid, 1, [5, 9, 13]))next_ch_in ch_midself.conv3 Conv(ch_mid * n ch_first, ch_out, 1)def forward(self, x):y1 self.conv1(x)y2 self.conv2(x)mid_out [y1]for conv in self.convs:y2 conv(y2)mid_out.append(y2)y torch.cat(mid_out, axis1)y self.conv3(y)return y 四、手把手教你添加GFPN
上一节我们给出了GFPN的核心代码这一节会教大家如何添加GFPN其实GFPN的添加方式和C2f是一模一样的非常简单只需要修改几处即可。
同时给大家推荐我其它位置的修改教程的链接当然你只使用本文的基础用本文的修改教程即可。 添加教程-YOLOv8改进 | 如何在网络结构中添加注意力机制、C2f、卷积、Neck、检测头 4.1 修改一
我们找到如下文件ultralytics/nn/tasks.py。在其中的开头我们导入我们的模块。 4.2 修改二
我们找到parse_model的函数在其中进行修改大约在700行修改如下的两处即可。 五、GFPN的yaml文件
其实最主要的是yaml文件的配置来复现Damo-YOLO的Neck部分大家复制粘贴我的yaml文件运行即可。
# Ultralytics YOLO , AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. modelyolov8n.yaml will call yolov8.yaml with scale n# [depth, width, max_channels]n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPss: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPsm: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPsl: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPsx: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs# YOLOv8.0n backbone
backbone:# [from, repeats, module, args]- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4- [-1, 3, C2f, [128, True]]- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]] # 9# DAMO-YOLO GFPN Head
head:- [-1, 1, Conv, [512, 1, 1]] # 10- [6, 1, Conv, [512, 3, 2]]- [[-1, 10], 1, Concat, [1]]- [-1, 3, CSPStage, [512]] # 13- [-1, 1, nn.Upsample, [None, 2, nearest]] #14- [4, 1, Conv, [256, 3, 2]] # 15- [[14, -1, 6], 1, Concat, [1]]- [-1, 3, CSPStage, [512]] # 17- [-1, 1, nn.Upsample, [None, 2, nearest]]- [[-1, 4], 1, Concat, [1]]- [-1, 3, CSPStage, [256]] # 20- [-1, 1, Conv, [256, 3, 2]]- [[-1, 17], 1, Concat, [1]]- [-1, 3, CSPStage, [512]] # 23- [17, 1, Conv, [256, 3, 2]] # 24- [23, 1, Conv, [256, 3, 2]] # 25- [[13, 24, -1], 1, Concat, [1]]- [-1, 3, CSPStage, [1024]] # 27- [[20, 23, 27], 1, Detect, [nc]] # Detect(P3, P4, P5) 六、成功运行的截图
下面是成功运行的截图确保我添加的机制是可以完美运行的给大家证明。 六、本文总结
到此本文的正式分享内容就结束了在这里给大家推荐我的YOLOv8改进有效涨点专栏本专栏目前为新开的平均质量分98分后期我会根据各种最新的前沿顶会进行论文复现也会对一些老的改进机制进行补充目前本专栏免费阅读(暂时大家尽早关注不迷路~)如果大家觉得本文帮助到你了订阅本专栏关注后续更多的更新~ 专栏回顾YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备