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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: