YOLOv11 改进 - 注意力机制 LS-YOLO MSFE 多尺度特征提取模块:并行分支结构增强多尺度感知,优化遥感与小目标检测

4 阅读5分钟

前言

本文介绍了一种用于滑坡检测的模型LS-YOLO及其在YOLOv11中的结合应用。LS-YOLO首先构建多尺度滑坡数据集MSLD,为模型训练提供丰富数据。设计了基于高效通道注意力、平均池化和空间可分离卷积的多尺度特征提取模块MSFE,充分提取滑坡特征信息。在解耦头中采用膨胀卷积增加模型感受野。我们将MSFE模块集成进YOLOv11,替换部分原有模块。实验表明,改进后的YOLOv11在数据集中表现出色 。

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

专栏链接: YOLOv11改进专栏

@[TOC]

介绍

摘要

滑坡作为一种分布广泛且破坏性极强的自然灾害,对人类生命安全及自然资产构成严重威胁,因此研究基于遥感影像的高精度滑坡检测方法具有重要的学术价值和实际应用意义。本文提出了一种新颖高效的滑坡检测模型LS-YOLO,专门针对遥感影像中的滑坡识别任务进行优化设计。研究首先构建了多尺度滑坡数据集(MSLD),并在数据增强过程中引入随机种子机制以增强数据鲁棒性。针对遥感影像中滑坡目标的多尺度特性,设计了融合高效通道注意力机制、平均池化操作和空间可分离卷积的多尺度特征提取模块。为进一步扩展模型感受野,在解耦头结构中采用膨胀卷积技术,具体而言,将基于膨胀卷积构建的上下文增强模块集成至解耦头回归任务分支,并以改进后的解耦头替代YOLOv5s原有的耦合头结构。大量实验验证结果表明,所提出的LS-YOLO模型在多尺度滑坡检测任务中展现出卓越性能,显著优于Faster RCNN、SSD、EfficientDet-D0、YOLOv5s、YOLOv7及YOLOX等主流目标检测模型。相较于基准模型YOLOv5s,LS-YOLO在滑坡检测任务中的平均精度(AP)指标提升2.18个百分点,达到97.06%的优异性能水平。

文章链接

论文地址:论文地址

代码地址:代码地址

基本原理

LS-YOLO

image-20240701093132705

  1. 多尺度滑坡数据集(MSLD)

    • 构建了一个包含大量滑坡样本的MSLD,具有高度的类内变化、广泛的滑坡尺寸范围和复杂的背景,为模型训练提供了丰富的数据资源。
  2. 多尺度特征提取(MSFE)模块

    • MSFE模块包括Efficient Channel Attention(ECA)、平均池化和空间可分离卷积,用于充分提取滑坡特征信息。
    • ECA部分引入了注意力机制,通过全局平均池化聚合特征并自适应地确定核大小,以增强模型对重要特征的关注。
  3. 改进的解耦头

    • LS-YOLO通过引入扩张卷积来改进解耦头,增加模型的感受野,提高滑坡定位的准确性。
    • 扩张卷积有助于捕获多尺度上下文信息,提升模型在滑坡位置定位方面的精度。
  4. 整体框架

    • LS-YOLO的整体框架结合了YOLOv5s的通用目标检测能力,并针对滑坡检测任务进行了优化和改进。
    • 模型在滑坡检测中利用MSFE模块提取多尺度特征,同时通过改进的解耦头提高了滑坡位置的准确性。

MSFE

image-20240701093219290

MSFE(Multiscale Feature Extraction)模块是论文中提出的一个关键技术,通过五个并行分支从多个感受野充分提取滑坡特征。

  1. 模块结构
    • MSFE模块包含两个分支:
      • 第一个分支是残差连接,有助于减轻梯度消失并加快模型训练速度。
      • 第二个分支包括Efficient Channel Attention(ECA)、平均池化和空间可分离卷积,用于充分提取滑坡特征信息。
  2. Efficient Channel Attention(ECA)
    • ECA是一种通用的插入式块,用于增强CNN的性能。

    • ECA包含一个挤压模块,用于压缩全局空间信息,以及一个激励模块,用于实现通道间的交互。

    • ECA通过全局平均池化聚合特征,自适应确定核大小k。

核心代码

import torch
import torch.nn as nn

# MSFE模块定义
class MSFE(nn.Module):

    def __init__(self, c_in, c_out):
        super(MSFE, self).__init__()

        c_ = int(c_in // 4)  # 计算每个分支的输出通道数

        self.ECA = ECA(c_in, k_size=5)  # ECA模块
        self.branch1 = Conv(c_in, c_, 1, 1)  # 分支1,1x1卷积

        # 分支2,3x3平均池化
        self.branch2 = nn.AvgPool2d(kernel_size=3, stride=1, padding=1)

        # 分支3,串联两个卷积层
        self.branch3 = nn.Sequential(
            Conv(c_in, c_, (3, 1), s=1, p=(1, 0)),  # 3x1卷积
            Conv(c_, c_, (1, 3), s=1, p=(0, 1))  # 1x3卷积
        )

        # 分支4,串联四个卷积层
        self.branch4 = nn.Sequential(
            Conv(c_in, c_, (3, 1), s=1, p=(1, 0)),  # 3x1卷积
            Conv(c_, c_, (1, 3), s=1, p=(0, 1)),  # 1x3卷积
            Conv(c_, c_, (3, 1), s=1, p=(1, 0)),  # 3x1卷积
            Conv(c_, c_, (1, 3), s=1, p=(0, 1))  # 1x3卷积
        )

        # 分支5,串联四个卷积层
        self.branch5 = nn.Sequential(
            Conv(c_in, c_, (5, 1), s=1, p=(2, 0)),  # 5x1卷积
            Conv(c_, c_, (1, 5), s=1, p=(0, 2)),  # 1x5卷积
            Conv(c_, c_, (5, 1), s=1, p=(2, 0)),  # 5x1卷积
            Conv(c_, c_, (1, 5), s=1, p=(0, 2))  # 1x5卷积
        )

        self.conv = Conv(c_in * 2, c_out, k=1)  # 1x1卷积,用于整合所有分支的输出

    def forward(self, x):
        x1 = self.ECA(x)  # 通过ECA模块
        y1 = self.branch1(x1)  # 分支1的输出
        y2 = self.branch2(x1)  # 分支2的输出
        y3 = self.branch3(x1)  # 分支3的输出
        y4 = self.branch4(x1)  # 分支4的输出
        y5 = self.branch5(x1)  # 分支5的输出

        # 将所有分支的输出在通道维度上拼接,并通过1x1卷积层,然后与输入x相加
        out = x + self.conv(torch.cat([y1, y2, y3, y4, y5], 1))
        return out

实验

脚本

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