YOLOv8改进 | SPPF | 具有多尺度带孔卷积层的ASPP【CVPR2018】


💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡


专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进——点击即可跳转


Atrous Spatial Pyramid Pooling (ASPP) 是一种在深度学习框架中用于语义分割的网络结构,它旨在通过不同采样率的带孔卷积(atrous convolution,也称为扩张卷积)来捕获多尺度上下文信息。ASPP 结构在原始的空洞卷积基础上,通过在多个不同的扩张率上应用卷积层,从而有效地扩大了感受野,同时保留了空间分辨率。在 ASPP 中,输入图像经过一系列带孔卷积层,每个层使用不同的扩张率,这样可以在不同的尺度上捕捉图像特征。这些层的结果被并行处理,并且它们的输出被拼接起来,形成一个丰富的特征图,这个特征图可以提供多尺度的上下文信息。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址YOLOv8改进——更新各种有效涨点方法——点击即可跳转

目录

1.原理

2. 将ASPP添加到YOLOv8中

2.1 ASPP的代码是实现

2.2 更改init.py文件

2.3 添加yaml文件

2.4 在task.py中进行注册

2.5 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1.原理

论文地址:DenseASPP for Semantic Segmentation in Street Scenes——点击即可跳转

官方仓库:github代码仓库——点击即可跳转

带孔空间金字塔池化 (ASPP) 是一种用于语义分割任务的技术,可提高神经网络理解多尺度物体的能力。

语义分割挑战

  • 在街景理解等任务中,物体的大小差异很大。传统的卷积网络难以捕捉多尺度上下文,因为增加感受野(影响输出的输入图像区域)通常会降低特征图的空间分辨率。

带孔卷积

  • 引入带孔卷积(也称为扩张卷积)来解决此问题。它允许更大的感受野,而不会通过在过滤器权重之间插入零(或空洞)来降低空间分辨率。这样,网络可以在特征图中保持高分辨率,同时扩展感受野以捕获更多上下文。

ASPP(带孔空间金字塔池化)

  • ASPP 以带孔卷积为基础,并行应用具有不同扩张率的多个带孔卷积。其理念是同时捕获多个尺度的特征。这样,网络可以聚合不同尺度的上下文信息,提高其识别不同大小物体的能力并提高分割准确性。

DenseASPP

  • 虽然 ASPP 改进了多尺度特征表示,但它在尺度密度和感受野大小方面存在限制。DenseASPP 通过密集连接多个带孔卷积层来解决这些限制。

  • 在 DenseASPP 中,每个带孔卷积层将其输出馈送到所有后续层。这种密集连接可确保以多个尺度和各种感受野生成特征图。它还允许后面层的神经元具有更大的感受野,而不会遭受内核退化。

  • 密集连接有助于形成非常密集的尺度金字塔,从而捕获广泛且密集的尺度范围内的特征,这对于对象大小变化性高的任务(如自动驾驶)特别有用。

优点

  • DenseASPP 提供较大的感受野,同时保持密集的多尺度特征表示。

  • 它结合了并行和级联空洞卷积层的优点,提高了尺度多样性和感受野的密度。

实现

  • DenseASPP 层的组织方式是,扩张率较小的层后面是扩张率较大的层。所有前几层的输出被连接起来并输入到每个后续层中。

  • 这种设计有助于捕获更丰富、更全面的特征集,从而提高整体分割性能。

总之,ASPP 通过使用具有不同扩张率的空洞卷积捕获多尺度特征来增强语义分割。 DenseASPP 通过密集连接空洞卷积层进一步改进了这种方法,以确保密集和大范围的尺度覆盖,显著提高了网络处理高分辨率图像中不同大小物体的能力。

2. 将ASPP添加到YOLOv8中

2.1 ASPP的代码是实现

关键步骤一: 将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“ASPP”

class ASPP(nn.Module):
    def __init__(self, in_channel=512, out_channel=256):
        super(ASPP, self).__init__()
        self.mean = nn.AdaptiveAvgPool2d((1, 1))  # (1,1)means ouput_dim
        self.conv = nn.Conv2d(in_channel, out_channel, 1)
        self.atrous_block1 = nn.Conv2d(in_channel, out_channel, 1)
        self.atrous_block6 = nn.Conv2d(in_channel, out_channel, 3, padding=6, dilation=6)
        self.atrous_block12 = nn.Conv2d(in_channel, out_channel, 3, padding=12, dilation=12)
        self.atrous_block18 = nn.Conv2d(in_channel, out_channel, 3, padding=18, dilation=18)
        self.conv_1x1_output = nn.Conv2d(out_channel * 5, out_channel, 1)

    def forward(self, x):
        size = x.shape[2:]

        image_features = self.mean(x)
        image_features = self.conv(image_features)
        image_features = F.upsample(image_features, size=size, mode='bilinear')

        atrous_block1 = self.atrous_block1(x)
        atrous_block6 = self.atrous_block6(x)
        atrous_block12 = self.atrous_block12(x)
        atrous_block18 = self.atrous_block18(x)

        net = self.conv_1x1_output(
            torch.cat([image_features, atrous_block1, atrous_block6, atrous_block12, atrous_block18], dim=1))
        return net

带孔空间金字塔池化 (ASPP) 通过捕获多尺度信息来增强卷积神经网络 (CNN) 中的特征提取过程。

特征提取

  • 首先将输入图像通过主干网络(例如 ResNet)以提取高级特征图。这些特征图的分辨率通常低于输入图像,但语义信息丰富。

