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

相关推荐
justjinji3 小时前
Go语言如何用Jaeger_Go语言Jaeger链路追踪教程【完整】
jvm·数据库·python
m0_743623923 小时前
开发者工具怎么看HTML_Elements面板使用指南【操作】
jvm·数据库·python
Wyz201210243 小时前
C#怎么实现EF Core迁移 C#如何用Entity Framework Core进行数据库迁移和更新表结构【数据库】
jvm·数据库·python
u0109147603 小时前
如何在Kubernetes集群部署phpMyAdmin_Deployment与Service配置
jvm·数据库·python
m0_640309303 小时前
怎么通过SSH通道连接SQL Server_跳板机安全配置指南
jvm·数据库·python
HHHHH1010HHHHH3 小时前
CSS如何处理网格布局中的绝对定位_利用relative网格项作为参考系
jvm·数据库·python
思绪无限3 小时前
YOLOv5至YOLOv12升级:草莓成熟度检测系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·草莓成熟度检测·yolov12·yolo全家桶
yejqvow123 小时前
CSS项目样式如何模块化_应用BEM规范构建组件化逻辑
jvm·数据库·python
m0_748920363 小时前
宝塔面板安装后无法访问宝塔官网接口_检查服务器外网连通性
jvm·数据库·python