YOLOv8改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)

news2025/1/20 20:02:51

一、本文介绍

本文给家大家带来的改进机制是iRMB,其是在论文Rethinking Mobile Block for Efficient Attention-based Models种提出,论文提出了一个新的主干网络EMO(后面我也会教大家如何使用该主干,本文先教大家使用该文中提出的注意力机制)。其主要思想是将轻量级的CNN架构与基于注意力的模型结构相结合(有点类似ACmix),我将iRMB和C2f结合,然后也将其用在了检测头种进行尝试三种结果进行对比,针对的作用也不相同,但是无论那种实验均有一定涨点效果,同时该注意力机制属于是比较轻量化的参数量比较小,训练速度也很快,后面我会将各种添加方法教给大家,让大家在自己的模型中进行复现。

推荐指数:⭐⭐⭐⭐⭐

涨点效果:⭐⭐⭐⭐⭐

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备    

训练结果对比图-> 

目录

一、本文介绍

二、iRMB的框架原理

2.1 iRMB结构

2.2 倒置残差块

2.3 元移动块(Meta-Mobile Block)

三、iRMB的核心代码 

四、手把手教你添加iRMB和C2f_iRMB机制 

4.1 步骤一

4.2 步骤二

4.3 步骤三

五、iRMB和C2f_iRMB的yaml文件和运行记录

5.1 yaml版本一(推荐)

5.2 yaml版本二

5.3 yaml版本三 

5.4 推荐iRMB可添加的位置 

5.5 iRMB的训练过程截图 

五、本文总结


二、iRMB的框架原理

官方论文地址:官方论文地址点击即可跳转

官方代码地址:官方代码地址点击即可跳转


iRMB(Inverted Residual Mobile Block)的主要思想是将轻量级的CNN架构与基于注意力的模型结构相结合(有点类似ACmix),以创建高效的移动网络。iRMB通过重新考虑倒置残差块(IRB)和Transformer的有效组件,实现了一种统一的视角,从而扩展了CNN的IRB到基于注意力的模型。iRMB的设计目标是在保持模型轻量级的同时,实现对计算资源的有效利用和高准确率。这一方法通过在下游任务上的广泛实验得到验证,展示出其在轻量级模型领域的优越性能。

iRMB的主要创新点在于以下三点:

1. 结合CNN的轻量级特性和Transformer的动态模型能力,创新提出了iRMB结构,适用于移动设备上的密集预测任务。
2. 使用倒置残差块设计,扩展了传统CNN的IRB到基于注意力的模型,增强了模型处理长距离信息的能力。
3. 提出了元移动块(Meta-Mobile Block),通过不同的扩展比率和高效操作符,实现了模型的模块化设计,使得模型更加灵活和高效。


2.1 iRMB结构

iRMB 结构的主要创新点是它结合了卷积神经网络(CNN)的轻量级特性和 Transformer 模型的动态处理能力。这种结构特别适用于移动设备上的密集预测任务,因为它旨在在计算能力有限的环境中提供高效的性能。iRMB 通过其倒置残差设计改进了信息流的处理,允许在保持模型轻量的同时捕捉和利用长距离依赖,这对于图像分类、对象检测和语义分割等任务至关重要。这种设计使得模型在资源受限的设备上也能高效运行,同时保持或提高预测准确性。

上面的图片来自与论文的图片2展示了iRMB(Inverted Residual Mobile Block)的设计理念和结构。左侧是从多头自注意力和前馈网络中抽象出的统一元移动块(Meta-Mobile Block),它将不同扩展比率和高效操作符结合起来,形成特定的模块。右侧是基于iRMB构建的类似ResNet的高效模型(EMO),它仅由推导出的iRMB组成,并用于各种下游任务,如分类(CLS)、检测(Det)和分割(Seg)。这种设计实现了模型的轻量化,同时保持了良好的性能和效率。 

这幅图展示了iRMB(Inverted Residual Mobile Block)的结构范式。iRMB是一种混合网络模块,它结合了深度可分离卷积(3x3 DW-Conv)和自注意力机制。1x1卷积用于通道数的压缩和扩张,以此优化计算效率。深度可分离卷积(DW-Conv)用于捕捉空间特征,而注意力机制则用于捕获特征间的全局依赖关系。


2.2 倒置残差块