具有不同扩张率的带孔卷积

  • 然后通过多个带孔卷积层处理提取的特征图,每个层具有不同的扩张率。扩张率控制核元素之间的间距,有效地增加了感受野而不会丢失空间分辨率。

  • 使用的典型扩张率例如为 1、6、12 和 18。这意味着特征图被卷积多次,每次的核元素之间的间距都不同。

池化和 1x1 卷积

  • 除了空洞卷积之外,全局平均池化通常应用于特征图以捕获全局上下文信息。

  • 1x1 卷积用于降低空洞卷积和池化特征的特征图的维数。这有助于保持计算效率并有效地融合特征。

多尺度特征的连接

  • 具有不同扩张率的空洞卷积的输出和池化特征图沿深度维度连接。这会产生丰富的多尺度特征表示,该表示结合了来自不同接受场的信息。

最终卷积层

  • 然后将连接的特征图传递到另一个 1x1 卷积层以融合多尺度特征并将输出通道数减少到所需的类别数以进行分割。

上采样

  • 使用双线性插值或反卷积层对最终输出进行上采样,以匹配输入图像的分辨率。这可确保分割图具有与原始输入图像相同的尺寸。

这样将允许 ASPP 创建丰富的多尺度特征表示,通过有效捕获局部细节和全局上下文来增强语义分割模型的性能。

2.2 更改init.py文件

关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数

然后在下面的__all__中声明函数

2.3 添加yaml文件

关键步骤三:在/ultralytics/ultralytics/cfg/models/v8下面新建文件yolov8_ASPP.yaml文件,粘贴下面的内容

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [ 0.33, 0.25, 1024 ]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [ -1, 1, Conv, [ 64, 3, 2 ] ]  # 0-P1/2
  - [ -1, 1, Conv, [ 128, 3, 2 ] ]  # 1-P2/4
  - [ -1, 3, C2f, [ 128, True ] ]
  - [ -1, 1, Conv, [ 256, 3, 2 ] ]  # 3-P3/8
  - [ -1, 6, C2f, [ 256, True ] ]
  - [ -1, 1, Conv, [ 512, 3, 2 ] ]  # 5-P4/16
  - [ -1, 6, C2f, [ 512, True ] ]
  - [ -1, 1, Conv, [ 1024, 3, 2 ] ]  # 7-P5/32
  - [ -1, 3, C2f, [ 1024, True ] ]
  - [ -1, 1, ASPP, [ 1024 ] ]  # 9

# YOLOv8.0n head
head:
  - [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ]
  - [ [ -1, 6 ], 1, Concat, [ 1 ] ]  # cat backbone P4
  - [ -1, 3, C2f, [ 512 ] ]  # 12

  - [ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ]
  - [ [ -1, 4 ], 1, Concat, [ 1 ] ]  # cat backbone P3
  - [ -1, 3, C2f, [ 256 ] ]  # 15 (P3/8-small)

  - [ -1, 1, Conv, [ 256, 3, 2 ] ]
  - [ [ -1, 12 ], 1, Concat, [ 1 ] ]  # cat head P4
  - [ -1, 3, C2f, [ 512 ] ]

  - [ -1, 1, Conv, [ 512, 3, 2 ] ]
  - [ [ -1, 9 ], 1, Concat, [ 1 ] ]  # cat head P5
  - [ -1, 3, C2f, [ 1024 ] ]  # 21 (P5/32-large)

  - [ [ 15, 18, 21 ], 1, Detect, [ nc ] ]  # Detect(P3, P4, P5)

温馨提示:本文只是对yolov8基础上添加模块,如果要对yolov8n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv8n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
 
# YOLOv8s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
 
# YOLOv8l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
 
# YOLOv8m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple
 
# YOLOv8x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple

2.4 在task.py中进行注册

关键步骤四:在parse_model函数中进行注册,添加ASPP,

2.5 执行程序

关键步骤五:在ultralytics文件中新建train.py,将model的参数路径设置为yolov8_ASPP.yaml的路径即可

建议大家写绝对路径,确保一定能找到

from ultralytics import YOLO
 
# Load a model
# model = YOLO('yolov8n.yaml')  # build a new model from YAML
# model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)
 
model = YOLO(r'/projects/ultralytics/ultralytics/cfg/models/v8/yolov8_ASPP.yaml')  # build from YAML and transfer weights
 
# Train the model
model.train(device = [3], batch=16)

🚀运行程序,如果出现下面的内容则说明添加成功🚀  

3. 完整代码分享

https://pan.baidu.com/s/135hvNLKeAsVFZc-7QN2BHQ?pwd=he8n

提取码: he8n 

4. GFLOPs

关于GFLOPs的计算方式可以查看百面算法工程师 | 卷积基础知识——Convolution

未改进的YOLOv8nGFLOPs

img

改进后的GFLOPs

5. 进阶

可以和损失函数以及注意力机制的修改相结合,效果可能会更好

6. 总结

空洞空间金字塔池化(ASPP)通过不同膨胀率的并行空洞卷积捕捉多尺度上下文信息,从而增强语义分割。通过应用这些卷积,ASPP在不降低空间分辨率的情况下有效地扩展了感受野,使网络能够整合来自不同尺度的特征。这一过程还通过全局平均池化进一步丰富,捕捉更广泛的上下文信息。这些多尺度卷积和池化特征的输出被连接并通过最终的1x1卷积处理以融合特征,然后进行上采样以恢复原始图像分辨率。这个过程使ASPP能够提高网络识别不同大小物体的能力,并增强精度。

  • 27
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay_545

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值