YOLOv8第Y9周:重要模块解读

本文介绍了深度学习训练中的关键模块,如普通卷积(Conv)、2D卷积(Conv2)、轻量级卷积(LightConv)、深度卷积(DWConv)、反卷积操作(DWConvTranspose2d)等,以及Focus、GhostConv、注意力机制(如ChannelAttention和SpatialAttention)和CSPBottleneck变种C2f。着重讲解了autopad函数和这些模块在模型构建中的作用。
摘要由CSDN通过智能技术生成

这部分挑选了几个比较重要的模块,其他可以查看我之前的文章https://blog.csdn.net/geo436872/article/details/134990833
YOLOv8中主要模块:

import math

import numpy as np
import torch
import torch.nn as nn

__all__ = (
    "Conv",
    "Conv2",
    "LightConv",
    "DWConv",
    "DWConvTranspose2d",
    "ConvTranspose",
    "Focus",
    "GhostConv",
    "ChannelAttention",
    "SpatialAttention",
    "CBAM",
    "Concat",
    "RepConv",
)

Conv: 使用普通卷积操作的模块。
Conv2: 使用2D卷积操作的模块。
LightConv: 使用轻量级卷积操作的模块。
DWConv: Depth-wise卷积操作的模块。
DWConvTranspose2d: 反卷积操作的深度卷积模块。
ConvTranspose: 反卷积操作的普通卷积模块。
Focus: YOLOv4中的焦点机制模块,用于提升小物体检测精度。
GhostConv: 使用Ghost卷积操作的模块。
ChannelAttention: 通道注意力模块,用于增强卷积操作的通道特征重要性。
SpatialAttention: 空间注意力模块,用于增强卷积操作的空间特征重要性。
CBAM: 基于通道和空间注意力的CBAM模块,用于增强卷积操作的特征重要性。
Concat: 将多个特征图连接在一起的模块。
RepConv: 重复卷积操作的模块。

一、autopad

def autopad(k, p=None, d=1):  # kernel, padding, dilation
    """Pad to 'same' shape outputs."""
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p

autopad函数是用来进行自动填充(padding)的。它接受参数k(卷积核大小)、p(填充大小,默认为None)和d(扩张率,默认为1)。

函数首先判断扩张率d是否大于1,如果是的话,计算实际的卷积核大小k。如果k为整数,则实际的卷积核大小为d * (k - 1) + 1;如果k是一个列表,则分别计算每个元素的实际卷积核大小。

接下来,如果填充大小p为None,则根据卷积核大小k计算自动填充大小。如果k是整数,则自动填充大小为k // 2;如果k是一个列表,则分别计算每个元素的自动填充大小。

最后,函数返回填充大小p。

二、Conv

class Conv(nn.Module):
    """Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""

    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        """Apply convolution, batch normalization and activation to input tensor."""
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        """Perform transposed convolution of 2D data."""
        return self.act(self.conv(x))

这是一个标准的卷积操作的类Conv,它继承自nn.Module。该类接受参数ch_in(输入通道数)、ch_out(输出通道数)、kernel(卷积核大小)、stride(步长)、padding(填充)、groups(分组卷积数)、dilation(扩张率)和activation(是否使用激活函数)。

在初始化方法__init__中,该类定义了一个2D卷积层conv,使用给定的参数进行配置。同时,还定义了一个批量归一化层bn来规范化输出特征图,并通过default_act属性定义了默认的激活函数nn.SiLU()。如果act为True,则使用默认激活函数;如果act是nn.Module类型的实例,则使用该实例作为激活函数;否则,使用nn.Identity()作为激活函数。

在前向传播方法forward中,该类对输入特征图应用了卷积操作、批量归一化和激活函数,然后返回处理后的输出。

三、Focus

class Focus(nn.Module):
    """Focus wh information into c-space."""

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
        """Initializes Focus object with user defined channel, convolution, padding, group and activation values."""
        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act=act)
        # self.contract = Contract(gain=2)

    def forward(self, x):
        """
        Applies convolution to concatenated tensor and returns the output.

        Input shape is (b,c,w,h) and output shape is (b,4c,w/2,h/2).
        """
        return self.conv(torch.cat((x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]), 1))
        # return self.conv(self.contract(x))

这段代码定义了一个名为Focus的类,用于将宽高信息聚焦到通道维度上。

在__init__方法中,这个模块接受一些参数,包括输入通道数c1,输出通道数c2,卷积核大小k,步长s,填充p,分组数g和是否应用激活函数act。然后,它创建一个卷积层对象self.conv,该层的输入通道数是输入通道数c1乘以4,输出通道数是c2。

在forward方法中,模块的实际操作是将输入的特征图x进行分块,并通过torch.cat函数在通道维度上进行拼接。然后,将拼接后的特征图输入到之前创建的卷积层self.conv中进行卷积操作。最后,返回卷积操作后得到的特征图作为模块的输出。

四、C2f

此模块在block.py中。

class C2f(nn.Module):
    """Faster Implementation of CSP Bottleneck with 2 convolutions."""

    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        """Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,
        expansion.
        """
        super().__init__()
        self.c = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, 2 * self.c, 1, 1)
        self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))

    def forward(self, x):
        """Forward pass through C2f layer."""
        y = list(self.cv1(x).chunk(2, 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

    def forward_split(self, x):
        """Forward pass using split() instead of chunk()."""
        y = list(self.cv1(x).split((self.c, self.c), 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

这段代码实现了名为C2f的PyTorch模块,是CSP Bottleneck的一种快速实现。它由两个卷积层组成,并包含一些参数用于定制模块的行为。

在初始化方法中,参数c1表示输入的通道数,c2表示输出的通道数,n表示重复的次数,shortcut表示是否使用shortcut连接,g表示分组数,e表示扩展因子。根据输出通道数c2和扩展因子e计算得到隐藏通道数self.c。接着定义了两个卷积层cv1和cv2,cv1将输入通道数c1变换为2*self.c个通道,cv2将(2+n)*self.c个通道变换为c2个通道。最后,通过nn.ModuleList创建了一个包含n个Bottleneck模块的列表m。

在前向传播方法forward中,首先通过cv1对输入x进行卷积操作,并使用chunk函数将结果分成两部分。然后,将第一部分作为输入,通过n个Bottleneck模块进行重复操作,并将每个模块的输出结果添加到列表y中。最后,将y中的结果沿着通道维度拼接起来,并通过cv2进行最终的卷积操作,得到最终的输出。

与forward方法类似,前向传播方法forward_split也是对输入进行卷积操作,并使用split函数将结果按照self.c进行切分。然后,通过n个Bottleneck模块进行重复操作,并将每个模块的输出结果添加到列表y中。最后,将y中的结果沿着通道维度拼接起来,并通过cv2进行最终的卷积操作,得到最终的输出。

C2f模块的作用是在CSP Bottleneck中起到加强特征表达能力的作用,并提高网络的计算效率。通过堆叠多个Bottleneck模块和合适的连接方式,可以构建更强大、更高效的神经网络模型来应对各种图像处理任务。

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值