python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Yolov5更换BiFPN

Yolov5更换BiFPN的详细步骤总结

作者:迪菲赫尔曼

将YOLOv5中的PANet层修改为EfficientDet-BiFPN,实现自上而下与自下而上的深浅层特征双向融合,明显提升YOLOv5算法检测精度,下面这篇文章主要给大家介绍了关于Yolov5更换BiFPN的详细步骤,需要的朋友可以参考下

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_Add2和BiFPN_Add3函数中定义的w参数,加入g1

g = [], [], []  # optimizer parameter groups
    bn = tuple(v for k, v in nn.__dict__.items() if 'Norm' in k)  # normalization layers, i.e. BatchNorm2d()
    for v in model.modules():
        # hasattr: 测试指定的对象是否具有给定的属性,返回一个布尔值
        if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):  # bias
            g[2].append(v.bias)
        if isinstance(v, bn):  # weight (no decay)
            g[1].append(v.weight)
        elif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):  # weight (with decay)
            g[0].append(v.weight)
        # BiFPN_Concat
        elif isinstance(v, BiFPN_Add2) and hasattr(v, 'w') and isinstance(v.w, nn.Parameter):
            g[1].append(v.w)
        elif isinstance(v, BiFPN_Add3) and hasattr(v, 'w') and isinstance(v.w, nn.Parameter):
            g[1].append(v.w)

导入BiFPN_Add3, BiFPN_Add2

from models.common import BiFPN_Add3, BiFPN_Add2

第四步:修改yolov5.yaml

Concat全部换成BiFPN_Add

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

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

总结

到此这篇关于Yolov5更换BiFPN的文章就介绍到这了,更多相关Yolov5更换BiFPN内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文