YOLOv9改进策略:注意力机制 | 用于微小目标检测的上下文增强和特征细化网络ContextAggregation,助力小目标检测,暴力涨点
💡💡💡本文改进内容:用于微小目标检测的上下文增强和特征细化网络ContextAggregation,助力小目标检测
yolov9-c-ContextAggregation summary: 971 layers, 51002153 parameters, 51002121 gradients, 238.9 GFLOPs
改进结构图如下:
YOLOv9魔术师专栏
☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️ ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️
包含注意力机制魔改、卷积魔改、检测头创新、损失&IOU优化、block优化&多层特征融合、 轻量级网络设计、24年最新顶会改进思路、原创自研paper级创新等
☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️
✨✨✨ 新开专栏暂定免费限时开放,后续每月调价一次✨✨✨
🚀🚀🚀 本项目持续更新 | 更新完结保底≥50+ ,冲刺100+🚀🚀🚀
🍉🍉🍉 联系WX: AI_CV_0624 欢迎交流!🍉🍉🍉
YOLOv9魔改:注意力机制、检测头、blcok魔改、自研原创等
YOLOv9魔术师
💡💡💡全网独家首发创新(原创),适合paper !!!
💡💡💡 2024年计算机视觉顶会创新点适用于Yolov5、Yolov7、Yolov8等各个Yolo系列,专栏文章提供每一步步骤和源码,轻松带你上手魔改网络 !!!
💡💡💡重点:通过本专栏的阅读,后续你也可以设计魔改网络,在网络不同位置(Backbone、head、detect、loss等)进行魔改,实现创新!!!
1.YOLOv9原理介绍
论文: 2402.13616.pdf (arxiv.org)
代码:GitHub - WongKinYiu/yolov9: Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information摘要: 如今的深度学习方法重点关注如何设计最合适的目标函数,从而使得模型的预测结果能够最接近真实情况。同时,必须设计一个适当的架构,可以帮助获取足够的信息进行预测。然而,现有方法忽略了一个事实,即当输入数据经过逐层特征提取和空间变换时,大量信息将会丢失。因此,YOLOv9 深入研究了数据通过深度网络传输时数据丢失的重要问题,即信息瓶颈和可逆函数。作者提出了可编程梯度信息(programmable gradient information,PGI)的概念,来应对深度网络实现多个目标所需要的各种变化。PGI 可以为目标任务计算目标函数提供完整的输入信息,从而获得可靠的梯度信息来更新网络权值。此外,研究者基于梯度路径规划设计了一种新的轻量级网络架构,即通用高效层聚合网络(Generalized Efficient Layer Aggregation Network,GELAN)。该架构证实了 PGI 可以在轻量级模型上取得优异的结果。研究者在基于 MS COCO 数据集的目标检测任务上验证所提出的 GELAN 和 PGI。结果表明,与其他 SOTA 方法相比,GELAN 仅使用传统卷积算子即可实现更好的参数利用率。对于 PGI 而言,它的适用性很强,可用于从轻型到大型的各种模型。我们可以用它来获取完整的信息,从而使从头开始训练的模型能够比使用大型数据集预训练的 SOTA 模型获得更好的结果。对比结果如图1所示。
YOLOv9框架图
1.1 YOLOv9框架介绍
YOLOv9各个模型介绍
2.Context Aggregation介绍
论文:https://arxiv.org/abs/2106.01401
摘要
卷积神经网络(CNNs)在计算机视觉中无处不在,具有无数有效和高效的变化。最近,Container——最初是在自然语言处理中引入的——已经越来越多地应用于计算机视觉。早期的用户继续使用CNN的骨干,最新的网络是端到端无CNN的Transformer解决方案。最近一个令人惊讶的发现表明,一个简单的基于MLP的解决方案,没有任何传统的卷积或Transformer组件,可以产生有效的视觉表示。虽然CNN、Transformer和MLP-Mixers可以被视为完全不同的架构,但我们提供了一个统一的视图,表明它们实际上是在神经网络堆栈中聚合空间上下文的更通用方法的特殊情况。我们提出了Container(上下文聚合网络),一个用于多头上下文聚合的通用构建块,它可以利用Container的长期交互作用,同时仍然利用局部卷积操作的诱导偏差,导致更快的收敛速度,这经常在CNN中看到。我们的Container架构在ImageNet上使用22M参数实现了82.7%的Top-1精度,比DeiT-Small提高了2.8,并且可以在短短200个时代收敛到79.9%的Top-1精度。比起相比的基于Transformer的方法不能很好地扩展到下游任务依赖较大的输入图像的分辨率,我们高效的网络,名叫CONTAINER-LIGHT,可以使用在目标检测和分割网络如DETR实例,RetinaNet和Mask-RCNN获得令人印象深刻的检测图38.9,43.8,45.1和掩码mAP为41.3,与具有可比较的计算和参数大小的ResNet-50骨干相比,分别提供了6.6、7.3、6.9和6.6 pts的较大改进。与DINO框架下的DeiT相比,我们的方法在自监督学习方面也取得了很好的效果。
仅需22M参数量,所提CONTAINER在ImageNet数据集取得了82.7%的的top1精度,以2.8%优于DeiT-Small;此外仅需200epoch即可达到79.9%的top1精度。不用于难以扩展到下游任务的Transformer方案(因为需要更高分辨率),该方案CONTAINER-LIGHT可以嵌入到DETR、RetinaNet以及Mask-RCNN等架构中用于目标检测、实例分割任务并分别取得了6.6,7.6,6.9指标提升。
提供了一个统一视角表明:它们均是更广义方案下通过神经网络集成空间上下文信息的特例。我们提出了CONTAINER(CONText AggregatIon NEtwoRK),一种用于多头上下文集成(Context Aggregation)的广义构建模块 。
本文有以下几点贡献:
- 提出了关于主流视觉架构的一个统一视角;
- 提出了一种新颖的模块CONTAINER,它通过可学习参数和响应的架构混合使用了静态与动态关联矩阵(Affinity Matrix),在图像分类任务中表现出了很强的结果;
- 提出了一种高效&有效的扩展CONTAINER-LIGHT在检测与分割方面取得了显著的性能提升。
3.Context Aggregation加入到YOLOv9
3.1新建py文件,路径为models/attention/attention.py
###################### ContextAggregation #### START by AI&CV ###############################
from mmcv.cnn import ConvModule
from mmengine.model import caffe2_xavier_init, constant_init
class ContextAggregation(nn.Module):
"""
Context Aggregation Block.
Args:
in_channels (int): Number of input channels.
reduction (int, optional): Channel reduction ratio. Default: 1.
conv_cfg (dict or None, optional): Config dict for the convolution
layer. Default: None.
"""
def __init__(self, in_channels, reduction=1):
super(ContextAggregation, self).__init__()
self.in_channels = in_channels
self.reduction = reduction
self.inter_channels = max(in_channels // reduction, 1)
conv_params = dict(kernel_size=1, act_cfg=None)
self.a = ConvModule(in_channels, 1, **conv_params)
self.k = ConvModule(in_channels, 1, **conv_params)
self.v = ConvModule(in_channels, self.inter_channels, **conv_params)
self.m = ConvModule(self.inter_channels, in_channels, **conv_params)
self.init_weights()
def init_weights(self):
for m in (self.a, self.k, self.v):
caffe2_xavier_init(m.conv)
constant_init(self.m.conv, 0)
def forward(self, x):
# n, c = x.size(0)
n = x.size(0)
c = self.inter_channels
# n, nH, nW, c = x.shape
# a: [N, 1, H, W]
a = self.a(x).sigmoid()
# k: [N, 1, HW, 1]
k = self.k(x).view(n, 1, -1, 1).softmax(2)
# v: [N, 1, C, HW]
v = self.v(x).view(n, 1, c, -1)
# y: [N, C, 1, 1]
y = torch.matmul(v, k).view(n, c, 1, 1)
y = self.m(y) * a
return x + y
###################### ContextAggregation #### END by AI&CV ###############################
3.2修改yolo.py
1)首先进行引用
from models.attention.attention import *
2)修改def parse_model(d, ch): # model_dict, input_channels(3)
在源码基础上加入ContextAggregation
elif m is nn.BatchNorm2d:
args = [ch[f]]
###attention #####
elif m in {EMA_attention, CoordAtt,CBAM,GAM_Attention,PolarizedSelfAttention,SimAM,NAMAttention,DoubleAttention,SKAttention,
ContextAggregation}:
c2 = ch[f]
args = [c2, *args]
###attention #####
3.3 yolov9-c-ContextAggregation.yaml
# 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, RepNCSPELAN4, [256, 128, 64, 1]], # 3
# avg-conv down
[-1, 1, ADown, [256]], # 4-P3/8
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 5
# avg-conv down
[-1, 1, ADown, [512]], # 6-P4/16
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 7
# avg-conv down
[-1, 1, ADown, [512]], # 8-P5/32
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 9
[-1, 1, ContextAggregation, [512]], # 10
]
# YOLOv9 head
head:
[
# elan-spp block
[-1, 1, SPPELAN, [512, 256]], # 11
# 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]], # 14
# 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]], # 17 (P3/8-small)
# avg-conv-down merge
[-1, 1, ADown, [256]],
[[-1, 14], 1, Concat, [1]], # cat head P4
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 20 (P4/16-medium)
# avg-conv-down merge
[-1, 1, ADown, [512]],
[[-1, 11], 1, Concat, [1]], # cat head P5
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 23 (P5/32-large)
# multi-level reversible auxiliary branch
# routing
[5, 1, CBLinear, [[256]]], # 24
[7, 1, CBLinear, [[256, 512]]], # 25
[9, 1, CBLinear, [[256, 512, 512]]], # 26
# conv down
[0, 1, Conv, [64, 3, 2]], # 27-P1/2
# conv down
[-1, 1, Conv, [128, 3, 2]], # 28-P2/4
# elan-1 block
[-1, 1, RepNCSPELAN4, [256, 128, 64, 1]], # 29
# avg-conv down fuse
[-1, 1, ADown, [256]], # 30-P3/8
[[24, 25, 26, -1], 1, CBFuse, [[0, 0, 0]]], # 31
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 256, 128, 1]], # 32
# avg-conv down fuse
[-1, 1, ADown, [512]], # 33-P4/16
[[25, 26, -1], 1, CBFuse, [[1, 1]]], # 34
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 35
# avg-conv down fuse
[-1, 1, ADown, [512]], # 36-P5/32
[[26, -1], 1, CBFuse, [[2]]], # 37
# elan-2 block
[-1, 1, RepNCSPELAN4, [512, 512, 256, 1]], # 38
# detection head
# detect
[[32, 35, 38, 17, 20, 23], 1, DualDDetect, [nc]], # DualDDetect(A3, A4, A5, P3, P4, P5)
]