连夜卷出 | 超越所有YOLO检测模型,mmdet开源当今最强最快目标检测模型!(一)

简介: 连夜卷出 | 超越所有YOLO检测模型,mmdet开源当今最强最快目标检测模型!(一)

首先,这里先声明一下由于论文和代码没有一并放出,所以以下内容全是个人学习RTMDet代码的一个结果,整个过程时间也比较紧凑,难免会有所遗漏和错误,一切关于RTMDet的工作,最终以OpenMMLab官方论文为主,因为看到开源代码的速度表,小编很难不爱,小模型就可以把YOLO全系列按在地上摩擦,因此也就有了下面的故事。


0、直接上架构图吧!


看着上面的图,熟悉不?是不是满满的YOLO系列的味道?是的,看代码我猜应该是基于YOLO来进行的增量实验吧,也仅仅是猜啦,毕竟暗俺也没看到RTMDet的论文,俺也不是开发者!


1、改进点1 —— CSPNeXt


1.1 Backbone 部分

话不多说,直接上代码:

class CSPNeXtBlock(BaseModule):
    def __init__(self,
                 in_channels: int,
                 out_channels: int,
                 expansion: float = 0.5,
                 add_identity: bool = True,
                 use_depthwise: bool = False,
                 kernel_size: int = 5,
                 conv_cfg: OptConfigType = None,
                 norm_cfg: ConfigType = dict(
                     type='BN', momentum=0.03, eps=0.001),
                 act_cfg: ConfigType = dict(type='SiLU'),
                 init_cfg: OptMultiConfig = None) -> None:
        super().__init__(init_cfg=init_cfg)
        hidden_channels = int(out_channels * expansion)
        conv = DepthwiseSeparableConvModule if use_depthwise else ConvModule
        self.conv1 = conv(
            in_channels,
            hidden_channels,
            3,
            stride=1,
            padding=1,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg)
        self.conv2 = DepthwiseSeparableConvModule(
            hidden_channels,
            out_channels,
            kernel_size,
            stride=1,
            padding=kernel_size // 2,
            conv_cfg=conv_cfg,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg)
        self.add_identity = add_identity and in_channels == out_channels
    def forward(self, x: Tensor) -> Tensor:
        identity = x
        out = self.conv1(x)
        out = self.conv2(out)
        if self.add_identity:
            return out + identity
        else:
            return out

其实通过代码我们可以很直观的看出模型的架构细节,这里小编也进行了简要的绘制,具体如下图:

image.png

这里提到的 Depthwise Separable Convolution 是 MobileNet 的基本单元,其实这种结构之前已经使用在 Inception 模型中。Depthwise Separable Convolution 其实是一种可分解卷积操作,其可以分解为2个更小的操作:Depthwise Convolution 和 Pointwise Convolution,如图所示。

image.png

Depthwise Convolution 和标准卷积不同,对于标准卷积,其卷积核是用在所有的输入通道上(input channels),而 Depthwise Convolution 针对每个输入通道采用不同的卷积核,就是说一个卷积核对应一个输入通道,所以说 Depthwise Convolution 是 Depth 级别的操作。

而 Pointwise Convolution 其实就是普通的 1×1 的卷积。对于 Depthwise Separable Convolution,首先是采用 Depthwise Convolution 对不同输入通道分别进行卷积,然后采用 Pointwise Convolution 将上面的输出再进行结合,这样整体效果和一个标准卷积是差不多的,但是会大大减少计算量和模型参数量。

熟悉DarkNet的朋友应该都知道,如果你不知道,小编这里也给出架构图:

image.png

然后依旧是直接上CSPLayer的代码:

