YOLOv7添加BiFPN

文章介绍了如何在YOLOv7目标检测框架中使用BiFPN(双向特征金字塔网络)模块。首先,定义了两种BiFPN类,一种基于特征图相加(Add),另一种基于通道数相加(Concat)。每个类都包含了可学习的权重参数以融合不同分支的特征。接着,在yolo.py模型文件中添加了对BiFPN的支持。最后,在train.py中更新了参数优化器,确保BiFPN的权重参数被正确优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的: 在YOLOv7中使用BiFPN

第一步:在models/common.py文件中,添加 BiFPN 类

注意: BiFPN 添加时,分为两种方式。第一种是按照通道数相加(Concat);第二种是按照特征图相加(Add)

# BiFPN
class BiFPN_Add2(nn.Module):
    def __init__(self, c1, c2):
        super(BiFPN_Add2, self).__init__()
        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]))


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]))


# 结合BiFPN 设置可学习参数 学习不同分支的权重
# 两个分支concat操作
class BiFPN_Concat2(nn.Module):
    def __init__(self, dimension=1):
        super(BiFPN_Concat2, self).__init__()
        self.d = dimension
        self.w = nn.Parameter(torch.ones(2, dtype=torch.float32), requires_grad=True)
        self.epsilon = 0.0001
        # 设置可学习参数 nn.Parameter的作用是:将一个不可训练的类型Tensor转换成可以训练的类型 parameter
        # 并且会向宿主模型注册该参数 成为其一部分 即model.parameters()会包含这个parameter
        # 从而在参数优化的时候可以自动一起优化

    def forward(self, x):
        w = self.w
        weight = w / (torch.sum(w, dim=0) + self.epsilon)  # 将权重进行归一化
        # Fast normalized fusion
        x = [weight[0] * x[0], weight[1] * x[1]]
        return torch.cat(x, self.d)


# 三个分支concat操作
class BiFPN_Concat3(nn.Module):
    def __init__(self, dimension=1):
        super(BiFPN_Concat3, self).__init__()
        self.d = dimension
        self.w = nn.Parameter(torch.ones(3, dtype=torch.float32), requires_grad=True)
        self.epsilon = 0.0001

    def forward(self, x):
        w = self.w
        weight = w / (torch.sum(w, dim=0) + self.epsilon)  # 将权重进行归一化
        # Fast normalized fusion
        x = [weight[0] * x[0], weight[1] * x[1], weight[2] * x[2]]
        return torch.cat(x, self.d)

第二步:在models/yolo.py中添加以下代码

        elif m is nn.BatchNorm2d:
            args = [ch[f]]
        elif m is Concat:
            c2 = sum([ch[x] for x in f])
#################下面为添加的代码########################
        elif m in [Concat, BiFPN_Concat2, BiFPN_Concat3]:
            c2 = sum(ch[x] for x in f)

第三步:在train.py中添加以下代码:

#  导入common中的所有类
#  代码添加到第一行
from models.common import *
        elif isinstance(v, BiFPN_Concat2) and hasattr(v, 'w') and isinstance(v.w, nn.Parameter):
            pg1.append(v.w)
        elif isinstance(v, BiFPN_Concat3) and hasattr(v, 'w') and isinstance(v.w, nn.Parameter):
            pg1.append(v.w)

### YOLOv11 中 BiFPN 结构的改进 #### 特性描述 在YOLOv11中,BiFPN(双向特征金字塔网络)得到了进一步增强。这种结构不仅继承了传统FPN的优点,在自上而下路径基础上增加了自底向上的连接方式,还引入了一些新的机制来提升小物体检测效果[^3]。 #### 优化细节 为了更好地处理不同尺度的目标尤其是小型目标,YOLOv11版本中的BiFPN实现了如下几个方面的改进: - **加权特征融合**:不同于简单的相加操作,新版BiFPN采用可学习权重的方式来进行跨层特征融合。这使得模型能够自动调整各层次贡献度,从而获得更加鲁棒且高质量的中间表示形式[^4]。 - **深度可控卷积(DCConv)**:针对原有标准卷积可能带来的信息损失问题,加入了Depthwise Separable Convolutions作为默认选项之一。该方法可以在保持计算效率的同时增加感受野大小,有助于捕捉更多上下文线索[^1]。 - **多尺度训练策略**:考虑到实际应用场景下的多样性需求,采用了动态变化输入尺寸的方法进行预训练阶段的数据增广。这样可以促使网络学会适应各种比例变换情况下的特征提取任务,间接增强了对于小目标识别的能力[^2]。 ```python def bifpn_layer(features, num_channels=256): P3_in, P4_in, P5_in = features # Top-down pathway with weighted fusion and depth-wise separable convolutions P5_td = tf.keras.layers.Conv2D(num_channels, kernel_size=(1, 1), padding='same')(P5_in) P4_td = tf.keras.layers.Add()([ tf.keras.layers.UpSampling2D()(P5_td), tf.keras.layers.DepthwiseConv2D(kernel_size=(3, 3), padding='same')(P4_in)]) P3_out = tf.keras.layers.Add()([ tf.keras.layers.UpSampling2D()(P4_td), tf.keras.layers.DepthwiseConv2D(kernel_size=(3, 3), padding='same')(P3_in)]) # Bottom-up pathway similarly implemented... ```
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值