【YOLOv8改进】Non-Local:基于非局部均值去噪滤波的自注意力模型 (论文笔记+引入代码)

简介: YOLO目标检测专栏探讨了YOLO的创新改进,包括引入非局部操作以捕获远程依赖,增强上下文信息。非局部模块可应用于图像分类、目标检测等任务,尤其适合视频分类。文章介绍了Non-local自注意力模型,通过计算任意位置间交互,提供全局信息。此外,展示了如何在YOLOv8中实现NLBlockND模块。详细内容及实战配置见相关链接。

YOLO目标检测创新改进与实战案例专栏

专栏目录: YOLO有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例

专栏链接: YOLO基础解析+创新改进+实战案例

摘要

卷积和循环神经网络中的操作都是一次处理一个局部邻域,在这篇文章中,作者提出了一个非局部的操作来作为捕获远程依赖的通用模块。
受计算机视觉中经典的非局部均值方法启发,我们的非局部操作计算某一位置的响应为所有位置特征的加权和。而且,这个模块可以插入到许多计算机视觉网络架构中去。

创新点

  • 提出的non-local operations通过计算任意两个位置之间的交互直接捕捉远程依赖,而不用局限于相邻点,其相当于构造了一个和特征图谱尺寸一样大的卷积核, 从而可以维持更多信息。
  • non-local可以作为一个组件,和其它网络结构结合,经过作者实验,证明了其可以应用于图像分类、目标检测、目标分割、姿态识别等视觉任务中,并且效果不错。
  • Non-local在视频分类上效果很好,倾向于使用在视频分类这个领域中。

    1. Non-local自注意力模型

Non-Local是由王小龙等人在2018年的计算机视觉与模式识别会议(CVPR 2018)提出的一种自注意力模型。该模型的灵感来源于非局部均值去噪滤波(Non-Local Means),它不同于传统的基于小区域(如3×3卷积核)的滤波方法。Non-Local操作通过在更大的搜索范围内进行加权,从而捕捉更广泛的上下文信息。更多细节可以参考这篇博客

在Non-Local神经网络(NN)中,'Local'指的是与卷积神经网络中的感受野相关的概念。传统卷积层的感受野通常有限(如3×3或5×5),而Non-Local模块允许感受野覆盖整个输入空间,从而实现全局信息的整合。

Non-Local模块与其他注意力机制模块(如CBAM、SE、BAM、SK)相似,都是可插拔的组件,用于对特征图进行信息细化(refinement)。它是一种有效的注意力机制实现,不过其理论基础更为丰富,可能会相对复杂和难以理解。

Non-local的通用公式:

  • $x$ 是输入信号,通常是特征图(feature map)。

  • $i$ 表示输出位置的索引,响应值是通过对所有可能的$j$位置加权求和得到的。

  • $f$ 是一个函数,用于计算位置$i$和$j$之间的相似度。

  • $g$ 是一个函数,用于在位置$j$计算特征图的表示。

  • $y$ 是经过响应因子$C(x)$标准化处理后得到的输出。

image

yolov8 引入

class NLBlockND(nn.Module):
    def __init__(self, in_channels, inter_channels=None, mode='embedded', 
                 dimension=2, bn_layer=True):
        """
        非局部(Non-Local)模块的实现,包含四种不同的成对函数,但不包括子采样技巧。
        参数:
            in_channels: 输入通道数(论文中为1024)
            inter_channels: 模块内部的通道数,如果未指定,则减半(论文中为512)
            mode: 支持高斯、嵌入式高斯、点积和连接四种模式
            dimension: 可以是1(时间维度),2(空间维度),3(时空维度)
            bn_layer: 是否添加批量归一化层
        """
        super(NLBlockND, self).__init__()

        assert dimension in [1, 2, 3]

        if mode not in ['gaussian', 'embedded', 'dot', 'concatenate']:
            raise ValueError('`mode` 必须是 `gaussian`, `embedded`, `dot` 或 `concatenate` 中的一个')

        self.mode = mode
        self.dimension = dimension

        self.in_channels = in_channels
        self.inter_channels = inter_channels

        # 在模块内部,通道数减半
        if self.inter_channels is None:
            self.inter_channels = in_channels // 2
            if self.inter_channels == 0:
                self.inter_channels = 1

        # 根据不同的维度分配适当的卷积、最大池化和批量归一化层
        if dimension == 3:
            conv_nd = nn.Conv3d
            max_pool_layer = nn.MaxPool3d(kernel_size=(1, 2, 2))
            bn = nn.BatchNorm3d
        elif dimension == 2:
            conv_nd = nn.Conv2d
            max_pool_layer = nn.MaxPool2d(kernel_size=(2, 2))
            bn = nn.BatchNorm2d
        else:
            conv_nd = nn.Conv1d
            max_pool_layer = nn.MaxPool1d(kernel_size=(2))
            bn = nn.BatchNorm1d

        # 论文中的函数g,通过1x1的卷积核进行卷积
        self.g = conv_nd(in_channels=self.in_channels, out_channels=self.inter_channels, kernel_size=1)

        # 在最后一个卷积层后添加BatchNorm层
        if bn_layer:
            self.W_z = nn.Sequential(
                conv_nd(in_channels=self.inter_channels, out_channels=self.in_channels, kernel_size=1),
                bn(self.in_channels)
            )
            # 根据论文第4.1节,初始化BN参数以确保非局部模块的初始状态是恒等映射
            nn.init.constant_(self.W_z[1].weight, 0)
            nn.init.constant_(self.W_z[1].bias, 0)
        else:
            self.W_z = conv_nd(in_channels=self.inter_channels, out_channels=self.in_channels, kernel_size=1)

            # 根据论文第3.3节,通过将Wz初始化为0,这个模块可以被插入到任何现有的架构中
            nn.init.constant_(self.W_z.weight, 0)
            nn.init.constant_(self.W_z.bias, 0)

        # 为高斯以外的所有操作定义theta和phi
        if self.mode in ["embedded", "dot", "concatenate"]:
            self.theta = conv_nd(in_channels=self.in_channels, out_channels=self.inter_channels, kernel_size=1)
            self.phi = conv_nd(in_channels=self.in_channels, out_channels=self.inter_channels, kernel_size=1)

        if self.mode == "concatenate":
            self.W_f = nn.Sequential(
                nn.Conv2d(in_channels=self.inter_channels * 2, out_channels=1, kernel_size=1),
                nn.ReLU()
            )

