• yolov5 common文件各模块理解


    Conv模块
    也是老组合了。包含卷积、批量归一化(控制梯度消失)、激活操作(激活操作的作用去线性化)

    Focus模块
    将图片切片为四块每一块的特征数量都变少了但是通道增加了可以看作另一种下采样,虽然增加了参数值和运算量并没有丢失特征。

    Bottleneck
    一种计算速度更快的残差块,相较于resnet残差块既加深了网络还减少了计算参数

    BottleneckCSP和C3
    均是CSP的一种结构是学习特征的主要结构

    class BottleneckCSP(nn.Module):
        # CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
        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 = nn.Conv2d(c1, c_, 1, 1, bias=False)
            self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False)
            self.cv4 = Conv(2 * c_, c2, 1, 1)
            self.bn = nn.BatchNorm2d(2 * c_)  # applied to cat(cv2, cv3)
            self.act = nn.SiLU()
            self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
    
        def forward(self, x):
            y1 = self.cv3(self.m(self.cv1(x)))
            y2 = self.cv2(x)
            return self.cv4(self.act(self.bn(torch.cat((y1, y2), dim=1))))
    
    
    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)  # act=FReLU(c2)
            self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
            # self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])
    
        def forward(self, x):
            return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
    
    
    • 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

    可见C3和bottleneckcsp的差别在于卷积层的选择上的差别。首先将原特征图分为两个部分一部分进行标准卷积,另一部分进行多个Bottleneck残差块的卷积操作。最后通过拼接操作拼接在最后进行一次标准卷积。

    SPP空间金字塔池化
    将一张特征图经过一系列不同的大小的滑动窗口进行最大值池化

    45454
    首先这是经过卷积、池化之后输入输出图片的大小之间的计算公式。 padding为扩充spp中为k//2,又因为k为奇数,乘2之后可以换一种表示方式就是 k-1,dilation为空洞卷积的参数函数中没有给出默认为1,stride 为1化简之后 H out==H in 同理W out == W in

    class SPP(nn.Module):
        # Spatial Pyramid Pooling (SPP) layer https://arxiv.org/abs/1406.4729
        def __init__(self, c1, c2, k=(5, 9, 13)):
            super().__init__()
            c_ = c1 // 2  # hidden channels
            self.cv1 = Conv(c1, c_, 1, 1)
            self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
            self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
    
        def forward(self, x):
            x = self.cv1(x)
            with warnings.catch_warnings():
                warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning
                return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    通过forward了解到先对x进行了一次标准卷积,之后将原特征图进行多次最大值池化和原特征图根据channel进行拼接,巧妙在多个最大池化层的参数的选取在经过上述公式计算之后图片的宽高并没有变化。所以除了channel batch,H,W都是相同的。而关于spp可以将不同的输入转化为同样大小的输出的理解,根据上述代码我的理解是相对于HW经过多个MAXpooling之后保持HW不变,如果是对不同的hw仅通过spp这个结构保证输出的格式都相同还是不太容易实现。请各位批评指正了。

  • 相关阅读:
    机器人过程自动化(RPA)入门 2. 录制播放
    【小白专用】VSCode下载和安装与配置PHP开发环境(详细版) 23.11.08
    【Unity3D】基于粒子系统实现烟花特效
    【VSCode实战】转换大小写快捷键
    YOLOv5、v7改进之三十二:引入SKAttention注意力机制
    深度学习——词汇embedded、Beam Search
    PCS7中如何实现DB块变量的自动上传
    【AUTOSAR】【通信安全】E2EXf
    uniapp使用scss仿tailwindcss进行常用样式封装便捷开发小程序或web
    论文阅读_大模型_ToolLLM
  • 原文地址:https://blog.csdn.net/u013345179/article/details/127848527