在iRMB设计中,使用倒置残差块(IRB)的概念被扩展到了基于注意力的模型中。这使得模型能够更有效地处理长距离信息,这是因为自注意力机制能够捕获输入数据中不同部分之间的全局依赖关系。传统的CNN通常只能捕捉到局部特征,而通过引入注意力机制,iRMB能够在提取特征时考虑到整个输入空间,增强了模型对复杂数据模式的理解能力,特别是在处理视觉和序列数据时。这种结合了传统CNN的轻量化和Transformer的长距离建模能力的设计,为在资源受限的环境中实现高效的深度学习模型提供了新的可能性(文章中并没有关于IRB的结构图)。


2.3 元移动块(Meta-Mobile Block)

元移动块(Meta-Mobile Block),它通过不同的扩展比率和高效操作符实现模块化设计。这种方法使得模型可以根据需要调整其容量,而无需重新设计整个网络。元移动块的核心理念是通过可插拔的方式,将不同的操作如卷积、自注意力等集成到一个统一的框架中,从而提高模型的效率和灵活性。这允许模型在复杂性和计算效率之间进行更好的权衡,特别适用于那些需要在有限资源下运行的应用。

图中展示的是Meta Mobile Block的设计。在这个构件中,1x1的卷积层被用来改变特征图的通道数,从而控制网络的容量。中间的“Efficient Operator”是一个高效的运算符,可以是自注意力机制或其他任何高效的层或操作。这种设计使得Meta Mobile Block能够灵活地适应不同的任务需求,并保持高效的计算性能。通过这样的模块化,网络能够在不同的环境和任务中进行快速调整和优化。 


三、iRMB的核心代码 

该代码的使用方式我们看章节四来进行使用,其中包含C2f_iRMB和iRMB本体注意力机制。

import math
import torch
import torch.nn as nn
import torch.nn.functional as F
from functools import partial
from einops import rearrange
from timm.models._efficientnet_blocks import SqueezeExcite
from timm.models.layers import DropPath

inplace = True

class LayerNorm2d(nn.Module):

    def __init__(self, normalized_shape, eps=1e-6, elementwise_affine=True):
        super().__init__()
        self.norm = nn.LayerNorm(normalized_shape, eps, elementwise_affine)

    def forward(self, x):
        x = rearrange(x, 'b c h w -> b h w c').contiguous()
        x = self.norm(x)
        x = rearrange(x, 'b h w c -> b c h w').contiguous()
        return x


def get_norm(norm_layer='in_1d'):
    eps = 1e-6
    norm_dict = {
        'none': nn.Identity,
        'in_1d': partial(nn.InstanceNorm1d, eps=eps),
        'in_2d': partial(nn.InstanceNorm2d, eps=eps),
        'in_3d': partial(nn.InstanceNorm3d, eps=eps),
        'bn_1d': partial(nn.BatchNorm1d, eps=eps),
        'bn_2d': partial(nn.BatchNorm2d, eps=eps),
        # 'bn_2d': partial(nn.SyncBatchNorm, eps=eps),
        'bn_3d': partial(nn.BatchNorm3d, eps=eps),
        'gn': partial(nn.GroupNorm, eps=eps),
        'ln_1d': partial(nn.LayerNorm, eps=eps),
        'ln_2d': partial(LayerNorm2d, eps=eps),
    }
    return norm_dict[norm_layer]


def get_act(act_layer='relu'):
    act_dict = {
        'none': nn.Identity,
        'relu': nn.ReLU,
        'relu6': nn.ReLU6,
        'silu': nn.SiLU
    }
    return act_dict[act_layer]


class ConvNormAct(nn.Module):

    def __init__(self, dim_in, dim_out, kernel_size, stride=1, dilation=1, groups=1, bias=False,
                 skip=False, norm_layer='bn_2d', act_layer='relu', inplace=True, drop_path_rate=0.):
        super(ConvNormAct, self).__init__()
        self.has_skip = skip and dim_in == dim_out
        padding = math.ceil((kernel_size - stride) / 2)
        self.conv = nn.Conv2d(dim_in, dim_out, kernel_size, stride, padding, dilation, groups, bias)
        self.norm = get_norm(norm_layer)(dim_out)
        self.act = get_act(act_layer)(inplace=inplace)
        self.drop_path = DropPath(drop_path_rate) if drop_path_rate else nn.Identity()

    def forward(self, x):
        shortcut = x
        x = self.conv(x)
        x = self.norm(x)
        x = self.act(x)
        if self.has_skip:
            x = self.drop_path(x) + shortcut
        return x