task与yaml配置

详见:https://blog.csdn.net/shangyanaf/article/details/139105131

相关文章
【论文实操】从ACNet中得到启发:非对称卷积块的使用可以有效提高ACC。即插即用!
【论文实操】从ACNet中得到启发:非对称卷积块的使用可以有效提高ACC。即插即用!
995 0
【论文实操】从ACNet中得到启发:非对称卷积块的使用可以有效提高ACC。即插即用!
|
机器学习/深度学习
YOLOv8改进 | 损失函数篇 | 更加聚焦的边界框损失Focaler-IoU、InnerFocalerIoU(二次创新)
YOLOv8改进 | 损失函数篇 | 更加聚焦的边界框损失Focaler-IoU、InnerFocalerIoU(二次创新)
1819 0
|
机器学习/深度学习 计算机视觉
YOLOv5改进 | 2023 | InnerIoU、InnerSIoU、InnerWIoU、FocusIoU等损失函数
YOLOv5改进 | 2023 | InnerIoU、InnerSIoU、InnerWIoU、FocusIoU等损失函数
921 0
|
Shell 网络架构 计算机视觉
YOLOv11改进策略【模型轻量化】| ShufflenetV2,通过通道划分构建高效网络
YOLOv11改进策略【模型轻量化】| ShufflenetV2,通过通道划分构建高效网络
721 14
|
Serverless 计算机视觉
YOLOv11改进策略【小目标改进】| Shape-NWD:融合改进,结合Shape-IoU和NWD 更好地适应小目标特性
YOLOv11改进策略【小目标改进】| Shape-NWD:融合改进,结合Shape-IoU和NWD 更好地适应小目标特性
2440 9
|
XML JSON 数据可视化
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
本文详细介绍了不同数据集格式之间的转换方法,包括YOLO、VOC、COCO、JSON、TXT和PNG等格式,以及如何可视化验证数据集。
5149 1
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
|
计算机视觉
【YOLOv10改进-损失函数】Shape-IoU:考虑边框形状与尺度的指标
YOLO目标检测专栏探讨了边框回归损失的创新方法,强调了目标形状和尺度对结果的影响。提出的新方法Shape-IoU关注边框自身属性,通过聚焦形状和尺度提高回归精度。实验显示,该方法提升了检测效果,超越现有技术,在多个任务中达到SOTA。论文和代码已公开。
|
机器学习/深度学习 编解码 TensorFlow
MobileNetV3架构解析与代码复现
MobileNet模型基于深度可分离卷积,这是一种分解卷积的形式,将标准卷积分解为深度卷积和`1*1`的点卷积。对于MobileNet,深度卷积将单个滤波器应用于每个输入通道,然后,逐点卷积应用`1*1`卷积将输出与深度卷积相结合。
3726 0
MobileNetV3架构解析与代码复现
|
机器学习/深度学习 算法 测试技术
【YOLOv8改进 - 注意力机制】Focused Linear Attention :全新的聚焦线性注意力模块
YOLOv8专栏探讨了该目标检测算法的创新改进,包括使用聚焦线性注意力模块,解决了Transformer在视觉任务中的效率和表达力问题。该模块增强自注意力,提高焦点能力和特征多样性,保持线性复杂度。文章提供了实证证据证明其在多个基准上的性能提升,并在GitHub上发布了代码。论文和更多实战案例链接见文中。