当前位置:   article > 正文

YOLOv5改进(六)--引入YOLOv8中C2F模块

YOLOv5改进(六)--引入YOLOv8中C2F模块

1、前言

本文主要使用YOLOv8的C2F模块替换YOLOv5中的C3模块,经过实验测试,发现YOLOv5更加适合嵌入式设备,所以并不是越新的框架性能就会越好。通常大部分的目标检测模型都是在coco数据集上进行训练,然后再与旧的模型进行比较,如果只看在coco数据集上的表现确实v7、v8是要优于v5的,但是在自己数据集上面训练可能就是另外一种结果,所以可以尝试将不同模型的不同模块进行融合,试一试训练效果。

2、C3模块和C2F模块

2.1、C3模块

YOLOV5 采用C3模块,类似于残差结构的思想,C3模块由三个CBS模块,也就是三个卷积层,再加上若干个BottleNeck模块构成,输入进来的特征,分为两个部分,一部分特征是只经过CBS模块处理,一部分经过CBS+BottleNeck处理,最后通过concat将两部分特征进行拼接,再经过一个CBS层将特征维度进行恢复。

class C3(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
 
    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

YOLOv5-v6.0版本中使用了C3模块,替代了早期的BottleneckCSP模块。这两者结构作用基本相同,均为CSP架构,只是在修正单元的选择上有所不同,C3模块包含了3个标准卷积层以及多个Bottleneck模块,与BottleneckCSP模块所不同的是,C3经过Bottleneck模块输出后的Conv模块被去掉了。旧版本的yolov5的CSP模块如下:

2.2、BottleNeck模块

BottleNeck模块是类似与resnet残差结构,该模块其实存在两种形式,也就是BottleNeck1和BottleNeck2,BottleNeck1是以resnet残差结构连接的,该残差结构是由两条路构成,其中一路先进行1×1卷积将特征图的通道数减小一半,从而减少计算量,再通过3×3卷积提取特征,并且将通道数加倍,其输入与输出的通道数是不发生改变的,而另外一路通过shortcut进行残差连接,与第一路的输出特征图相加,从而实现特征融合;BottleNeck2只是经过一次1x1卷积的CBS和一次3x3卷积的CBS

2.3、C2F模块

CBS处理之后的特征首先进行Split分割成两部分特征,一部分特征保留不做任何处理,一部分经过若干个BottleNeck进行处理;其中每个BottleNeck又会分出两条通道,一条是将处理过的特征传递给下一个BottleNeck,一条则是保留下来用作后面的concat连接。最后经过n个BottleNeck之后将所有的特征进行融合。

n个BottleNeck的特征融合方式很像FPN特征金字塔自顶向下融合,将深层特征与浅层特征进行融合 。

在这里插入图片描述

C2f 使用了3个卷积模块(ConV+BN+SILU),以及n个BottleNeck构成输入的特征经过Split之后通道数变为原来的一半(h ∗ w ∗ 0.5cout),一半的特征图不做处理,另外一半则是传入到BottleNeck模块中做特征融合操作,其结构图如下:

3、C2F代码实现

添加C2f和C2F_Bottleneck模块代码,因为YOLOv5和YOLOv8的Bottleneck模块不一致,这里直接拷贝YOLOv8源码的C2f和C2F_Bottleneck模块。

3.1、common.py

models/common.py的加入C2fC2F_Bottleneck

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(C2F_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))


class C2F_Bottleneck(nn.Module):
    """Standard bottleneck."""

    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
        """Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, and
        expansion.
        """
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = Conv(c_, c2, k[1], 1, g=g)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        """'forward()' applies the YOLO FPN to input data."""
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

3.2、yolo.py

models/yolo.py的parse_model函数,添加C2f 模块

if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP,C3, C2f]:
  • 1

在这里插入图片描述

3.3、yolov5s_C2F.yaml

models文件夹新建一个yolov5s_C2F.yaml文件,将yolov5s所有的C3模块都换成了C2f模块。

# YOLOv5 
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/668679
推荐阅读
相关标签