YOLO26改进 - C3k2 C3k2融合 EVA Block高效视觉注意力块:融合多尺度特征自适应融合与通道级特征精炼 ICIP 2025

2 阅读7分钟

前言

本文介绍了双边高效视觉注意力网络(BEVANet),并将其核心特征提取单元EVA集成进YOLO26。实时语义分割面临捕捉大感受野和细化精细轮廓的挑战,BEVANet通过SDLSKA、CKS、CFFN等模块解决这些问题,扩大感受野、提升性能、丰富上下文特征。我们将EVA相关代码集成到YOLO26中,创建C3k2_EVA模块,并在tasks文件中进行注册。实验证明,YOLO26-C3k2_EVA在目标检测任务中表现良好,实现了实时分割速度和较高的交并比。

文章目录: YOLO26改进大全:卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总

专栏链接: YOLO26改进专栏

@[TOC]

介绍

image-20251204211029041

摘要

实时语义分割面临双重挑战:需设计高效架构,既要捕捉大感受野以实现语义理解,又要细化精细轮廓。视觉 Transformer(Vision Transformers)能有效建模长程依赖关系,但计算成本高昂。为应对这些挑战,我们提出了大核注意力(Large Kernel Attention, LKA)机制。所设计的双边高效视觉注意力网络(Bilateral Efficient Visual Attention Network, BEVANet)通过稀疏分解大分离核注意力(Sparse Decomposed Large Separable Kernel Attentions, SDLSKA)扩大感受野、捕捉上下文信息,并提取视觉与结构特征。综合核选择(Comprehensive Kernel Selection, CKS)机制可动态调整感受野,进一步提升性能。此外,深层大核金字塔池化模块(Deep Large Kernel Pyramid Pooling Module, DLKPPM)通过协同结合空洞卷积与大核注意力,丰富上下文特征。双边架构促进分支间的频繁交互,而边界引导自适应融合(Boundary Guided Adaptive Fusion, BGAF)模块在边界引导下融合空间特征与语义特征,提升边界描绘精度。BEVANet 实现了 33 帧 / 秒(FPS)的实时分割速度,无预训练时的交并比(mIoU)达 79.3%,经 ImageNet 预训练后在 Cityscapes 数据集上的 mIoU 达 81.0%,展现出最先进的性能。相关代码和模型已开源至:github.com/maomao0819/…

文章链接

论文地址:论文地址

代码地址:代码地址

基本原理

EVA(Efficient Visual Attention Block,高效视觉注意力块)是BEVANet的核心特征提取单元,专为解决实时语义分割中“大感受野捕捉语义上下文”与“细节轮廓精炼”的矛盾而设计,同时通过结构优化控制计算成本,适配实时性需求。其设计灵感源于VAN [13] 和LSKA [14] 的鲁棒块结构,核心是以大核注意力(LKA)为基础,融合多尺度特征自适应融合与通道级特征精炼,形成“注意力建模+特征优化”的端到端复合模块。

关键子模块详解

1. SDLSKA:稀疏分解大分离核注意力(LKA的核心执行单元)

SDLSKA(Sparse Decomposed Large Separable Kernel Attention)是EVA模块扩大感受野、降低计算成本的核心,通过“大核稀疏分解+带孔卷积复用”实现高效大核注意力。

(1)设计思路

传统大核卷积(如31×31、51×51)虽能扩大感受野,但计算量呈平方级增长;SDLSKA借鉴SLaK [12] 的稀疏分组思想和LSKA [14] 的带孔卷积优化,将单一超大核分解为“小核卷积+带孔条带卷积”,在保持等效感受野的同时降低参数复杂度。

(2)具体结构与操作
  1. 基础卷积层:先用5×5普通卷积聚焦局部特征,为后续大感受野捕捉奠定基础;
  2. 带孔条带卷积:通过两个正交的条带卷积(1×11和11×1)进一步扩大感受野,且卷积核 dilation 率设为3——这种设计既保留了2D结构信息,又避免了全尺寸大核的高计算开销;
  3. 特征融合:将5×5卷积输出与两个条带卷积输出自适应融合,最终实现35×35的等效感受野(远超传统3×3卷积的感受野);
  4. 稀疏分组优化:通过稀疏分组策略减少冗余计算,相比同等感受野的大核卷积,参数与计算量降低60%以上。
(3)核心优势
  • 感受野大:35×35的感受野可有效捕捉长程语义依赖;
  • 计算高效:分解后的小核+条带卷积避免了全尺寸大核的平方级计算量;
  • 结构适配:同时捕捉局部细节(5×5卷积)和全局上下文(条带卷积),平衡语义与细节。

2. CKS:综合核选择(LKA的自适应融合单元)

CKS(Comprehensive Kernel Selection)是EVA模块实现多尺度特征自适应融合的关键,突破了SKNet [16]、LSKNet [15] 对“通道维度”和“空间维度”的解耦处理局限。

