YOLOv5 更换Neck之 BiFPN

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    文章目录


    更新日志2023/2/12修复了版本问题导致的代码差异性。🍀


    Yolov5如何更换BiFPN?

    第一步修改common.py

    将如下代码添加到common.py文件中

    # BiFPN 
    # 两个特征图add操作
    class BiFPN_Add2(nn.Module):
        def __init__(self, c1, c2):
            super(BiFPN_Add2, self).__init__()
            # 设置可学习参数 nn.Parameter的作用是将一个不可训练的类型Tensor转换成可以训练的类型parameter
            # 并且会向宿主模型注册该参数 成为其一部分 即model.parameters()会包含这个parameter
            # 从而在参数优化的时候可以自动一起优化
            self.w = nn.Parameter(torch.ones(2, dtype=torch.float32), requires_grad=True)
            self.epsilon = 0.0001
            self.conv = nn.Conv2d(c1, c2, kernel_size=1, stride=1, padding=0)
            self.silu = nn.SiLU()
    
        def forward(self, x):
            w = self.w
            weight = w / (torch.sum(w, dim=0) + self.epsilon)
            return self.conv(self.silu(weight[0] * x[0] + weight[1] * x[1]))
    
    
    # 三个特征图add操作
    class BiFPN_Add3(nn.Module):
        def __init__(self, c1, c2):
            super(BiFPN_Add3, self).__init__()
            self.w = nn.Parameter(torch.ones(3, dtype=torch.float32), requires_grad=True)
            self.epsilon = 0.0001
            self.conv = nn.Conv2d(c1, c2, kernel_size=1, stride=1, padding=0)
            self.silu = nn.SiLU()
    
        def forward(self, x):
            w = self.w
            weight = w / (torch.sum(w, dim=0) + self.epsilon)  
            # Fast normalized fusion
            return self.conv(self.silu(weight[0] * x[0] + weight[1] * x[1] + weight[2] * x[2]))
    
    

    第二步修改yolo.py

    parse_model函数中找到elif m is Concat:语句在其后面加上BiFPN_Add相关语句
    在这里插入图片描述

    elif m is Concat:
        c2 = sum(ch[x] for x in f)
    # 添加bifpn_add结构
    elif m in [BiFPN_Add2, BiFPN_Add3]:
        c2 = max([ch[x] for x in f])
    

    第三步修改train.py

    • BiFPN_Add2BiFPN_Add3函数中定义的w参数加入g1

    在这里插入图片描述

        g0, g1, g2 = [], [], []  # optimizer parameter groups
        for v in model.modules():
            if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):  # bias
                g2.append(v.bias)
            if isinstance(v, nn.BatchNorm2d):  # weight (no decay)
                g0.append(v.weight)
            elif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):  # weight (with decay)
                g1.append(v.weight)
            # BiFPN_Concat
            elif isinstance(v, BiFPN_Add2) and hasattr(v, 'w') and isinstance(v.w, nn.Parameter):
                g1.append(v.w)
            elif isinstance(v, BiFPN_Add3) and hasattr(v, 'w') and isinstance(v.w, nn.Parameter):
                g1.append(v.w)
    
    • 导入BiFPN_Add3, BiFPN_Add2
    from models.common import BiFPN_Add3, BiFPN_Add2
    

    第四步修改yolov5.yaml

    Concat全部换成BiFPN_Add

    # YOLOv5 🚀 by Ultralytics, GPL-3.0 license
    
    # Parameters
    nc: 80  # number of classes
    depth_multiple: 0.33  # model depth multiple
    width_multiple: 0.50  # layer channel multiple
    anchors:
      - [10,13, 16,30, 33,23]  # P3/8
      - [30,61, 62,45, 59,119]  # P4/16
      - [116,90, 156,198, 373,326]  # P5/32
    
    # YOLOv5 v6.0 backbone
    backbone:
      # [from, number, module, args]
      [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
       [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
       [-1, 3, C3, [128]],
       [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
       [-1, 6, C3, [256]],
       [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
       [-1, 9, C3, [512]],
       [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
       [-1, 3, C3, [1024]],
       [-1, 1, SPPF, [1024, 5]],  # 9
      ]
    
    # YOLOv5 v6.1 BiFPN head
    head:
      [[-1, 1, Conv, [512, 1, 1]],
       [-1, 1, nn.Upsample, [None, 2, 'nearest']],
       [[-1, 6], 1, BiFPN_Add2, [256, 256]],  # cat backbone P4
       [-1, 3, C3, [512, False]],  # 13
    
       [-1, 1, Conv, [256, 1, 1]],
       [-1, 1, nn.Upsample, [None, 2, 'nearest']],
       [[-1, 4], 1, BiFPN_Add2, [128, 128]],  # cat backbone P3
       [-1, 3, C3, [256, False]],  # 17 
    
       [-1, 1, Conv, [512, 3, 2]],  
       [[-1, 13, 6], 1, BiFPN_Add3, [256, 256]],  #v5s通道数是默认参数的一半
       [-1, 3, C3, [512, False]],  # 20 
    
       [-1, 1, Conv, [512, 3, 2]],
       [[-1, 10], 1, BiFPN_Add2, [256, 256]],  # cat head P5
       [-1, 3, C3, [1024, False]],  # 23 
    
       [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
      ]
    
    

    注意BiFPN_Add本质是add操作因此输入层通道数、feature map要完全对应

    2022.8.25 官方也提供了BiFPN可以尝试用官方的
    关于5m加BiFPN的文件我已经更新到了我的Git


    本人更多 YOLOv5/v7 实战内容导航🍀🌟🚀

    1. 手把手带你调参YOLOv5 (v5.0-v7.0)推理🌟强烈推荐

    2. 手把手带你调参YOLOv5 (v5.0-v7.0)训练🚀

    3. 手把手带你调参YOLOv5 (v5.0-v7.0)验证

    4. 简单三步 用YOLOv5快速训练自己的数据集

    5. 手把手带你YOLOv5/v7 (v5.0-v7.0)添加注意力机制(一)并附上30多种顶会Attention原理图🌟强烈推荐🍀新增8种

    6. 手把手带你YOLOv5/v7 (v5.0-v7.0)添加注意力机制(二)在C3模块中加入注意力机制

    7. YOLOv5/v7 如何更换激活函数

    8. YOLOv5 如何更换BiFPN?

    9. YOLOv5 数据增强方式解析

    10. YOLOv5/v7 更换上采样方式( 最近邻 / 双线性 / 双立方 / 三线性 / 转置卷积)

    11. YOLOv5/v7 如何更换EIOU / alpha IOU / SIoU

    12. YOLOv5/v7 应用轻量级通用上采样算子CARAFE

    13. 空间金字塔池化改进 SPP / SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC🚀

    14. 用于低分辨率图像和小物体的模块SPD-Conv

    15. GSConv+Slim-neck 减轻模型的复杂度同时提升精度

    16. 头部解耦 | 将YOLOX解耦头添加到YOLOv5 | 涨点杀器

    17. Stand-Alone Self-Attention | 搭建纯注意力FPN+PAN结构

    18. 改进YOLOv5/v7 | 引入密集连接卷积网络DenseNet思想 | 搭建密集连接模块

    19. YOLOv5/v7 更换骨干网络之 PP-LCNet

    20. YOLOv5/v7 更换骨干网络之 EfficientNet-B0

    21. YOLOv5/v7 更换骨干网络之 MobileNet V3

    22. YOLOv5/v7 更换骨干网络之 GhostNet

    23. YOLOv5/v7 更换骨干网络之 ShuffleNetv2

    24. YOLOv5/v7 引入 最新 BiFusion Neck🍀

    25. YOLOv5/v7 引入 YOLOv8 的 C2f 模块🍀

    26. YOLOv5/v7 引入 RepVGG 重参数化模块🍀

    27. YOLOv5 模型剪枝实战✂️

    28. YOLOv5 知识蒸馏实战⚗️

    29. YOLOv7 知识蒸馏实战⚗️

    30. YOLOv5/v7 Falsk Web 部署💻

    31. YOLOv5/v7添加PyQt5页面📟

    32. YOLOv5 安卓部署📱


    请添加图片描述


    有问题欢迎大家指正如果感觉有帮助的话请点赞支持下👍📖🌟

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    “YOLOv5 更换Neck之 BiFPN” 的相关文章