YOLOv11改进系列 | 引入EMO ICCV2023的C3k2_iRMB模块,轻量注意力残差混合块增强C3k2,多尺度分割更稳更准

YOLOv11-seg改进 | C3k2_iRMB轻量注意力残差混合块替换C3k2全流程指南

    • 一、本文简介
      • [原始 C3k2 的局限性](#原始 C3k2 的局限性)
      • 本文改进核心
      • [改进前后参数量 / GFLOPs 对比](#改进前后参数量 / GFLOPs 对比)
    • 二、模块原理详解
      • [2.1 层级结构总览](#2.1 层级结构总览)
      • [2.2 基础组件](#2.2 基础组件)
      • [2.3 iRMB:窗口注意力局部全局融合算子(核心)](#2.3 iRMB:窗口注意力局部全局融合算子(核心))
      • [2.4 iRMB:局部增强 + SE 重标定 + 残差投影](#2.4 iRMB:局部增强 + SE 重标定 + 残差投影)
      • [2.5 C3k2_iRMB:完整 Bottleneck 替换逻辑](#2.5 C3k2_iRMB:完整 Bottleneck 替换逻辑)
    • 三、改进思想与创新点
      • [3.1 背景与动机](#3.1 背景与动机)
      • [3.2 核心创新点](#3.2 核心创新点)
      • [3.3 与现有方案的对比](#3.3 与现有方案的对比)
      • [3.4 在 YOLOv11 框架中的适配设计](#3.4 在 YOLOv11 框架中的适配设计)
    • 四、完整代码
      • [4.1 来自 `ultralytics/nn/extra_modules/attention.py`](#4.1 来自 ultralytics/nn/extra_modules/attention.py)
      • [4.2 来自 `ultralytics/nn/extra_modules/block.py`](#4.2 来自 ultralytics/nn/extra_modules/block.py)
    • 五、手把手配置步骤(三步法)
      • [Step 1:确认 `extra_modules/init.py` 导入(已自动导入,跳过)](#Step 1:确认 extra_modules/__init__.py 导入(已自动导入,跳过))
      • [Step 2:确认 `tasks.py` 注册(已注册,跳过)](#Step 2:确认 tasks.py 注册(已注册,跳过))
      • [Step 3:训练代码](#Step 3:训练代码)
    • [六、YAML 配置文件](#六、YAML 配置文件)
      • [变体一:全面替换(Backbone + Head 全部替换,推荐作为首选配置)](#变体一:全面替换(Backbone + Head 全部替换,推荐作为首选配置))
      • [变体二:仅替换 Backbone(Head 保留原版 C3k2)](#变体二:仅替换 Backbone(Head 保留原版 C3k2))
      • [变体三:精度优先模式(深层全部使用 c3k=True 强力配置)](#变体三:精度优先模式(深层全部使用 c3k=True 强力配置))
      • [变体四:混合模式(浅层保持原版 C3k2,深层引入 iRMB)](#变体四:混合模式(浅层保持原版 C3k2,深层引入 iRMB))
      • [变体五:P2 四尺度版(增加 P2 输出层,适合小目标密集场景)](#变体五:P2 四尺度版(增加 P2 输出层,适合小目标密集场景))
    • 七、常见问题(FAQ)
      • [7.1 `NameError: name 'C3k2_iRMB' is not defined`](#7.1 NameError: name 'C3k2_iRMB' is not defined)
      • [7.2 需要安装哪些第三方依赖](#7.2 需要安装哪些第三方依赖)
      • [7.3 `Segment` 改成 `Detect` 怎么写](#7.3 Segment 改成 Detect 怎么写)
      • [7.4 YAML 参数怎么理解](#7.4 YAML 参数怎么理解)
    • 八、总结

专栏系列 :YOLOv11 注意力/精度改进实战
改进点 :将 YOLOv11-seg 中的 C3k2 替换为 C3k2_iRMB,引入 EMO 中的 iRMB 轻量注意力残差混合块,以窗口注意力、深度卷积局部建模和 SE 通道重标定联合增强特征表达能力,在较小参数与算力增幅下提升复杂背景、多尺度与实例边界场景下的分割表现。


一、本文简介

本文引入 EMO(ICCV 2023) 中的 iRMB 模块,将其嵌入 YOLOv11 的 C3k2 结构形成 C3k2_iRMB。根据仓库文档 YOLOV11配置文件.md103 项说明,当前配置来源为 EMO ICCV2023 中的 iRMB 。从实现上看,这个模块并不是简单加一个注意力层,而是将窗口自注意力、深度卷积局部增强、SE 通道重标定和残差投影组合到一个轻量残差块中,用来替换原始 C3k2 中的普通 Bottleneck

原始 C3k2 的局限性

YOLOv11 默认 C3k2 结构高效稳定,但在实例分割任务中仍然存在几个典型问题:

  1. 局部与全局建模割裂:标准卷积更擅长局部聚合,缺少显式的局部全局关系建模能力。
  2. 特征选择能力不足 :原始 Bottleneck 缺少动态注意力与通道重标定机制。
  3. 复杂场景表达有限:面对遮挡、小目标、复杂背景和精细边界时,基础卷积块的表达能力往往不够。

本文改进核心

C3k2_iRMB 在不改变 C2f/C3k2 外层聚合框架的前提下,仅替换内部单元为 iRMB,主要引入三点增强:

  1. 窗口注意力建模:在局部窗口中完成轻量多头注意力,增强局部范围内的全局依赖感知。
  2. 局部卷积分支补强 :注意力输出后再经过深度卷积 conv_local 做局部细节增强。
  3. SE 通道重标定 + 残差投影:进一步提升关键通道响应,增强特征表达能力。

改进前后参数量 / GFLOPs 对比

下表结果来自项目环境下的 model.info() 实测:

python 复制代码
from ultralytics import YOLO
model = YOLO("ultralytics/cfg/models/11-seg/light_impro/yolo11-seg-C3k2-iRMB.yaml")
model.info()
模型 参数量 GFLOPs 说明
yolo11n-seg 2.46M2,460,112 9.6 基线
yolo11n-seg-C3k2-iRMB 2.57M2,571,808 10.0 2026-04-21 实测
变化 +111,696+4.54% +0.4+4.17% 精度改进方向

当前环境下,该模型的 model.info() 实测结果为 10.0 GFLOPs

从机制和实测指标看,C3k2_iRMB 属于轻量精度增强型替换块 ,比很多重注意力模块更克制,但表达力明显强于普通 Bottleneck


二、模块原理详解

2.1 层级结构总览

text 复制代码
C3k2_iRMB
├─ 继承自 C3k2
│  ├─ 继承自 C2f
│  │  ├─ cv1: Conv(c1, 2c, 1)
│  │  ├─ cv2: Conv((2+n)c, c2, 1)
│  │  └─ m: ModuleList(...)
│  └─ 将原始 Bottleneck 替换为 iRMB
├─ C3k_iRMB
│  └─ 在 C3k 内部堆叠 iRMB
└─ iRMB
   ├─ norm: BatchNorm2d
   ├─ qk: 1x1 Conv,生成 Q/K
   ├─ v: 1x1 Conv + act,生成 V
   ├─ window attention
   │  ├─ padding
   │  ├─ rearrange to windows
   │  ├─ q @ k^T * scale
   │  └─ softmax + dropout
   ├─ conv_local: depthwise Conv
   ├─ se: SEAttention
   ├─ proj: 1x1 Conv
   └─ drop_path + residual

2.2 基础组件

SEAttention

SEAttention 是标准的 squeeze-excitation 通道注意力,核心形式为:

z = G A P ( x ) z = \mathrm{GAP}(x) z=GAP(x)

s = σ ( W 2 ( δ ( W 1 ( z ) ) ) ) s = \sigma(W_2(\delta(W_1(z)))) s=σ(W2(δ(W1(z))))

y = x ⊙ s y = x \odot s y=x⊙s

它的作用是对重要通道进行增强,对冗余通道进行抑制。

DropPath

DropPath 在残差分支上实现随机深度,训练阶段对不同样本按概率丢弃整条残差路径,有助于稳定深层网络训练并增强泛化能力。

窗口划分与 rearrange

iRMB 内部使用 einops.rearrange 把特征图划分为窗口,再在窗口内做注意力。设窗口大小为 M M M,则原始输入:

X ∈ R B × C × H × W X \in \mathbb{R}^{B \times C \times H \times W} X∈RB×C×H×W

会被重排为多个局部窗口,每个窗口内部进行多头注意力建模。这样可把全局注意力复杂度控制在局部范围内,避免直接在整张特征图上做全局注意力的高开销。

2.3 iRMB:窗口注意力局部全局融合算子(核心)

iRMB 的核心是"窗口注意力 + 局部卷积 + 通道重标定"的混合设计。

attn_s=True 时,它的注意力部分核心公式为:

Q , K = C o n v 1 × 1 ( X ) Q, K = \mathrm{Conv}_{1\times1}(X) Q,K=Conv1×1(X)

V = C o n v 1 × 1 ( X ) V = \mathrm{Conv}_{1\times1}(X) V=Conv1×1(X)

A t t n ( Q , K , V ) = S o f t m a x ( Q K T d ) V \mathrm{Attn}(Q, K, V)=\mathrm{Softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V Attn(Q,K,V)=Softmax(d QKT)V

这里的注意力不是全局展开,而是限制在窗口内部,因此更适合检测/分割这类高分辨率特征图场景。

2.4 iRMB:局部增强 + SE 重标定 + 残差投影

注意力完成后,iRMB 会继续执行局部卷积增强:

X l o c a l = C o n v L o c a l ( X a t t n ) X_{local} = \mathrm{ConvLocal}(X_{attn}) Xlocal=ConvLocal(Xattn)

再通过 SE 模块完成通道重标定:

X s e = S E ( X l o c a l ) X_{se} = \mathrm{SE}(X_{local}) Xse=SE(Xlocal)

如果满足跳连条件,则形成:

X ′ = X a t t n + X s e X' = X_{attn} + X_{se} X′=Xattn+Xse

最后再通过投影卷积和 DropPath:

Y = P r o j ( X ′ ) Y = \mathrm{Proj}(X') Y=Proj(X′)

o u t = X + D r o p P a t h ( Y ) \mathrm{out} = X + \mathrm{DropPath}(Y) out=X+DropPath(Y)

这种做法的价值在于:
先用注意力建模局部窗口内的关系,再用深度卷积补强局部纹理,再用 SE 做通道筛选,最终通过残差方式稳定输出。

2.5 C3k2_iRMB:完整 Bottleneck 替换逻辑

C3k2_iRMB 依然沿用 C2f/C3k2 的外层拼接逻辑,只是把内部 Bottleneck 替换为 iRMB

y 0 , y 1 = S p l i t ( c v 1 ( x ) ) y_0, y_1 = \mathrm{Split}(\mathrm{cv1}(x)) y0,y1=Split(cv1(x))

y i + 1 = i R M B ( y i ) y_{i+1} = \mathrm{iRMB}(y_i) yi+1=iRMB(yi)

o u t = c v 2 ( C o n c a t ( y 0 , y 1 , ... ) ) \mathrm{out} = \mathrm{cv2}(\mathrm{Concat}(y_0, y_1, \ldots)) out=cv2(Concat(y0,y1,...))

因此:

  1. 输入输出尺寸完全兼容;
  2. Neck / Head 结构无需大改;
  3. 只需替换 YAML 中的模块名即可完成接入。

三、改进思想与创新点

3.1 背景与动机

实例分割任务需要同时兼顾局部边缘细节与区域上下文一致性。原始 C3k2 主要靠卷积堆叠做特征提取,虽然效率高,但对复杂场景的上下文建模能力有限。EMO 提出的 iRMB 则试图在保持高效的前提下,将注意力、卷积和通道增强融合到一个轻量残差块中。

将其迁移到 YOLOv11 的动机很直接:

  1. 保留 YOLO 骨架的效率优势;
  2. 用窗口注意力补足局部卷积对中程依赖建模不足的问题;
  3. 用局部卷积分支和 SE 模块补强边缘与通道表达。

3.2 核心创新点

创新点一:窗口级轻量注意力

相较于全局自注意力,iRMB 采用窗口注意力:

A t t n ( Q , K , V ) = S o f t m a x ( Q K T d ) V \mathrm{Attn}(Q, K, V)=\mathrm{Softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V Attn(Q,K,V)=Softmax(d QKT)V

但注意力仅在局部窗口内部完成,因此显著降低复杂度,更适合检测与分割骨干。

创新点二:注意力后追加局部卷积补强

很多注意力块容易牺牲卷积的局部纹理优势,而 iRMB 在注意力后保留:

C o n v L o c a l ( X ) \mathrm{ConvLocal}(X) ConvLocal(X)

并与跳连叠加,使得它不会过于偏向纯 token mixer,而是兼顾局部结构信息。

创新点三:SE 通道重标定

SEAttention 带来的通道筛选可以增强对重要特征的响应,这对复杂纹理、小目标和实例边界尤为有帮助。

创新点四:残差投影与随机深度

通过:

o u t = x + D r o p P a t h ( P r o j ( x ′ ) ) \mathrm{out}=x+\mathrm{DropPath}(\mathrm{Proj}(x')) out=x+DropPath(Proj(x′))

iRMB 保持了残差块的训练稳定性,同时通过 DropPath 提升了深层训练的鲁棒性。

3.3 与现有方案的对比

方法 局部建模 全局上下文 通道筛选 复杂度水平 适用场景
C3k2 原版 常规卷积 通用检测 / 分割
C3k2_LFE Shift 局部位移建模 低到中 纹理与边缘增强
C3k2_LEGM 窗口注意力 + MLP 动态重标定 复杂背景与多尺度分割
C3k2_iRMB 注意力 + depthwise local conv 中到强 SE 多尺度分割、遮挡、小目标与复杂边界
全局 Transformer block 弱局部 很强 可选 高算力场景

3.4 在 YOLOv11 框架中的适配设计

当前仓库中导入与注册已经完成:

  1. ultralytics/nn/extra_modules/__init__.py 已有 from .block import *
  2. ultralytics/nn/tasks.pyC3K2_CLASS 已包含 C3k2_iRMB
  3. 目标 YAML 已经可以被 YOLO() 正常构建。

因此在当前仓库环境下,不需要额外补导入或补注册。


四、完整代码

为保证和仓库源码逐字一致,下面代码块不在块内加入人工中文注释,解释放在代码块外。

4.1 来自 ultralytics/nn/extra_modules/attention.py

python 复制代码
class SEAttention(nn.Module):
    def __init__(self, channel=512,reduction=16):
        super().__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel, bias=False),
            nn.Sigmoid()
        )

    def init_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                init.kaiming_normal_(m.weight, mode='fan_out')
                if m.bias is not None:
                    init.constant_(m.bias, 0)
            elif isinstance(m, nn.BatchNorm2d):
                init.constant_(m.weight, 1)
                init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                init.normal_(m.weight, std=0.001)
                if m.bias is not None:
                    init.constant_(m.bias, 0)

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y.expand_as(x)

4.2 来自 ultralytics/nn/extra_modules/block.py

python 复制代码
class DropPath(nn.Module):
    """Drop paths (Stochastic Depth) per sample  (when applied in main path of residual blocks).
    """
    
    def __init__(self, drop_prob=None):
        super(DropPath, self).__init__()
        self.drop_prob = drop_prob
    
    def forward(self, x):
        return drop_path(x, self.drop_prob, self.training)
python 复制代码
class iRMB(nn.Module):
	def __init__(self, dim_in, dim_out, norm_in=True, has_skip=True, exp_ratio=1.0,
				 act=True, v_proj=True, dw_ks=3, stride=1, dilation=1, se_ratio=0.0, dim_head=16, 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 = nn.BatchNorm2d(dim_in) if norm_in else nn.Identity()
		self.act = Conv.default_act if act 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 = nn.Conv2d(dim_in, int(dim_in * 2), 1, bias=qkv_bias)
			self.v = nn.Sequential(
				nn.Conv2d(dim_in, dim_mid, kernel_size=1, groups=self.num_head if v_group else 1, bias=qkv_bias),
				self.act
			)
			self.attn_drop = nn.Dropout(attn_drop)
		else:
			if v_proj:
				self.v = nn.Sequential(
					nn.Conv2d(dim_in, dim_mid, kernel_size=1, groups=self.num_head if v_group else 1, bias=qkv_bias),
					self.act
				)
			else:
				self.v = nn.Identity()
		self.conv_local = Conv(dim_mid, dim_mid, k=dw_ks, s=stride, d=dilation, g=dim_mid)
		self.se = SEAttention(dim_mid, reduction=se_ratio) if se_ratio > 0.0 else nn.Identity()
		
		self.proj_drop = nn.Dropout(drop)
		self.proj = nn.Conv2d(dim_mid, dim_out, kernel_size=1)
		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

class C3k_iRMB(C3k):
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5, k=3):
        super().__init__(c1, c2, n, shortcut, g, e, k)
        c_ = int(c2 * e)  # hidden channels
        self.m = nn.Sequential(*(iRMB(c_, c_) for _ in range(n)))

class C3k2_iRMB(C3k2):
    def __init__(self, c1, c2, n=1, c3k=False, e=0.5, g=1, shortcut=True):
        super().__init__(c1, c2, n, c3k, e, g, shortcut)
        self.m = nn.ModuleList(C3k_iRMB(self.c, self.c, 2, shortcut, g) if c3k else iRMB(self.c, self.c) for _ in range(n))

五、手把手配置步骤(三步法)

Step 1:确认 extra_modules/__init__.py 导入(已自动导入,跳过)

当前仓库 ultralytics/nn/extra_modules/__init__.py 已包含 from .block import *,因此 C3k2_iRMB 无需额外导入。

Step 2:确认 tasks.py 注册(已注册,跳过)

当前仓库 ultralytics/nn/tasks.pyC3K2_CLASS 中已经注册 C3k2_iRMB,无需额外补注册。

Step 3:训练代码

python 复制代码
from ultralytics import YOLO

# 加载改进模型
model = YOLO("ultralytics/cfg/models/11-seg/light_impro/yolo11-seg-C3k2-iRMB.yaml")

# 查看参数量和 GFLOPs
model.info()

# 开始训练
model.train(
    data="coco8-seg.yaml",
    epochs=100,
    imgsz=640,
    batch=16,
    device=0
)

六、YAML 配置文件

变体一:全面替换(Backbone + Head 全部替换,推荐作为首选配置)

适用场景:希望完整引入 iRMB 的注意力 + 局部卷积建模能力。

实测参数量:2.57M / 10.0 GFLOPs(n scale)

yaml 复制代码
# YOLO11-seg C3k2_iRMB full replacement
nc: 80
scales:
  n: [0.50, 0.25, 1024]
  s: [0.50, 0.50, 1024]
  m: [0.50, 1.00, 512]
  l: [1.00, 1.00, 512]
  x: [1.00, 1.50, 512]

backbone:
  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 2, C3k2_iRMB, [256, False, 0.25]] # 2
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2_iRMB, [512, False, 0.25]] # 4
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2_iRMB, [512, True]] # 6
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2_iRMB, [1024, True]] # 8
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 11
  - [[-1, 6], 1, Concat, [1]] # 12 cat backbone P4
  - [-1, 2, C3k2_iRMB, [512, False]] # 13
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 14
  - [[-1, 4], 1, Concat, [1]] # 15 cat backbone P3
  - [-1, 2, C3k2_iRMB, [256, False]] # 16 (P3/8-small)
  - [-1, 1, Conv, [256, 3, 2]] # 17
  - [[-1, 13], 1, Concat, [1]] # 18 cat head P4
  - [-1, 2, C3k2_iRMB, [512, False]] # 19 (P4/16-medium)
  - [-1, 1, Conv, [512, 3, 2]] # 20
  - [[-1, 10], 1, Concat, [1]] # 21 cat head P5
  - [-1, 2, C3k2_iRMB, [1024, True]] # 22 (P5/32-large)
  - [[16, 19, 22], 1, Segment, [nc, 32, 256]] # 23 Segment(P3, P4, P5)

变体二:仅替换 Backbone(Head 保留原版 C3k2)

适用场景:优先验证 Backbone 侧引入 iRMB 后的收益。

yaml 复制代码
# YOLO11-seg C3k2_iRMB backbone only
nc: 80
scales:
  n: [0.50, 0.25, 1024]
  s: [0.50, 0.50, 1024]
  m: [0.50, 1.00, 512]
  l: [1.00, 1.00, 512]
  x: [1.00, 1.50, 512]

backbone:
  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 2, C3k2_iRMB, [256, False, 0.25]] # 2
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2_iRMB, [512, False, 0.25]] # 4
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2_iRMB, [512, True]] # 6
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2_iRMB, [1024, True]] # 8
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 11
  - [[-1, 6], 1, Concat, [1]] # 12 cat backbone P4
  - [-1, 2, C3k2, [512, False]] # 13
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 14
  - [[-1, 4], 1, Concat, [1]] # 15 cat backbone P3
  - [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)
  - [-1, 1, Conv, [256, 3, 2]] # 17
  - [[-1, 13], 1, Concat, [1]] # 18 cat head P4
  - [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)
  - [-1, 1, Conv, [512, 3, 2]] # 20
  - [[-1, 10], 1, Concat, [1]] # 21 cat head P5
  - [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)
  - [[16, 19, 22], 1, Segment, [nc, 32, 256]] # 23 Segment(P3, P4, P5)

变体三:精度优先模式(深层全部使用 c3k=True 强力配置)

适用场景:打开 c3k=True,进一步增强内部堆叠表达能力。

yaml 复制代码
# YOLO11-seg C3k2_iRMB accuracy-first
nc: 80
scales:
  n: [0.50, 0.25, 1024]
  s: [0.50, 0.50, 1024]
  m: [0.50, 1.00, 512]
  l: [1.00, 1.00, 512]
  x: [1.00, 1.50, 512]

backbone:
  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 2, C3k2_iRMB, [256, True, 0.25]] # 2
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2_iRMB, [512, True, 0.25]] # 4
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2_iRMB, [512, True]] # 6
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2_iRMB, [1024, True]] # 8
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 11
  - [[-1, 6], 1, Concat, [1]] # 12 cat backbone P4
  - [-1, 2, C3k2_iRMB, [512, True]] # 13
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 14
  - [[-1, 4], 1, Concat, [1]] # 15 cat backbone P3
  - [-1, 2, C3k2_iRMB, [256, True]] # 16 (P3/8-small)
  - [-1, 1, Conv, [256, 3, 2]] # 17
  - [[-1, 13], 1, Concat, [1]] # 18 cat head P4
  - [-1, 2, C3k2_iRMB, [512, True]] # 19 (P4/16-medium)
  - [-1, 1, Conv, [512, 3, 2]] # 20
  - [[-1, 10], 1, Concat, [1]] # 21 cat head P5
  - [-1, 2, C3k2_iRMB, [1024, True]] # 22 (P5/32-large)
  - [[16, 19, 22], 1, Segment, [nc, 32, 256]] # 23 Segment(P3, P4, P5)

变体四:混合模式(浅层保持原版 C3k2,深层引入 iRMB)

适用场景:兼顾速度与精度,只在中深层使用 iRMB。

yaml 复制代码
# YOLO11-seg C3k2_iRMB hybrid
nc: 80
scales:
  n: [0.50, 0.25, 1024]
  s: [0.50, 0.50, 1024]
  m: [0.50, 1.00, 512]
  l: [1.00, 1.00, 512]
  x: [1.00, 1.50, 512]

backbone:
  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 2, C3k2, [256, False, 0.25]] # 2
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2_iRMB, [512, False, 0.25]] # 4
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2_iRMB, [512, True]] # 6
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2_iRMB, [1024, True]] # 8
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 11
  - [[-1, 6], 1, Concat, [1]] # 12 cat backbone P4
  - [-1, 2, C3k2_iRMB, [512, False]] # 13
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 14
  - [[-1, 4], 1, Concat, [1]] # 15 cat backbone P3
  - [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)
  - [-1, 1, Conv, [256, 3, 2]] # 17
  - [[-1, 13], 1, Concat, [1]] # 18 cat head P4
  - [-1, 2, C3k2_iRMB, [512, False]] # 19 (P4/16-medium)
  - [-1, 1, Conv, [512, 3, 2]] # 20
  - [[-1, 10], 1, Concat, [1]] # 21 cat head P5
  - [-1, 2, C3k2_iRMB, [1024, True]] # 22 (P5/32-large)
  - [[16, 19, 22], 1, Segment, [nc, 32, 256]] # 23 Segment(P3, P4, P5)

变体五:P2 四尺度版(增加 P2 输出层,适合小目标密集场景)

适用场景:小目标较多,希望把 P2/4 也接入分割输出。

注意:P2 版层索引重新计算,Segment 输出使用 [19, 22, 25, 28]

yaml 复制代码
# YOLO11-seg C3k2_iRMB P2 4-scale
nc: 80
scales:
  n: [0.50, 0.25, 1024]
  s: [0.50, 0.50, 1024]
  m: [0.50, 1.00, 512]
  l: [1.00, 1.00, 512]
  x: [1.00, 1.50, 512]

backbone:
  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 2, C3k2_iRMB, [256, False, 0.25]] # 2
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2_iRMB, [512, False, 0.25]] # 4
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2_iRMB, [512, True]] # 6
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2_iRMB, [1024, True]] # 8
  - [-1, 1, SPPF, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 11
  - [[-1, 6], 1, Concat, [1]] # 12 cat backbone P4
  - [-1, 2, C3k2_iRMB, [512, False]] # 13
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 14
  - [[-1, 4], 1, Concat, [1]] # 15 cat backbone P3
  - [-1, 2, C3k2_iRMB, [256, False]] # 16 (P3/8-small)
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]] # 17
  - [[-1, 2], 1, Concat, [1]] # 18 cat backbone P2
  - [-1, 2, C3k2_iRMB, [128, False]] # 19 (P2/4-xsmall)
  - [-1, 1, Conv, [256, 3, 2]] # 20
  - [[-1, 16], 1, Concat, [1]] # 21 cat head P3
  - [-1, 2, C3k2_iRMB, [256, False]] # 22 (P3/8-medium)
  - [-1, 1, Conv, [256, 3, 2]] # 23
  - [[-1, 13], 1, Concat, [1]] # 24 cat head P4
  - [-1, 2, C3k2_iRMB, [512, False]] # 25 (P4/16-medium)
  - [-1, 1, Conv, [512, 3, 2]] # 26
  - [[-1, 10], 1, Concat, [1]] # 27 cat head P5
  - [-1, 2, C3k2_iRMB, [1024, True]] # 28 (P5/32-large)
  - [[19, 22, 25, 28], 1, Segment, [nc, 32, 256]] # 29 Segment(P2, P3, P4, P5)

七、常见问题(FAQ)

7.1 NameError: name 'C3k2_iRMB' is not defined

优先检查以下几项:

  1. ultralytics/nn/extra_modules/block.py 中是否存在 C3k2_iRMB
  2. ultralytics/nn/extra_modules/__init__.py 是否仍保留 from .block import *
  3. ultralytics/nn/tasks.pyC3K2_CLASS 是否包含 C3k2_iRMB

7.2 需要安装哪些第三方依赖

iRMB 这条链路至少需要:

bash 复制代码
pip install einops timm

因为:

  1. block.py 顶部使用了 from einops import rearrange, reduce
  2. 仓库整体环境中使用了 timm 相关组件

7.3 Segment 改成 Detect 怎么写

只需要替换最后一层:

  1. 三尺度版改成 [[16, 19, 22], 1, Detect, [nc]]
  2. P2 四尺度版改成 [[19, 22, 25, 28], 1, Detect, [nc]]

7.4 YAML 参数怎么理解

C3k2_iRMB 的 YAML 参数与普通 C3k2 一致:

写法 含义 示例
[256, False, 0.25] c2=256, c3k=False, e=0.25 Backbone 浅层
[512, False] c2=512, c3k=False, e=0.5 Head 常用
[512, True] c2=512, c3k=True, e=0.5 精度优先堆叠版

其中:

  1. c2 是输出通道数;
  2. c3k=True 时内部切换到 C3k_iRMB 堆叠;
  3. e 是隐藏通道扩展比。

八、总结

对比维度 原始 C3k2 C3k2_iRMB
参数量(n scale) 2.46M 2.57M(+4.54%)
GFLOPs(n scale) 9.6 10.0(+4.17%)
局部建模方式 常规卷积堆叠 窗口注意力后接 depthwise conv_local 局部增强
上下文建模能力 较弱 窗口级自注意力增强中程依赖建模
通道筛选机制 SEAttention 通道重标定
残差稳定性 基础残差 DropPath + residual projection
归一化格式 BN(BCHW) BN(BCHW),无额外格式切换成本
论文来源 YOLOv11 原版 EMO(ICCV 2023)中的 iRMB
适用场景 通用目标检测 / 分割 小目标、多尺度、复杂背景、遮挡和精细实例分割

总结C3k2_iRMB 将 EMO(ICCV 2023)中的 iRMB 引入 YOLOv11,核心是用窗口注意力补足卷积块对中程上下文建模的不足,再通过深度卷积局部增强和 SE 通道筛选提升细节表达。在 n scale 下参数量增加 4.54%(+0.11M),GFLOPs 增加 4.17%(+0.4),属于增幅较小但结构收益明确的精度增强型替换块。对于多尺度实例分割、复杂背景、小目标和遮挡场景,这种模块通常比单纯卷积 Bottleneck 更有表达优势。

如果这篇文章对你有帮助,欢迎点赞、收藏、在评论区交流你实际训练后的涨点情况,也欢迎关注我的 YOLOv11 改进专栏,后面还会继续更新更多能直接落地的检测/分割结构改法。

相关推荐
小超同学你好2 小时前
Transformer 27. Vision Transformer(ViT):把图像当作「词序列」的编码器
人工智能·深度学习·transformer
赋创小助手3 小时前
RTX PRO 6000 vs RTX 5090:从一组230B模型测试数据谈企业级推理选型
服务器·人工智能·科技·深度学习·自然语言处理
不才小强3 小时前
深度学习模型部署实战指南
人工智能·深度学习
森诺Alyson3 小时前
前沿技术借鉴研讨-2026.4.16(视觉语言模型/医学影像文本多模态对齐)
论文阅读·人工智能·经验分享·计算机视觉·语言模型
思绪无限3 小时前
YOLOv5至YOLOv12升级:车型识别与计数系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·yolov12·yolo全家桶·车型识别与计数
思绪无限3 小时前
YOLOv5至YOLOv12升级:田间杂草检测系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·田间杂草检测·yolov12·yolo全家桶
YOULANSHENGMENG4 小时前
深度学习的一些基础知识
人工智能·深度学习
思绪无限4 小时前
YOLOv5至YOLOv12升级:常见车型识别系统的设计与实现(完整代码+界面+数据集项目)
人工智能·深度学习·yolo·目标检测·目标跟踪·yolov12·yolo全家桶
BFT白芙堂4 小时前
基于 AR 阻抗可视化的 Franka Research3 机械臂遥操作设计与应用
人工智能·深度学习·机器学习·机器人·ar·franka