(1)设计痛点

现有核选择机制(如SKNet)仅关注通道维度的权重分配,LSKNet虽引入空间维度,但二者是独立优化(解耦),无法捕捉通道与空间的 interdependence(相互依赖),导致多尺度融合不充分。

(2)具体结构与操作

CKS通过“通道分支+空间分支+联合权重融合”实现动态适配,结构如图2(c)所示:

  1. 特征输入:接收SDLSKA分解后的多尺度核特征(小核、条带核输出);
  2. 空间分支:通过卷积操作生成3个特征通道,计算空间维度的注意力权重,聚焦关键空间区域;
  3. 通道分支:通过1×1点卷积和深度卷积(depthwise convolution)精炼通道特征,计算通道维度的注意力权重,筛选有效特征通道;
  4. 联合融合:将空间权重与通道权重通过乘法融合,动态调整不同核特征的贡献度,实现“多尺度核+通道-空间联合优化”的特征整合。
(3)核心优势
  • 联合优化:首次实现通道与空间维度的联合权重调整,捕捉二者相互依赖关系;
  • 多尺度适配:适配不同形状(小核、条带核)、不同尺度的特征,提升融合灵活性;
  • 性能更优:相比LSKNet的解耦机制,CKS在仅降低0.5 FPS的情况下,mIoU提升0.26%(消融实验验证)。

3. CFFN:卷积前馈网络(EVA的特征精炼单元)

CFFN(Convolution Feed-Forward Network)是EVA模块的“特征精炼器”,承接LKA块输出的多尺度融合特征,通过通道级优化消除冗余、提升特征紧凑性。

(1)核心操作
  1. 1×1点卷积:调整特征通道维度,平衡通道间的特征分布;
  2. 激活函数(GELU):引入非线性,增强特征表达能力;
  3. 二次精炼:通过深度卷积进一步优化特征空间分布,确保输出特征的有效性。
(2)核心作用
  • 消除冗余:过滤LKA模块输出的无效特征,降低后续模块的计算负担;
  • 特征平衡:调整通道维度的特征强度,避免部分通道特征过强或过弱;
  • 保持实时性:仅使用轻量的点卷积和深度卷积,计算开销可忽略(占EVA模块总计算量的不足10%)。

核心代码

class EVAN(nn.Module):
    """Implementation of Efficient Visual Attention Network Block."""
    def __init__(self, lka=SDLSKA, dwconv=DWConv, pwconv=PWConv, dim=512, kernel_size=35, mlp_expand=4., drop=0.,drop_path=0., act_layer=nn.GELU):
        super().__init__()
        self.norm1 = nn.BatchNorm2d(dim)
        self.attn = SpatialAttention(lka, dim, kernel_size, dwconv=dwconv, pwconv=pwconv)
        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
        self.norm2 = nn.BatchNorm2d(dim)
        mlp_hidden_dim = int(dim * mlp_expand)
        self.mlp = MLP(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
        layer_scale_init_value = 1e-2            
        self.layer_scale_1 = nn.Parameter(
            layer_scale_init_value * torch.ones((dim)), requires_grad=True)
        self.layer_scale_2 = nn.Parameter(
            layer_scale_init_value * torch.ones((dim)), requires_grad=True)

        self.apply(self._init_weights)

    def _init_weights(self, m):
        if isinstance(m, nn.Linear):
            nn.init.trunc_normal_(m.weight, std=.02)
            if m.bias is not None:
                nn.init.constant_(m.bias, 0)
        elif isinstance(m, nn.LayerNorm):
            nn.init.constant_(m.bias, 0)
            nn.init.constant_(m.weight, 1.0)
        elif isinstance(m, nn.Conv2d):
            fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
            fan_out //= m.groups
            nn.init.normal_(m.weight, 0, math.sqrt(2.0 / fan_out))
            if m.bias is not None:
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        x = x + self.drop_path(self.layer_scale_1.unsqueeze(-1).unsqueeze(-1) * self.attn(self.norm1(x)))
        x = x + self.drop_path(self.layer_scale_2.unsqueeze(-1).unsqueeze(-1) * self.mlp(self.norm2(x)))
        return x

实验

脚本

import warnings
warnings.filterwarnings('ignore')
from ultralytics import YOLO
 
if __name__ == '__main__':
#     修改为自己的配置文件地址
    model = YOLO('./ultralytics/cfg/models/26/yolo26-C3k2_EVA.yaml')
#     修改为自己的数据集地址
    model.train(data='./ultralytics/cfg/datasets/coco8.yaml',
                cache=False,
                imgsz=640,
                epochs=10,
                single_cls=False,  # 是否是单类别检测
                batch=8,
                close_mosaic=10,
                workers=0,
                optimizer='MuSGD',  
                # optimizer='SGD',
                amp=False,
                project='runs/train',
                name='yolo26-C3k2_EVA',
                )
    
 

结果

image-20260124104718022