class iRMB(nn.Module):

    def __init__(self, dim_in, dim_out, norm_in=True, has_skip=True, exp_ratio=1.0, norm_layer='bn_2d',
                 act_layer='relu', v_proj=True, dw_ks=3, stride=1, dilation=1, se_ratio=0.0, dim_head=8, window_size=7,
                 attn_s=True, qkv_bias=False, attn_drop=0., drop=0., drop_path=0., v_group=False, attn_pre=False):
        super().__init__()
        self.norm = get_norm(norm_layer)(dim_in) if norm_in else nn.Identity()
        dim_mid = int(dim_in * exp_ratio)
        self.has_skip = (dim_in == dim_out and stride == 1) and has_skip
        self.attn_s = attn_s
        if self.attn_s:
            assert dim_in % dim_head == 0, 'dim should be divisible by num_heads'
            self.dim_head = dim_head
            self.window_size = window_size
            self.num_head = dim_in // dim_head
            self.scale = self.dim_head ** -0.5
            self.attn_pre = attn_pre
            self.qk = ConvNormAct(dim_in, int(dim_in * 2), kernel_size=1, bias=qkv_bias, norm_layer='none',
                                  act_layer='none')
            self.v = ConvNormAct(dim_in, dim_mid, kernel_size=1, groups=self.num_head if v_group else 1, bias=qkv_bias,
                                 norm_layer='none', act_layer=act_layer, inplace=inplace)
            self.attn_drop = nn.Dropout(attn_drop)
        else:
            if v_proj:
                self.v = ConvNormAct(dim_in, dim_mid, kernel_size=1, bias=qkv_bias, norm_layer='none',
                                     act_layer=act_layer, inplace=inplace)
            else:
                self.v = nn.Identity()
        self.conv_local = ConvNormAct(dim_mid, dim_mid, kernel_size=dw_ks, stride=stride, dilation=dilation,
                                      groups=dim_mid, norm_layer='bn_2d', act_layer='silu', inplace=inplace)
        self.se = SqueezeExcite(dim_mid, rd_ratio=se_ratio, act_layer=get_act(act_layer)) if se_ratio > 0.0 else nn.Identity()

        self.proj_drop = nn.Dropout(drop)
        self.proj = ConvNormAct(dim_mid, dim_out, kernel_size=1, norm_layer='none', act_layer='none', inplace=inplace)
        self.drop_path = DropPath(drop_path) if drop_path else nn.Identity()

    def forward(self, x):
        shortcut = x
        x = self.norm(x)
        B, C, H, W = x.shape
        if self.attn_s:
            # padding
            if self.window_size <= 0:
                window_size_W, window_size_H = W, H
            else:
                window_size_W, window_size_H = self.window_size, self.window_size
            pad_l, pad_t = 0, 0
            pad_r = (window_size_W - W % window_size_W) % window_size_W
            pad_b = (window_size_H - H % window_size_H) % window_size_H
            x = F.pad(x, (pad_l, pad_r, pad_t, pad_b, 0, 0,))
            n1, n2 = (H + pad_b) // window_size_H, (W + pad_r) // window_size_W
            x = rearrange(x, 'b c (h1 n1) (w1 n2) -> (b n1 n2) c h1 w1', n1=n1, n2=n2).contiguous()
            # attention
            b, c, h, w = x.shape
            qk = self.qk(x)
            qk = rearrange(qk, 'b (qk heads dim_head) h w -> qk b heads (h w) dim_head', qk=2, heads=self.num_head,
                           dim_head=self.dim_head).contiguous()
            q, k = qk[0], qk[1]
            attn_spa = (q @ k.transpose(-2, -1)) * self.scale
            attn_spa = attn_spa.softmax(dim=-1)
            attn_spa = self.attn_drop(attn_spa)
            if self.attn_pre:
                x = rearrange(x, 'b (heads dim_head) h w -> b heads (h w) dim_head', heads=self.num_head).contiguous()
                x_spa = attn_spa @ x
                x_spa = rearrange(x_spa, 'b heads (h w) dim_head -> b (heads dim_head) h w', heads=self.num_head, h=h,
                                  w=w).contiguous()
                x_spa = self.v(x_spa)
            else:
                v = self.v(x)
                v = rearrange(v, 'b (heads dim_head) h w -> b heads (h w) dim_head', heads=self.num_head).contiguous()
                x_spa = attn_spa @ v
                x_spa = rearrange(x_spa, 'b heads (h w) dim_head -> b (heads dim_head) h w', heads=self.num_head, h=h,
                                  w=w).contiguous()
            # unpadding
            x = rearrange(x_spa, '(b n1 n2) c h1 w1 -> b c (h1 n1) (w1 n2)', n1=n1, n2=n2).contiguous()
            if pad_r > 0 or pad_b > 0:
                x = x[:, :, :H, :W].contiguous()
        else:
            x = self.v(x)

        x = x + self.se(self.conv_local(x)) if self.has_skip else self.se(self.conv_local(x))

        x = self.proj_drop(x)
        x = self.proj(x)

        x = (shortcut + self.drop_path(x)) if self.has_skip else x
        return x


