YOLO组件之C2f模块介绍

C2F类是yolo算法中的组件之一,该类是一个继承自 nn.Module 的神经网络模块。

1. C2f 类的前向传播过程

首先将输入数据经过第一个卷积层 cv1,然后将输出分为两个部分。其中一个部分直接传递给输出,另一个部分经过多个 Bottleneck 模块的处理。最后,两个部分的结果在通道维度上进行拼接,并经过第二个卷积层 cv2 得到最终的输出。

结构如下:

2. C2f模块的作用

特征转换:C2f模块通过两个卷积层(cv1和cv2)对输入数据进行特征转换。cv1卷积层将输入数据的通道数从c1变换为2 * self.c,cv2卷积层将经过一系列操作后的特征图的通道数从(2 + n) * self.c变换为c2。这些卷积操作有助于提取输入数据中的不同层次和抽象程度的特征。

分支处理:C2f模块将输入数据分为两个分支进行处理。其中一个分支直接传递给输出,另一个分支经过多个Bottleneck模块的处理。这样的分支设计有助于增加网络的非线性能力和表示能力,从而提高网络对复杂数据的建模能力。

特征融合:C2f模块通过在通道维度上对不同分支的特征进行拼接,实现特征融合。拼接后的特征将包含来自不同分支的信息,丰富了特征的表达能力。

3. yolov8中代码实现

复制代码
class C2f(nn.Module):
    """CSP Bottleneck with 2 convolutions."""
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):  # 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))

代码解析:

a. init(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):初始化函数,用于定义和初始化类的属性和子模块。

c1:输入通道数。

c2:输出通道数。

n:Bottleneck 模块的数量。

shortcut:是否使用残差连接(shortcut)。

g:分组卷积中的组数。

e:扩展因子,用于计算隐藏通道数。

self.c = int(c2 * e):计算隐藏通道数。

self.cv1 = Conv(c1, 2 * self.c, 1, 1):定义第一个卷积层 cv1,输入通道数为 c1,输出通道数为 2 * self.c,卷积核大小为 1x1,步长为 1。

self.cv2 = Conv((2 + n) * self.c, c2, 1):定义第二个卷积层 cv2,输入通道数为 (2 + n) * self.c,输出通道数为 c2,卷积核大小为 1x1。

self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n)):创建一个包含 n 个 Bottleneck 模块的 nn.ModuleList 对象,并将其赋值给属性 self.m。每个 Bottleneck 模块的输入通道数和输出通道数都为 self.c,使用的卷积核大小为 ((3, 3), (3, 3)),扩展因子为 1.0。

b. forward(self, x):前向传播函数,定义了数据在网络中的正向流动。

x:输入数据。

y = list(self.cv1(x).chunk(2, 1)):将输入数据 x 经过 cv1 卷积层后的结果进行分割成两个张量,并存储在列表 y 中。

y.extend(m(y[-1]) for m in self.m):将列表 y 的最后一个张量作为输入,依次经过 self.m 中的每个 Bottleneck 模块,并将结果添加到列表 y 中。

return self.cv2(torch.cat(y, 1)):将列表 y 中的张量在维度 1 上进行拼接,并将拼接后的结果经过 cv2 卷积层得到最终的输出。

c. forward_split(self, x):前向传播函数的另一种实现方式,它与 forward 函数的区别在于使用了 split() 方法代替了 chunk() 方法。

y = list(self.cv1(x).split((self.c, self.c), 1)):将输入数据 x 经过 cv1 卷积层后的结果按照指定大小进行切割,并存储在列表 y 中。

y.extend(m(y[-1]) for m in self.m):将列表 y 的最后一个张量作为输入,依次经过 self.m 中的每个 Bottleneck 模块,并将结果添加到列表 y 中。

return self.cv2(torch.cat(y, 1)):将列表 y 中的张量在维度 1 上进行拼接,并将拼接后的结果经过 cv2 卷积层得到最终的输出。

4. 总结

综上,C2f模块在CSP Bottleneck结构中起到关键的作用,通过特征转换、分支处理和特征融合等操作,提取和转换输入数据的特征,生成更具表征能力的输出。这有助于提高网络的性能和表示能力,使得网络能够更好地适应复杂的数据任务。

相关推荐
我材不敲代码1 小时前
YOLOv4 核心内容详解
yolo
构建的乐趣1 小时前
测度(Measure)和概率测度(Probability Measure) 测度和度量的区别
python
清水白石0081 小时前
把事故变成护城河:如何设计回归测试,防止“订单重复创建”这类历史 Bug 卷土重来?
python·bug
狐狐生风1 小时前
LangGraph 工具调用集成
python·langchain·prompt·agent·langgraph
MATLAB代码顾问1 小时前
【智能优化】无穷优化算法(INFO)原理与Python实现
开发语言·python·算法
动物园猫1 小时前
火焰与烟雾目标检测数据集分享(适用于YOLO系列深度学习分类检测任务)
深度学习·yolo·目标检测
SilentSamsara1 小时前
迭代器协议:`__iter__` / `__next__` 的完整执行流程
开发语言·人工智能·python·算法·机器学习
yuanpan1 小时前
Python + psutil 实战:开发一个简易系统监控工具
linux·运维·python
MATLAB代码顾问2 小时前
【智能优化】鹈鹕优化算法(POA)原理与Python实现
开发语言·python·算法
动物园猫2 小时前
驾驶中的疲劳状态识别数据集分享(适用于YOLO系列深度学习分类检测任务)
深度学习·yolo·分类