YOLO26 改进 - 注意力机制 ACmix自注意力与卷积混合模型:轻量级设计融合双机制优势,实现高效特征提取与推理加速

📅 2026/7/6 1:58:16
YOLO26 改进 - 注意力机制   ACmix自注意力与卷积混合模型:轻量级设计融合双机制优势,实现高效特征提取与推理加速
前言本文介绍了将自注意力和卷积技术相结合的ACmix模型及其在YOLO26中的结合应用。研究发现自注意力和卷积存在强烈基础关系大部分计算使用相同操作且第一阶段计算复杂度占主导。ACmix通过将传统卷积和自注意力模块操作统一实现了两种技术的优雅整合还采用深度卷积替代低效张量移位操作提高了效率。我们将ACmix集成进YOLO26大量实验表明改进后的模型表现优于基线。文章目录 YOLO26改进大全卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总专栏链接: YOLO26改进专栏摘要卷积与自注意力作为两种强大的表示学习技术传统上被视为彼此独立的并行方法。本研究揭示了二者之间存在的深刻内在联系从计算视角分析表明这两种范式的核心计算操作实际上具有高度一致性。具体而言我们首先论证了传统k×k卷积可分解为k²个1×1卷积操作辅以位移与求和运算随后将自注意力模块中的查询、键和值投影过程解释为多个1×1卷积操作继而计算注意力权重并进行值聚合。分析结果表明两种模块的第一阶段均包含相似的计算操作。更为重要的是相较于第二阶段第一阶段在计算复杂度上占据主导地位与通道数平方成正比。这一关键发现自然引导出两种看似迥异范式的优雅整合方案——即一种同时兼具自注意力与卷积优势的混合模型ACmix该模型相比纯卷积或纯自注意力方法具有最低的计算开销。大量系统性实验验证表明所提出的模型在图像识别及下游任务中相较于竞争性基线方法均取得了显著优越的性能表现。相关代码与预训练模型将发布于https://github.com/Panxuran/ACmix及https://gitee.com/mindspore/models平台。创新点发现共同操作ACmix揭示了自注意力和卷积之间存在强烈的基础关系指出它们的大部分计算实际上使用相同的操作。通过将传统卷积分解为多个1×1卷积并将自注意力模块中的查询、键和值的投影解释为多个1×1卷积ACmix发现了这两种技术之间的共同操作。阶段性计算复杂度ACmix强调了自注意力和卷积模块中第一阶段的计算复杂度较高这一观察自然地导致了这两种看似不同范式的优雅整合。通过最小化计算开销ACmix实现了自注意力和卷积的有效融合。轻量级移位和聚合为了提高效率ACmix采用深度卷积替代低效的张量移位操作实现了轻量级的移位操作。这种创新的方法改善了模型的实际效率同时保持了数据的局部性。模块化设计ACmix采用了模块化的设计将自注意力和卷积技术结合在一起同时保持了模块之间的独立性。这种设计使得ACmix能够充分利用两种技术的优势同时避免了昂贵的重复投影操作。文章链接论文地址论文地址代码地址代码地址基本原理ACmix是一种将自注意力self-attention和卷积convolution技术相结合的模型旨在实现更高效的表示学习。阶段I - 输入特征首先通过三个1×1卷积进行投影然后被分成N个部分每个部分包含3×N个特征图。 - 对于自注意力路径将中间特征分成N组每组包含三个特征片段分别来自三个1×1卷积。这三个特征图分别用作查询queries、键keys和值values遵循传统的多头自注意力模块。 - 对于卷积路径采用轻量级全连接层生成k^2个特征图。通过移位和聚合生成的特征图以卷积方式处理输入特征并从本地感受野中收集信息。 - 最后两个路径的输出相加其强度由两个可学习的标量控制F_out αF_att βF_conv。改进的移位和求和 - 在卷积路径中中间特征遵循传统卷积模块中进行的移位和求和操作。为了提高效率采用固定卷积核的深度卷积来替代低效的张量移位操作。 - 通过深度卷积的固定卷积核实现了轻量级的移位操作避免了数据局部性的破坏并更容易实现向量化。阶段II - ACmix在第二阶段引入了额外的计算开销包括一个轻量级全连接层和一个组卷积。这些计算复杂度与通道大小C成线性关系相对于第一阶段来说较小。 - 通过轻量级全连接层和组卷积实现了卷积路径中的特征生成和聚合进一步提高了模型的灵活性和性能。核心代码import torch import torch.nn as nn import torch.nn.functional as F import time # 位置编码函数 def position(H, W, is_cudaTrue): # 根据是否使用 CUDA 设备生成横向和纵向的位置编码 if is_cuda: loc_w torch.linspace(-1.0, 1.0, W).cuda().unsqueeze(0).repeat(H, 1) loc_h torch.linspace(-1.0, 1.0, H).cuda().unsqueeze(1).repeat(1, W) else: loc_w torch.linspace(-1.0, 1.0, W).unsqueeze(0).repeat(H, 1) loc_h torch.linspace(-1.0, 1.0, H).unsqueeze(1).repeat(1, W) loc torch.cat([loc_w.unsqueeze(0), loc_h.unsqueeze(0)], 0).unsqueeze(0) return loc # 步幅函数按给定步幅下采样输入张量 def stride(x, stride): b, c, h, w x.shape return x[:, :, ::stride, ::stride] # 初始化张量值为 0.5 def init_rate_half(tensor): if tensor is not None: tensor.data.fill_(0.5) # 初始化张量值为 0 def init_rate_0(tensor): if tensor is not None: tensor.data.fill_(0.) # ACmix 模块类定义 class ACmix(nn.Module): def __init__(self, in_planes, out_planes, kernel_att7, head4, kernel_conv3, stride1, dilation1): super(ACmix, self).__init__() self.in_planes in_planes self.out_planes out_planes self.head head self.kernel_att kernel_att self.kernel_conv kernel_conv self.stride stride self.dilation dilation self.rate1 torch.nn.Parameter(torch.Tensor(1)) self.rate2 torch.nn.Parameter(torch.Tensor(1)) self.head_dim self.out_planes // self.head # 定义三个 1x1 卷积层用于生成查询、键、值 self.conv1 nn.Conv2d(in_planes, out_planes, kernel_size1) self.conv2 nn.Conv2d(in_planes, out_planes, kernel_size1) self.conv3 nn.Conv2d(in_planes, out_planes, kernel_size1) self.conv_p nn.Conv2d(2, self.head_dim, kernel_size1) self.padding_att (self.dilation * (self.kernel_att - 1) 1) // 2 self.pad_att torch.nn.ReflectionPad2d(self.padding_att) self.unfold nn.Unfold(kernel_sizeself.kernel_att, padding0, strideself.stride) self.softmax torch.nn.Softmax(dim1) # 定义全连接层和深度卷积层 self.fc nn.Conv2d(3*self.head, self.kernel_conv * self.kernel_conv, kernel_size1, biasFalse) self.dep_conv nn.Conv2d(self.kernel_conv * self.kernel_conv * self.head_dim, out_planes, kernel_sizeself.kernel_conv, biasTrue, groupsself.head_dim, padding1, stridestride) self.reset_parameters() def reset_parameters(self): # 初始化参数 init_rate_half(self.rate1) init_rate_half(self.rate2) kernel torch.zeros(self.kernel_conv * self.kernel_conv, self.kernel_conv, self.kernel_conv) for i in range(self.kernel_conv * self.kernel_conv): kernel[i, i//self.kernel_conv, i%self.kernel_conv] 1. kernel kernel.squeeze(0).repeat(self.out_planes, 1, 1, 1) self.dep_conv.weight nn.Parameter(datakernel, requires_gradTrue) self.dep_conv.bias init_rate_0(self.dep_conv.bias) def forward(self, x): # 通过卷积层生成查询、键和值 q, k, v self.conv1(x), self.conv2(x), self.conv3(x) scaling float(self.head_dim) ** -0.5 b, c, h, w q.shape h_out, w_out h//self.stride, w//self.stride # 位置编码 pe self.conv_p(position(h, w, x.is_cuda).to(x.dtype)) q_att q.view(b*self.head, self.head_dim, h, w) * scaling k_att k.view(b*self.head, self.head_dim, h, w) v_att v.view(b*self.head, self.head_dim, h, w) if self.stride 1: q_att stride(q_att, self.stride) q_pe stride(pe, self.stride) else: q_pe pe # 展开键和位置编码 unfold_k self.unfold(self.pad_att(k_att)).view(b*self.head, self.head_dim, self.kernel_att*self.kernel_att, h_out, w_out) unfold_rpe self.unfold(self.pad_att(pe)).view(1, self.head_dim, self.kernel_att*self.kernel_att, h_out, w_out) # 计算注意力权重 att (q_att.unsqueeze(2)*(unfold_k q_pe.unsqueeze(2) - unfold_rpe)).sum(1) att self.softmax(att) # 应用注意力权重到值 out_att self.unfold(self.pad_att(v_att)).view(b*self.head, self.head_dim, self.kernel_att*self.kernel_att, h_out, w_out) out_att (att.unsqueeze(1) * out_att).sum(2).view(b, self.out_planes, h_out, w_out) # 卷积部分 f_all self.fc(torch.cat([q.view(b, self.head, self.head_dim, h*w), k.view(b, self.head, self.head_dim, h*w), v.view(b, self.head, self.head_dim, h*w)], 1)) f_conv f_all.permute(0, 2, 1, 3).reshape(x.shape[0], -1, x.shape[-2], x.shape[-1]) out_conv self.dep_conv(f_conv) # 返回注意力和卷积的加权结果 return self.rate1 * out_att self.rate2 * out_conv实验脚本import warnings warnings.filterwarnings(ignore) from ultralytics import YOLO if __name__ __main__: # 修改为自己的配置文件地址 model YOLO(./ultralytics/cfg/models/26/yolo26-ACmix.yaml) # 修改为自己的数据集地址 model.train(data./ultralytics/cfg/datasets/coco8.yaml, cacheFalse, imgsz640, epochs10, single_clsFalse, # 是否是单类别检测 batch8, close_mosaic10, workers0, optimizerMuSGD, ampTrue, projectruns/train, nameyolo26-ACmix, )实验结果