def autopad(k, p=None, d=1):  # kernel, padding, dilation
    """Pad 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-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p


class Conv(nn.Module):
    """Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""
    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        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 Bottleneck(nn.Module):
    """Standard bottleneck."""

    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
        """Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, and
        expansion.
        """
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = Conv(c_, c2, k[1], 1, g=g)
        self.add = shortcut and c1 == c2
        self.iRMB = iRMB(c2, c2)

    def forward(self, x):
        """'forward()' applies the YOLO FPN to input data."""
        return x + self.iRMB(self.cv2(self.cv1(x))) if self.add else self.iRMB(self.cv2(self.cv1(x)))



class C2f_iRMB(nn.Module):
    """Faster Implementation of CSP Bottleneck with 2 convolutions."""

    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        """Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,
        expansion.
        """
        super().__init__()
        self.c = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, 2 * self.c, 1, 1)
        self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))

    def forward(self, x):
        """Forward pass through C2f layer."""
        y = list(self.cv1(x).chunk(2, 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

    def forward_split(self, x):
        """Forward pass using split() instead of chunk()."""
        y = list(self.cv1(x).split((self.c, self.c), 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))





if __name__ == "__main__":


    # Generating Sample image
    image_size = (1, 64, 640, 640)
    image = torch.rand(*image_size)

    # Model
    model = iRMB(64, 64)

    out = model(image)
    print(len(out))


四、手把手教你添加iRMB和C2f_iRMB机制 

4.1 步骤一

首先我们找到如下的目录'ultralytics/nn/modules',然后在这个目录下创建一个py文件,名字可以根据你自己的习惯起,然后将iRMB和C2f_iRMB的核心代码复制进去。

4.2 步骤二

之后我们找到'ultralytics/nn/tasks.py'文件,在其中注册我们的iRMB和C2f_iRMB模块。

首先我们需要在文件的开头导入我们的iRMB和C2f_iRMB模块,如下图所示->

​​

4.3 步骤三

我们找到parse_model这个方法,可以用搜索(Ctrl + F)也可以自己手动找,大概在六百多行吧。 我们找到如下的地方,然后将iRMB和C2f_iRMB添加进去即可,模仿我添加即可。

​​

        elif m in {iRMB}:
            args = [ch[f],  ch[f]]

到此我们就注册成功了。


五、iRMB和C2f_iRMB的yaml文件和运行记录

下面推荐几个版本的yaml文件给大家,大家可以复制进行训练,但是组合用很多具体那种最有效果都不一定,针对不同的数据集效果也不一样,我下面推荐了几种我自己认为可能有效果的配合方式,你也可以自己进行组合。


5.1 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. 'model=yolov8n.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 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOP

# YOLOv8.0 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

# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f_iRMB, [512]]  # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f_iRMB, [256]]  # 15 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f_iRMB, [512]]  # 18 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f_iRMB, [1024]]  # 21 (P5/32-large)

  - [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)


5.2 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. 'model=yolov8n.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 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOP

# YOLOv8.0 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_iRMB, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f_iRMB, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f_iRMB, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f_iRMB, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]  # 9

# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f_iRMB, [512]]  # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f_iRMB, [256]]  # 15 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f_iRMB, [512]]  # 18 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f_iRMB, [1024]]  # 21 (P5/32-large)

  - [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)


5.3 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. 'model=yolov8n.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 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOP

# YOLOv8.0 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

# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]  # 15 (P3/8-small)
  - [-1, 1, iRMB, []]  # 16

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 19 (P4/16-medium)
  - [-1, 1, iRMB, []]  # 20

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 23 (P5/32-large)
  - [-1, 1, iRMB, []]  # 24

  - [[16, 20, 24], 1, Detect, [nc]]  # Detect(P3, P4, P5)

5.4 推荐iRMB可添加的位置 

在YOLOv8种我们的可以改进的位置有很多,不同添加的位置效果也不同,所以我下面推荐几个添加的位,置大家可以进行参考,当然不一定要按照我推荐的地方添加。

  1. 残差连接中:在残差网络的残差连接中加入注意力机制或者替换其中的卷积

  2. Neck部分:YOLOv8的Neck部分负责特征融合,这里添加注意力机制可以帮助模型更有效地融合不同层次的特征,让模型更关注那些有用的特征

  3. Backbone:可以替换中干网络中的卷积部分

  4. 能添加的位置很多,一篇文章很难全部介绍到,后期我会发文件里面集成上百种的改进机制,然后还有许多融合模块,给大家。


5.5 iRMB的训练过程截图 

大家可以看下面的运行结果和添加的位置所以不存在我发的代码不全或者运行不了的问题大家有问题也可以在评论区评论我看到都会为大家解答(我知道的)。

​​

​​​


五、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~),如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

专栏回顾YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1347916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java超高精度无线定位技术--UWB (超宽带)人员定位系统源码

UWB室内定位技术是一种全新的、与传统通信技术有极大差异的通信新技术。它不需要使用传统通信体制中的载波&#xff0c;而是通过发送和接收具有纳秒或纳秒级以下的极窄脉冲来传输数据&#xff0c;从而具有GHz量级的带宽。 UWB&#xff08;超宽带&#xff09;高精度定位系统是一…

08.哲说建造者模式(Builder Pattern)

“The odds that we’re in ‘base reality’ is one in billions.” —— Elon Musk 这段话出自马斯克在2016年的一次演讲&#xff0c;“人类活在真实世界的几率&#xff0c;可能不到十亿分之一”。此言一出&#xff0c;可谓一石激起千层浪。有人嘲讽马斯克是“语不惊人死不休…

论文阅读——SG-Former

SG-Former: Self-guided Transformer with Evolving Token Reallocation 1. Introduction 方法的核心是利用显著性图&#xff0c;根据每个区域的显著性重新分配tokens。显著性图是通过混合规模的自我关注来估计的&#xff0c;并在训练过程中自我进化。直观地说&#xff0c;我们…

3D视觉-相机选用的原则

鉴于不同技术方案都有其适用的场景&#xff0c;立体相机的选型讲究的原则为“先看用途&#xff0c;再看场景&#xff0c;终评精度”&#xff0c;合适的立体相机在方案中可以起到事半功倍的效果。从用途上来进行划分&#xff0c;三维视觉方案主要应用在两个方向&#xff1a;测量…

PyTorch常用工具(1)数据处理

文章目录 前言1 数据处理1.1 Dataset1.2 DataLoader 前言 在训练神经网络的过程中需要用到很多的工具&#xff0c;最重要的是数据处理、可视化和GPU加速。本章主要介绍PyTorch在这些方面常用的工具模块&#xff0c;合理使用这些工具可以极大地提高编程效率。 由于内容较多&am…

【每日一题】一周中的第几天

文章目录 Tag题目来源解题思路方法一&#xff1a;模拟 写在最后 Tag 【模拟】【数学】【2023-12-30】 题目来源 1185. 一周中的第几天 解题思路 方法一&#xff1a;模拟 思路 题目中的日期是在 1971 到 2100 年之间的有效日期&#xff0c;即 1971-01-01 到 2100-12-31 范围…

Scene Creator

场景创建器是一个方便、易于使用的编辑工具&#xff0c;旨在简化创建新场景的过程。使用场景创建器&#xff0c;您可以选择一个模板场景&#xff0c;定义一个目录来存储您的场景&#xff0c;并在需要时自动将新场景添加到构建中。 下载&#xff1a; ​​Unity资源商店链接 资…

数据结构:第7章:查找(复习)

目录 顺序查找&#xff1a; 折半查找&#xff1a; 二叉排序树&#xff1a; 4. (程序题) 平衡二叉树&#xff1a; 顺序查找&#xff1a; ASL 折半查找&#xff1a; 这里 j 表示 二叉查找树的第 j 层 二叉排序树&#xff1a; 二叉排序树&#xff08;Binary Search Tree&…

李宏毅 自然语言处理(Voice Conversion) 笔记

前一章笔记&#xff1a;李宏毅 自然语言处理&#xff08;Speech Recognition&#xff09; 笔记 引入 什么是voice conversion&#xff1f; 输入一段声音&#xff0c;输出另一段声音&#xff0c;我们希望这两端声音&#xff1a;内容一样&#xff0c;其他方面不一样&#xff08…

6个火爆全网的AI开源项目,用上月10万+

标题月10万可能说的有点夸张和含糊&#xff0c;10万具体指的是你可以利用这些开源项目实现&#xff1a; 访问量10万 收入10万 用户10万 …… 开源项目只是免费的工具&#xff0c;具体怎么实现还需要你根据自己需求去深入运营。这里只是给你推荐一些比较热门的开源项目&…

html-css-js移动端导航栏底部固定+i18n国际化全局

需求&#xff1a;要做一个移动端的仿照小程序的导航栏页面操作&#xff0c;但是这边加上了i18n国家化&#xff0c;由于页面切换的时候会导致国际化失效&#xff0c;所以写了这篇文章 1.效果 切换页面的时候中英文也会跟着改变&#xff0c;不会导致切换后回到默认的语言 2.实现…

【ESP-NOW with ESP32:向多个开发板发送数据(一对多)】

【ESP-NOW with ESP32&#xff1a;向多个开发板发送数据&#xff08;一对多&#xff09;】 1. 项目概况2. 先决条件2.1 环境配置2.2 所需零件 3. 获取主板 MAC 地址4. ESP32 发射器 &#xff08;ESP-NOW&#xff09;4.1 接收方的MAC地址4.2 OnDataSent&#xff08;&#xff09;…

2023-12-16 LeetCode每日一题(统计区间中的整数数目)

2023-12-16每日一题 一、题目编号 2276. 统计区间中的整数数目二、题目链接 点击跳转到题目位置 三、题目描述 给你区间的 空 集&#xff0c;请你设计并实现满足要求的数据结构&#xff1a; **新增&#xff1a;**添加一个区间到这个区间集合中。 **统计&#xff1a;**计算…

Plantuml之甘特图语法介绍(二十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Transformer基本结构

Transformer基本结构 输入部分、编码部分、解码部分、输出部分 1、输入部分 原文本嵌入层及其位置编码器目标文本嵌入层及其位置编码器 位置编码器(PositionalEncoding)&#xff1a;将词汇位置不同可能会产生不同语义的信息加入到词张量中&#xff0c;以弥补位置信息的缺失 …

node版本管理器nvm的下载和使用

介绍 nvm 全名 node.js version management&#xff0c;顾名思义是一个nodejs的版本管理工具。通过它可以安装和切换不同版本的nodejs。 下载和安装 在下载和安装nvm前&#xff0c;需要确保当前电脑没有安装node&#xff0c;否则则需要先把原来的node卸载了。 下载地址&#…

HTML+CSS+JS制作三款雪花酷炫特效

🎀效果展示 🎀代码展示 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html

Fortran 编译后Dll依赖问题(libifcoremd.dll)

在VS里&#xff0c;点击运行按钮&#xff0c;程序正常运行。 在exe文件目录中&#xff0c;双击exe运行&#xff0c;提示缺少libifcoremd.dll文件&#xff0c;经查阅资料和以往的经验&#xff0c;解决方法如下&#xff1a; 红色是默认的&#xff0c;绿色是能够正常运行的。

AcWing算法提高课-2.3.1矩阵距离

算法提高课整理 CSDN个人主页&#xff1a;更好的阅读体验 本文同步发表于 CSDN | 洛谷 | AcWing | 个人博客 原题链接 题目描述 给定一个 01 矩阵&#xff0c;求矩阵中每个元素离 1 的最短曼哈顿距离。 输入格式 第一行两个整数 n , m n,m n,m。 接下来一个 n n n 行 …

跳圈圈^^

欢迎来到程序小院 跳圈圈 玩法&#xff1a;女骑士点击左下按钮越过低处火圈&#xff0c;点击右下按钮越过高处火圈&#xff0c;越过火圈获得分数&#xff0c;快去挑战吧^^。开始游戏https://www.ormcc.com/play/gameStart/235 html <div id"loadicon"><im…