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结构中起到关键的作用,通过特征转换、分支处理和特征融合等操作,提取和转换输入数据的特征,生成更具表征能力的输出。这有助于提高网络的性能和表示能力,使得网络能够更好地适应复杂的数据任务。

相关推荐
Gigavision4 小时前
基于BUAA-MIHR数据集的噪声解耦对比学习算法
人工智能·python·深度学习·算法
IPdodo_4 小时前
跨境 API 调用不稳定怎么办:出口、超时重试与链路监控的实践
网络·python·网络协议
Madison-No75 小时前
搭建项目测试环境
linux·运维·服务器·python
计算机编程-吉哥5 小时前
YOLO26 vs YOLO11 vs YOLOv8:深度学习咖啡果实成熟度分割系统【计算机毕业设计选题推荐】
人工智能·python·深度学习·yolo·django·毕业设计
大衛說6 小时前
11 · 异常处理与日志
python
auto_go6 小时前
Python 实战指南(7)——账本动不动就崩?先把“魔法字符串”和“裸报错”干掉
python
Beyond_System|系统之外6 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
根目录下的猫6 小时前
RK3588适配的轻量级AI模型推荐
人工智能·后端·python·目标检测
wno7047 小时前
Spring Security权限控制
java·python·spring
YOLO数据集集合7 小时前
高铁轨道紧固件损坏检测数据集 | 高铁巡检 紧固件缺陷 轨道安全9093期
人工智能·目标检测·计算机视觉·目标跟踪·轨道·铁轨紧固件·铁轨