class CSPLayer(BaseModule):
    def __init__(self,
                 in_channels: int,
                 out_channels: int,
                 expand_ratio: float = 0.5,
                 num_blocks: int = 1,
                 add_identity: bool = True,
                 use_depthwise: bool = False,
                 use_cspnext_block: bool = False,
                 channel_attention: bool = False,
                 conv_cfg: OptConfigType = None,
                 norm_cfg: ConfigType = dict(type='BN', momentum=0.03, eps=0.001),
                 act_cfg: ConfigType = dict(type='Swish'),
                 init_cfg: OptMultiConfig = None) -> None:
        super().__init__(init_cfg=init_cfg)
        block = CSPNeXtBlock if use_cspnext_block else DarknetBottleneck
        mid_channels = int(out_channels * expand_ratio)
        self.channel_attention = channel_attention
        self.main_conv = ConvModule(
            in_channels,
            mid_channels,
            1,
            conv_cfg=conv_cfg,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg)
        self.short_conv = ConvModule(
            in_channels,
            mid_channels,
            1,
            conv_cfg=conv_cfg,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg)
        self.final_conv = ConvModule(
            2 * mid_channels,
            out_channels,
            1,
            conv_cfg=conv_cfg,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg)
        self.blocks = nn.Sequential(*[
            block(
                mid_channels,
                mid_channels,
                1.0,
                add_identity,
                use_depthwise,
                conv_cfg=conv_cfg,
                norm_cfg=norm_cfg,
                act_cfg=act_cfg) for _ in range(num_blocks)
        ])
        if channel_attention:
            self.attention = ChannelAttention(2 * mid_channels)
    def forward(self, x: Tensor) -> Tensor:
        x_short = self.short_conv(x)
        x_main = self.main_conv(x)
        x_main = self.blocks(x_main)
        x_final = torch.cat((x_main, x_short), dim=1)
        if self.channel_attention:
            x_final = self.attention(x_final)
        return self.final_conv(x_final)

其结构如下所示,毫无疑问依旧是香香的CSP思想,但是这里的结构使用了5×5的DW卷积,实现了更少的参数量的情况下,带来更大的感受野。

image.png

同时这里RTMDet的Backbone中还考虑了通道注意力的问题,其代码如下:

class ChannelAttention(BaseModule):
    def __init__(self, channels: int, init_cfg: OptMultiConfig = None) -> None:
        super().__init__(init_cfg)
        self.global_avgpool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Conv2d(channels, channels, 1, 1, 0, bias=True)
        self.act = nn.Hardsigmoid(inplace=True)
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        out = self.global_avgpool(x)
        out = self.fc(out)
        out = self.act(out)
        return x * out

小编依旧给小伙伴们画了示意图:

image.png

其实还有一个细节,这里我想的也不是很明白,如果熟悉ResNet构建的小伙伴应该知道,凯明大神在构建ResNet50是使用的残差Block的数量配比就是[3,6,6,3],

image.png

image.png

这里RTMDet使用的配比也是:

image.png

但是小编在白嫖 TRT-ViT、NeXtViT、SWin以及ConvNeXt的时候都在或有或无地说逐层增加配比会带来更好的结果,这里不知道为什么RTMDet选择以前的数据,期待论文中的描述和解释!

1.2 Neck部分

其实也是毫不意外的PAFPN的架构,只不过这里作者选择把YOLO系列中的CSPBlock替换为了本方法中的CSPNeXt Block,具体架构图如下所示:

image.png

1.3 Head部分

这部分也是相对比较常规的设计,对于PAFPN结构输出的特征,先使用由堆叠的卷积所组成的分类分支以及回归分支提取对应的分类特征和回归特征,然后分别送到对应的RTM分类分支和回归分支,得到我们最终随需要的东西,这里有一个小小的细节,便是堆叠的卷积在不同level的中是共享权重的,具体可以参见代码,这里也不进行过多的猜测,最终还是以论文为主。

image.png

