RT-DETR改进策略【Neck】| 使用CARAFE轻量级通用上采样算子
一、本文介绍
本文记录的是
利用CARAFE上采样对RT-DETR的颈部网络进行改进的方法研究
。
RT-DETR
采用传统的最近邻插值的方法,仅考虑子像素邻域,无法捕获密集预测任务所需的丰富语义信息,从而影响模型在密集预测任务中的性能。
CARAFE
通过在大感受野内聚合信息、能够实时适应实例特定内容且保持计算效率。
二、CARAFE介绍
CARAFE
:
内容感知的特征重新组合
CARAFE(Content - Aware ReAssembly of FEatures)
是一种用于特征上采样的操作符,其设计原理和优势如下:
2.1、CARAFE原理
-
总体框架
:
CARAFE由两个关键组件组成,即 核预测模块 和 内容感知重组模块 。给定大小为 C × H × W C×H×W C × H × W 的特征图 x x x 和上采样比例 σ \sigma σ (假设 σ \sigma σ 是整数),CARAFE将产生大小为 C × σ H × σ W C×\sigma H×\sigma W C × σ H × σW 的新特征图 X ′ X' X ′ 。 -
核预测模块
:负责以内容感知的方式生成重组核。每个源位置
x
x
x
上对应
σ
2
\sigma^{2}
σ
2
个目标位置
X
′
X'
X
′
上,每个目标位置需要一个
k
u
p
×
k
u
p
k_{u p}×k_{u p}
k
u
p
×
k
u
p
的重组核,因此该模块将输出大小为
C
u
p
×
H
×
W
C_{u p}×H×W
C
u
p
×
H
×
W
的重组核,其中
C
u
p
=
σ
2
k
u
p
2
C_{u p} = \sigma^{2}k_{u p}^{2}
C
u
p
=
σ
2
k
u
p
2
。该模块由三个子模块组成,分别是通道压缩器、内容编码器和核归一化器。
- 通道压缩器 :采用 1 × 1 1×1 1 × 1 卷积层将输入特征通道从 C C C 压缩到 C m C_{m} C m ,减少特征图的通道数,从而减少后续步骤的参数和计算成本,使CARAFE更高效。
- 内容编码器 :使用核大小为 k e n c o d e r k_{encoder} k e n co d er 的卷积层根据输入特征的内容生成重组核,编码器的参数为 k e n c o d e r × k e n c o d e r × C m × C u p k_{encoder}×k_{encoder}×C_{m}×C_{u p} k e n co d er × k e n co d er × C m × C u p 。增大 k e n c o d e r k_{encoder} k e n co d er 可以扩大编码器的感受野,利用更大区域内的上下文信息,但计算复杂度也会随之增加。通过研究, k e n c o d e r = k u p − 2 k_{encoder} = k_{u p} - 2 k e n co d er = k u p − 2 是性能和效率之间的良好平衡。
- 核归一化器 :在将每个 k u p × k u p k_{u p}×k_{u p} k u p × k u p 重组核应用于输入特征图之前,使用softmax函数对其进行空间归一化,使核值之和为 1 1 1 ,这是对局部区域的软选择。
- 内容感知重组模块 :对于目标位置 l ′ l' l ′ 和以 l = ( i , j ) l = (i, j) l = ( i , j ) 为中心的相应方形区域 N ( X l , k u p ) N(X_{l}, k_{u p}) N ( X l , k u p ) ,重组过程如公式 X l ′ ′ = ∑ n = − r r ∑ m = − r r W l ′ ( n , m ) ⋅ X ( i + n , j + m ) \mathcal{X}_{l'}' = \sum_{n = -r}^{r}\sum_{m = -r}^{r}\mathcal{W}_{l'(n, m)}·\mathcal{X}_{(i + n, j + m)} X l ′ ′ = ∑ n = − r r ∑ m = − r r W l ′ ( n , m ) ⋅ X ( i + n , j + m ) 所示,其中 r = ⌊ k u p / 2 ⌋ r = \lfloor k_{u p} / 2\rfloor r = ⌊ k u p /2 ⌋ 。通过重组核,区域 N ( X l , k u p ) N(X_{l}, k_{u p}) N ( X l , k u p ) 中的每个像素根据特征的内容而不是位置的距离对上采样像素 l ′ l' l ′ 的贡献不同,使得重组后的特征图的语义比原始特征图更强。
2.2、优势
-
大视野
:与之前仅利用子像素邻域的工作不同,
CARAFE可以在大感受野内聚合上下文信息。 -
内容感知处理
:
CARAFE能够根据实例特定的内容进行实时处理,为每个样本生成自适应的内核,而不是使用固定的内核。 -
轻量且计算快速
:
CARAFE引入的计算开销很小,可以很容易地集成到现代网络架构中。 - 通用性和有效性 :在对象检测、实例分割、语义分割、图像修复等广泛的密集预测任务中,CARAFE都能显著提升性能。
论文: https://arxiv.org/abs/1905.02188
源码: https://github.com/tiny-smart/dysample
三、CARAFE的实现代码
CARAFE模块
的实现代码如下:
class CARAFE(nn.Module):
def __init__(self, c, k_enc=3, k_up=5, c_mid=64, scale=2):
""" The unofficial implementation of the CARAFE module.
The details are in "https://arxiv.org/abs/1905.02188".
Args:
c: The channel number of the input and the output.
c_mid: The channel number after compression.
scale: The expected upsample scale.
k_up: The size of the reassembly kernel.
k_enc: The kernel size of the encoder.
Returns:
X: The upsampled feature map.
"""
super(CARAFE, self).__init__()
self.scale = scale
self.comp = Conv(c, c_mid)
self.enc = Conv(c_mid, (scale * k_up) ** 2, k=k_enc, act=False)
self.pix_shf = nn.PixelShuffle(scale)
self.upsmp = nn.Upsample(scale_factor=scale, mode='nearest')
self.unfold = nn.Unfold(kernel_size=k_up, dilation=scale,
padding=k_up // 2 * scale)
def forward(self, X):
b, c, h, w = X.size()
h_, w_ = h * self.scale, w * self.scale
W = self.comp(X) # b * m * h * w
W = self.enc(W) # b * 100 * h * w
W = self.pix_shf(W) # b * 25 * h_ * w_
W = torch.softmax(W, dim=1) # b * 25 * h_ * w_
X = self.upsmp(X) # b * c * h_ * w_
X = self.unfold(X) # b * 25c * h_ * w_
X = X.view(b, c, -1, h_, w_) # b * 25 * c * h_ * w_
X = torch.einsum('bkhw,bckhw->bchw', [W, X]) # b * c * h_ * w_
return X
四、添加步骤
4.1 修改ultralytics/nn/modules/block.py
此处需要修改的文件是
ultralytics/nn/modules/block.py
block.py中定义了网络结构的通用模块
,我们想要加入新的模块就只需要将模块代码放到这个文件内即可。
将
CARAFE
模块代码添加到此文件下。
4.2 修改ultralytics/nn/modules/ init .py
此处需要修改的文件是
ultralytics/nn/modules/__init__.py
__init__.py
文件中定义了所有模块的初始化,我们只需要将
block.py
中的新的模块命添加到对应的函数即可。
CARAFE
在
block.py
中实现,所有要添加在
from .block import
:
from .block import (
C1,
C2,
...
CARAFE
)
4.3 修改ultralytics/nn/modules/tasks.py
在
tasks.py
文件中,需要在两处位置添加各模块类名称。
首先:在函数声明中引入
CARAFE
其次:在
parse_model函数
中注册
CARAFE
模块
elif m in [CARAFE]:
args = [ch[f], *args[0:]]
五、yaml模型文件
5.1 模型改进⭐
在代码配置完成后,配置模型的YAML文件。
此处以
ultralytics/cfg/models/rt-detr/rtdetr-l.yaml
为例,在同目录下创建一个用于自己数据集训练的模型文件
rtdetr-l-CARAFE.yaml
。
将
rtdetr-l.yaml
中的内容复制到
rtdetr-l-CARAFE.yaml
文件下,修改
nc
数量等于自己数据中目标的数量。
📌 修改方法是将
CARAFE模块
替换
rtdetr-l
颈部网络中的上采样模块
nn.Upsample
。
# Ultralytics YOLO 🚀, AGPL-3.0 license
# RT-DETR-l object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'
# [depth, width, max_channels]
l: [1.00, 1.00, 1024]
backbone:
# [from, repeats, module, args]
- [-1, 1, HGStem, [32, 48]] # 0-P2/4
- [-1, 6, HGBlock, [48, 128, 3]] # stage 1
- [-1, 1, DWConv, [128, 3, 2, 1, False]] # 2-P3/8
- [-1, 6, HGBlock, [96, 512, 3]] # stage 2
- [-1, 1, DWConv, [512, 3, 2, 1, False]] # 4-P3/16
- [-1, 6, HGBlock, [192, 1024, 5, True, False]] # cm, c2, k, light, shortcut
- [-1, 6, HGBlock, [192, 1024, 5, True, True]]
- [-1, 6, HGBlock, [192, 1024, 5, True, True]] # stage 3
- [-1, 1, DWConv, [1024, 3, 2, 1, False]] # 8-P4/32
- [-1, 6, HGBlock, [384, 2048, 5, True, False]] # stage 4
head:
- [-1, 1, Conv, [256, 1, 1, None, 1, 1, False]] # 10 input_proj.2
- [-1, 1, AIFI, [1024, 8]]
- [-1, 1, Conv, [256, 1, 1]] # 12, Y5, lateral_convs.0
- [-1, 1, CARAFE, []]
- [7, 1, Conv, [256, 1, 1, None, 1, 1, False]] # 14 input_proj.1
- [[-2, -1], 1, Concat, [1]]
- [-1, 3, RepC3, [256]] # 16, fpn_blocks.0
- [-1, 1, Conv, [256, 1, 1]] # 17, Y4, lateral_convs.1
- [-1, 1, CARAFE, []]
- [3, 1, Conv, [256, 1, 1, None, 1, 1, False]] # 19 input_proj.0
- [[-2, -1], 1, Concat, [1]] # cat backbone P4
- [-1, 3, RepC3, [256]] # X3 (21), fpn_blocks.1
- [-1, 1, Conv, [256, 3, 2]] # 22, downsample_convs.0
- [[-1, 17], 1, Concat, [1]] # cat Y4
- [-1, 3, RepC3, [256]] # F4 (24), pan_blocks.0
- [-1, 1, Conv, [256, 3, 2]] # 25, downsample_convs.1
- [[-1, 12], 1, Concat, [1]] # cat Y5
- [-1, 3, RepC3, [256]] # F5 (27), pan_blocks.1
- [[21, 24, 27], 1, RTDETRDecoder, [nc]] # Detect(P3, P4, P5)
六、成功运行结果
分别打印网络模型可以看到
CARAFE模块
已经加入到模型中,并可以进行训练了。
rtdetr-l-CARAFE :
rtdetr-l-CARAFE summary: 702 layers, 32,956,755 parameters, 32,956,755 gradients, 108.3 GFLOPs
from n params module arguments
0 -1 1 25248 ultralytics.nn.modules.block.HGStem [3, 32, 48]
1 -1 6 155072 ultralytics.nn.modules.block.HGBlock [48, 48, 128, 3, 6]
2 -1 1 1408 ultralytics.nn.modules.conv.DWConv [128, 128, 3, 2, 1, False]
3 -1 6 839296 ultralytics.nn.modules.block.HGBlock [128, 96, 512, 3, 6]
4 -1 1 5632 ultralytics.nn.modules.conv.DWConv [512, 512, 3, 2, 1, False]
5 -1 6 1695360 ultralytics.nn.modules.block.HGBlock [512, 192, 1024, 5, 6, True, False]
6 -1 6 2055808 ultralytics.nn.modules.block.HGBlock [1024, 192, 1024, 5, 6, True, True]
7 -1 6 2055808 ultralytics.nn.modules.block.HGBlock [1024, 192, 1024, 5, 6, True, True]
8 -1 1 11264 ultralytics.nn.modules.conv.DWConv [1024, 1024, 3, 2, 1, False]
9 -1 6 6708480 ultralytics.nn.modules.block.HGBlock [1024, 384, 2048, 5, 6, True, False]
10 -1 1 524800 ultralytics.nn.modules.conv.Conv [2048, 256, 1, 1, None, 1, 1, False]
11 -1 1 789760 ultralytics.nn.modules.transformer.AIFI [256, 1024, 8]
12 -1 1 66048 ultralytics.nn.modules.conv.Conv [256, 256, 1, 1]
13 -1 1 74312 ultralytics.nn.AddModules.CARAFE.CARAFE [256]
14 7 1 262656 ultralytics.nn.modules.conv.Conv [1024, 256, 1, 1, None, 1, 1, False]
15 [-2, -1] 1 0 ultralytics.nn.modules.conv.Concat [1]
16 -1 3 2232320 ultralytics.nn.modules.block.RepC3 [512, 256, 3]
17 -1 1 66048 ultralytics.nn.modules.conv.Conv [256, 256, 1, 1]
18 -1 1 74312 ultralytics.nn.AddModules.CARAFE.CARAFE [256]
19 3 1 131584 ultralytics.nn.modules.conv.Conv [512, 256, 1, 1, None, 1, 1, False]
20 [-2, -1] 1 0 ultralytics.nn.modules.conv.Concat [1]
21 -1 3 2232320 ultralytics.nn.modules.block.RepC3 [512, 256, 3]
22 -1 1 590336 ultralytics.nn.modules.conv.Conv [256, 256, 3, 2]
23 [-1, 17] 1 0 ultralytics.nn.modules.conv.Concat [1]
24 -1 3 2232320 ultralytics.nn.modules.block.RepC3 [512, 256, 3]
25 -1 1 590336 ultralytics.nn.modules.conv.Conv [256, 256, 3, 2]
26 [-1, 12] 1 0 ultralytics.nn.modules.conv.Concat [1]
27 -1 3 2232320 ultralytics.nn.modules.block.RepC3 [512, 256, 3]
28 [21, 24, 27] 1 7303907 ultralytics.nn.modules.head.RTDETRDecoder [1, [256, 256, 256]]
rtdetr-l-CARAFE summary: 702 layers, 32,956,755 parameters, 32,956,755 gradients, 108.3 GFLOPs