一、本文介绍
本文给大家带来的改进机制是最近这几天最新发布的改进机制MFDS-DETR提出的一种HS-FPN结构,其是一种为白细胞检测设计的网络结构,主要用于解决白细胞数据集中的多尺度挑战。它的基本原理包括两个关键部分:特征选择模块和特征融合模块。其可以起到特征选择的作用,非常适合轻量化的读者来使用,其存在二次创新和多次创新的机会,利用该结构参数量下降了约100W,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家,同时本专栏目前改进基于yolov9.yaml文件,后期如果官方放出轻量化版本,专栏内所有改进也会同步更新,请大家放心。
欢迎大家订阅我的专栏一起学习YOLO!
专栏地址:YOLOv9有效涨点专栏-持续复现各种顶会内容-有效涨点-全网改进最全的专栏
目录
一、本文介绍
二、HS-FPN原理
2.1 HS-FPN的基本原理
2.2 SSF模块
三、HS-FPN的核心代码
四、手把手教你添加HS-FPN
4.1 HS-FPN添加步骤
4.1.1 修改一
4.1.2 修改二
4.1.3 修改三
4.1.4 修改四
4.2 HS-FPN的yaml文件和训练截图
4.2.1 HS-FPN的yaml版本一(推荐)
4.2.2 HS-FPN的yaml版本二
4.2 HS-FPN的训练过程截图
五、本文总结
二、HS-FPN原理
论文地址:论文官方链接
代码地址:代码官方链接
2.1 HS-FPN的基本原理
HS-FPN(High-level Screening-feature Fusion Pyramid Networks)是一种为白细胞检测设计的网络结构,主要用于解决白细胞数据集中的多尺度挑战。它的基本原理包括两个关键部分:特征选择模块和特征融合模块。
HS-FPN的结构如下图所示,包括两个主要组成部分:
1. 特征选择模块:该模块利用通道注意力(CA)和维度匹配(DM)机制对不同尺度的特征图进行筛选。通过池化操作(如全局平均池化和全局最大池化)和权重计算,该模块有效地提取了每个通道中的重要信息。
2. 特征融合模块:该模块通过选择性特征融合(SFF)机制将筛选后的低级特征和高级特征结合起来。高级特征扩展后,通过双线性插值或转置卷积进行尺度调整,然后与低级特征融合,从而增强模型对白细胞特征的表达能力。
总的来说,HS-FPN通过这两个模块协同工作,有效地解决了白细胞检测中的多尺度问题,提高了检测的准确性和鲁棒性。
2.2 SSF模块
选择性特征融合(Selective Feature Fusion, SFF)是HS-FPN网络中的一个关键组件,它的主要作用是融合不同尺度的特征图。SFF通过使用高级特征作为权重来过滤低尺度特征中的重要信息。在这个过程中,高级特征经过转置卷积和双线性插值操作进行尺度调整,以匹配低尺度特征的尺寸。然后,利用高级特征作为注意力权重,筛选出低尺度特征中有用的信息。这种融合方法能够有效地结合高级特征的语义信息和低尺度特征的细节信息,从而提高模型在处理多尺度问题时的性能。
下图为大家展示了SFF模块的框架结构:
给定一个输入高级特征和一个输入低尺度特征,高级特征首先使用一个大小为2,核大小为3x3的转置卷积(T-Conv)进行扩展,得到特征大小。
然后,为了统一高级特征和低尺度特征的维度,作者使用双线性插值来向上或向下采样高级特征,得到特征。接下来,使用CA模块将高级特征转换为相应的注意力权重,以过滤低尺度特征,在获得具有相同维度的特征后。
最后,将过滤后的低尺度特征与高级特征融合,以增强模型的特征表示,并得到。方程(1)和(2)说明了特征选择的融合过程:
三、HS-FPN的核心代码
这里的CA对应着官方代码中的ChannelAttention,但是在早期的库里面它在官方里面已经集成了,导入过来可能名字重复从而导致使用的时候报错,我这里给改写成CA了,大家看官方代码的时候需要注意下。
import torch
import torch.nn as nn
import torch.nn.functional as F__all__ = ['CA', 'multiply', 'Add']class Add(nn.Module):# Concatenate a list of tensors along dimensiondef __init__(self, ch=256):super().__init__()def forward(self, x):input1, input2 = x[0], x[1]x = input1 + input2return xclass multiply(nn.Module):def __init__(self):super().__init__()def forward(self, x):x = x[0] * x[1]return xclass CA(nn.Module):def __init__(self, in_planes, ratio = 4, flag=True):super(CA, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.max_pool = nn.AdaptiveMaxPool2d(1)self.conv1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)self.relu = nn.ReLU()self.conv2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)self.flag = flagself.sigmoid = nn.Sigmoid()nn.init.xavier_uniform_(self.conv1.weight)nn.init.xavier_uniform_(self.conv2.weight)def forward(self, x):avg_out = self.conv2(self.relu(self.conv1(self.avg_pool(x))))max_out = self.conv2(self.relu(self.conv1(self.max_pool(x))))out = avg_out + max_outout = self.sigmoid(out) * x if self.flag else self.sigmoid(out)return outclass FeatureSelectionModule(nn.Module):def __init__(self, in_chan, out_chan):super(FeatureSelectionModule, self).__init__()self.conv_atten = nn.Conv2d(in_chan, in_chan, kernel_size=1)self.group_norm1 = nn.GroupNorm(32, in_chan)self.sigmoid = nn.Sigmoid()self.conv = nn.Conv2d(in_chan, out_chan, kernel_size=1)self.group_norm2 = nn.GroupNorm(32, out_chan)nn.init.xavier_uniform_(self.conv_atten.weight)nn.init.xavier_uniform_(self.conv.weight)def forward(self, x):atten = self.sigmoid(self.group_norm1(self.conv_atten(F.avg_pool2d(x, x.size()[2:]))))feat = torch.mul(x, atten)x = x + featfeat = self.group_norm2(self.conv(x))return featif __name__ == "__main__":# Generating Sample imageimage_size = (1, 64, 240, 240)image = torch.rand(*image_size)# Modelmobilenet_v3 = FeatureSelectionModule(64, 64)out = mobilenet_v3(image)print(out.size())
四、手把手教你添加HS-FPN
4.1 HS-FPN添加步骤
4.1.1 修改一
首先我们找到如下的目录'yolov9-main/models',然后在这个目录下在创建一个新的目录然后这个就是存储改进的仓库,大家可以在这里新建所有的改进的py文件,对应改进的文件名字可以根据你自己的习惯起(不影响任何但是下面导入的时候记住改成你对应的即可),然后将HS-FPN 的核心代码复制进去。
4.1.2 修改二
然后在新建的目录里面我们在新建一个__init__.py文件(此文件大家只需要建立一个即可),然后我们在里面添加导入我们模块的代码。注意标记一个'.'其作用是标记当前目录。
4.1.3 修改三
然后我们找到如下文件''models/yolo.py''在开头的地方导入我们的模块按照如下修改->
(如果你看了我多个改进机制此处只需要添加一个即可,无需重复添加)
注意的添加位置要放在common的导入上面!!!!!
4.1.4 修改四
然后我们找到''models/yolo.py''文件中的parse_model方法,按照如下修改->
elif m in {'此处添加大家修改的对应机制即可'}:c2 = ch[f]args = [c2, *args]
elif m is multiply:c2 = ch[f[0]]elif m is Add:c2 = ch[f[-1]]
到此就修改完成了,复制下面的ymal文件即可运行。
4.2 HS-FPN的yaml文件和训练截图
4.2.1 HS-FPN的yaml版本一(推荐)
下面的添加HS-FPN是我实验结果的版本,这个版本为官方一比一复现的版本。
# 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, Conv, [128, 3, 2]], # 2-P2/4# elan-1 block[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 3# conv down[-1, 1, Conv, [256, 3, 2]], # 4-P3/8# elan-2 block[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 5# conv down[-1, 1, Conv, [512, 3, 2]], # 6-P4/16# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 7# conv down[-1, 1, Conv, [512, 3, 2]], # 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[ -1, 1, CA, [ ] ], # 11[ -1, 1, nn.Conv2d, [ 256, 1 ] ], # 12[ -1, 1, RepNCSPELAN4, [256, 256, 128, 1] ], # 13 P5[ 7, 1, CA, [ ] ],[ -1, 1, nn.Conv2d, [ 256, 1 ] ], # 15[ 12, 1, nn.ConvTranspose2d, [ 256, 3, 2, 1, 1 ] ], # 16[ -1, 1, CA, [ 4, False ] ],[ [ -1, 15 ], 1, multiply, [ ] ], # 18[ [ -1, 16 ], 1, Add, [ ] ], # 19[ -1, 1, RepNCSPELAN4, [256, 256, 128, 1]], # 20 P4[ 5, 1, CA, [ ] ], # 21[ -1, 1, nn.Conv2d, [ 256, 1 ] ], # 22[ 16, 1, nn.ConvTranspose2d, [ 256, 3, 2, 1, 1 ] ], # 23[ -1, 1, CA, [ 4, False ] ], # 24[ [ -1, 22 ], 1, multiply, [ ] ], # 25[ [ -1, 23 ], 1, Add, [ ] ], # 26[ -1, 1, RepNCSPELAN4, [256, 256, 128, 1]], # 27 P3# routing + 5[5, 1, CBLinear, [[256]]], # 28[7, 1, CBLinear, [[256, 512]]], # 29[9, 1, CBLinear, [[256, 512, 512]]], # 30# conv down[0, 1, Conv, [64, 3, 2]], # 31-P1/2# conv down[-1, 1, Conv, [128, 3, 2]], # 32-P2/4# elan-1 block[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 33# conv down fuse[-1, 1, Conv, [256, 3, 2]], # 34-P3/8[[28, 29, 30, -1], 1, CBFuse, [[0, 0, 0]]], # 35# elan-2 block[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 36# conv down fuse[-1, 1, Conv, [512, 3, 2]], # 37-P4/16[[29, 30, -1], 1, CBFuse, [[1, 1]]], # 38# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 39# conv down fuse[-1, 1, Conv, [512, 3, 2]], # 40-P5/32[[30, -1], 1, CBFuse, [[2]]], # 41# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 42# detect[[36, 39, 42, 13, 20, 27], 1, DualDDetect, [nc]], # DualDDetect(A3, A4, A5, P3, P4, P5)]
4.2.2 HS-FPN的yaml版本二
添加的版本二具体那种适合你需要大家自己多做实验来尝试,此版本把通道数改回了YOLOv5的版本。
# 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, Conv, [128, 3, 2]], # 2-P2/4# elan-1 block[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 3# conv down[-1, 1, Conv, [256, 3, 2]], # 4-P3/8# elan-2 block[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 5# conv down[-1, 1, Conv, [512, 3, 2]], # 6-P4/16# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 7# conv down[-1, 1, Conv, [512, 3, 2]], # 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[ -1, 1, CA, [ ] ], # 11[ -1, 1, nn.Conv2d, [ 256, 1 ] ], # 12[ -1, 1, RepNCSPELAN4, [256, 256, 128, 1] ], # 13 P5[ 7, 1, CA, [ ] ],[ -1, 1, nn.Conv2d, [ 256, 1 ] ], # 15[ 12, 1, nn.ConvTranspose2d, [ 256, 3, 2, 1, 1 ] ], # 16[ -1, 1, CA, [ 4, False ] ],[ [ -1, 15 ], 1, multiply, [ ] ], # 18[ [ -1, 16 ], 1, Add, [ ] ], # 19[ -1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 20 P4[ 5, 1, CA, [ ] ], # 21[ -1, 1, nn.Conv2d, [ 256, 1 ] ], # 22[ 16, 1, nn.ConvTranspose2d, [ 256, 3, 2, 1, 1 ] ], # 23[ -1, 1, CA, [ 4, False ] ], # 24[ [ -1, 22 ], 1, multiply, [ ] ], # 25[ [ -1, 23 ], 1, Add, [ ] ], # 26[ -1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 27 P3# routing + 5[5, 1, CBLinear, [[256]]], # 28[7, 1, CBLinear, [[256, 512]]], # 29[9, 1, CBLinear, [[256, 512, 512]]], # 30# conv down[0, 1, Conv, [64, 3, 2]], # 31-P1/2# conv down[-1, 1, Conv, [128, 3, 2]], # 32-P2/4# elan-1 block[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 33# conv down fuse[-1, 1, Conv, [256, 3, 2]], # 34-P3/8[[28, 29, 30, -1], 1, CBFuse, [[0, 0, 0]]], # 35# elan-2 block[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 36# conv down fuse[-1, 1, Conv, [512, 3, 2]], # 37-P4/16[[29, 30, -1], 1, CBFuse, [[1, 1]]], # 38# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 39# conv down fuse[-1, 1, Conv, [512, 3, 2]], # 40-P5/32[[30, -1], 1, CBFuse, [[2]]], # 41# elan-2 block[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 42# detect[[36, 39, 42, 13, 20, 27], 1, DualDDetect, [nc]], # DualDDetect(A3, A4, A5, P3, P4, P5)]
4.2 HS-FPN的训练过程截图
大家可以看下面的运行结果和添加的位置所以不存在我发的代码不全或者运行不了的问题大家有问题也可以在评论区评论我看到都会为大家解答(我知道的)。
五、本文总结
到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv9改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~
希望大家阅读完以后可以给文章点点赞和评论支持一下这样购买专栏的人越多群内人越多大家交流的机会就更多了。
专栏地址:YOLOv9有效涨点专栏-持续复现各种顶会内容-有效涨点-全网改进最全的专栏