相关文章
|
3月前
|
人工智能 测试技术 PyTorch
AI计算机视觉笔记二十四:YOLOP 训练+测试+模型评估
本文介绍了通过正点原子的ATK-3568了解并实现YOLOP(You Only Look Once for Panoptic Driving Perception)的过程,包括训练、测试、转换为ONNX格式及在ONNX Runtime上的部署。YOLOP由华中科技大学团队于2021年发布,可在Jetson TX2上达到23FPS,实现了目标检测、可行驶区域分割和车道线检测的多任务学习。文章详细记录了环境搭建、训练数据准备、模型转换和测试等步骤,并解决了ONNX转换过程中的问题。
|
7月前
|
机器学习/深度学习 人工智能
谷歌提出大规模ICL方法——强化和无监督
【5月更文挑战第26天】谷歌DeepMind团队提出Many-Shot ICL,一种强化和无监督学习方法,用于提升大型语言模型处理多样化任务的能力。通过提供更多示例,模型无需权重更新即可学习新任务。研究还引入Reinforced ICL和Unsupervised ICL,减少对人类生成输出的依赖。Many-Shot ICL能有效克服预训练偏见,但示例顺序对其性能至关重要。然而,NLL作为评估指标的局限性被指出,且增加示例数量可能降低性能。该研究为改进LLMs提供了新视角,但仍需在更多模型和场景中验证。[链接: https://arxiv.org/abs/2404.11018]
77 1
|
7月前
|
人工智能 调度 vr&ar
探索生成模型的新篇章:扩散模型的理论与实践
【4月更文挑战第11天】扩散模型作为新兴的生成工具,基于变分自编码器(VAE)和去噪扩散概率模型(DDPM),通过逐步添加噪声生成样本,广泛应用于图像和视频生成,展示出在逆问题解决上的潜力。尽管训练复杂且计算需求高,研究者正通过新理论框架和SDE方法优化模型,以应对挑战并提升性能。
80 1
探索生成模型的新篇章:扩散模型的理论与实践
|
7月前
|
机器学习/深度学习 计算机视觉
大模型一定就比小模型好?谷歌的这项研究说不一定
【5月更文挑战第5天】谷歌研究挑战传统观念,指出在生成图像任务中,小模型并不一定逊色于大模型。实验显示小模型在有限计算资源下能生成高质量图像,且泛化性能佳。在多个图像生成任务中,小模型的表现与大模型相当甚至更好,暗示了小模型在该领域的潜力。这一发现提示了在追求性能时需综合考虑模型规模和效率。论文链接:https://arxiv.org/pdf/2404.01367.pdf
67 2
|
7月前
|
机器学习/深度学习 人工智能
ChatGPT检测器——以前所未有的准确性捕捉AI生成的论文
【2月更文挑战第25天】ChatGPT检测器——以前所未有的准确性捕捉AI生成的论文
100 7
ChatGPT检测器——以前所未有的准确性捕捉AI生成的论文
|
7月前
|
编解码 人工智能 算法
极智AI | 目标检测实现分享二:听说克莱今天复出了?详解YOLOv2算法与克莱检测
大家好,我是极智视界,本文详细介绍一下 YOLOv2 算法的设计与实现,包括训练。
253 1
|
7月前
|
机器学习/深度学习 人工智能 算法
基于AidLux的工业视觉少样本缺陷检测实战应用---深度学习分割模型UNET的实践部署
  工业视觉在生产和制造中扮演着关键角色,而缺陷检测则是确保产品质量和生产效率的重要环节。工业视觉的前景与发展在于其在生产制造领域的关键作用,尤其是在少样本缺陷检测方面,借助AidLux技术和深度学习分割模型UNET的实践应用,深度学习分割模型UNET的实践部署变得至关重要。
181 1
|
机器学习/深度学习 人工智能 缓存
连夜卷出 | 超越所有YOLO检测模型,mmdet开源当今最强最快目标检测模型!(二)
连夜卷出 | 超越所有YOLO检测模型,mmdet开源当今最强最快目标检测模型!(二)
564 0
|
机器学习/深度学习 人工智能 自然语言处理
与生成模型相比,为何机器人研究还在用几年前的老方法?(2)
与生成模型相比,为何机器人研究还在用几年前的老方法?
|
机器学习/深度学习 人工智能 自然语言处理
与生成模型相比,为何机器人研究还在用几年前的老方法?
与生成模型相比,为何机器人研究还在用几年前的老方法?
124 0