bifpn问题

在EfficientDet-pytorch实现中遇到BiFPN参数不可导问题,导致训练集有map但测试集map全为0。经过检查,问题并非由BiFPN引起。尝试将BiFPN参数改为可导后,模型准确率不升反降。最终采用toandaominh1997/EfficientDet.Pytorch的实现,同时网络上出现了其他版本的解决方案。

 

https://github.com/Michael-Jing/EfficientDet-pytorch/blob/master/efficientdet_pytorch/BiFPN.py

这里面的参数不可导,

训练集有map,但是测试集map全是0,

经过验证,不是bifpn的问题。

bifpn 动态参数和静态参数

改成可求导的参数后,准确率反而下降了。

后来用的就是这个:

https://github.com/toandaominh1997/EfficientDet.Pytorch/blob/cd75ddb5d7f1ade0f16914b70d564b9cf82ea917/models/efficientdet.py

import torch
from torch.nn.init import xavier_uniform

import torch.nn as nn
import torch.nn.functional as F

f
### BIFPN 神经网络架构概述 双向特征金字塔网络(Bidirectional Feature Pyramid Network, BiFPN)是一种用于目标检测任务的高效特征融合方法。它通过增强不同尺度之间的信息交互能力,显著提升了模型性能。以下是关于如何理解并配置 BiFPN 的详细介绍。 --- #### **BiFPN 架构的核心特点** 1. **双向信息流动** 不同于传统的单向 FPN 结构,BiFPN 实现了自顶向下和自底向上的双重信息传递方式。这有助于更好地融合高低分辨率特征图的信息[^2]。 2. **加权特征融合** 在每次跨层特征融合过程中引入可学习的权重参数,从而动态调整各路径的重要性。这种方法可以有效减少冗余计算,并提升模型精度[^3]。 3. **轻量化设计** 尽管增加了额外的连接关系,但由于采用了高效的逐点卷积操作以及共享权重策略,整体复杂度仍然较低,适合部署在资源受限场景下运行。 --- #### **实现步骤** ##### 1. 定义基础组件 构建一个基本单元 `BiFPN` 类来处理每一阶段内的多级特征映射转换过程: ```python import torch import torch.nn as nn import torch.nn.functional as F class ConvBlock(nn.Module): """标准卷积块""" def __init__(self, channels_in, channels_out, kernel_size=3, stride=1, padding=1): super(ConvBlock, self).__init__() self.conv = nn.Sequential( nn.Conv2d(channels_in, channels_out, kernel_size, stride=stride, padding=padding), nn.BatchNorm2d(channels_out), # 批量归一化加速收敛 nn.ReLU(inplace=True) # ReLU激活函数增加非线性表达力 ) def forward(self, x): return self.conv(x) class WeightedFeatureFusion(nn.Module): """带权重的特征融合模块""" def __init__(self, num_inputs, epsilon=1e-4): super(WeightedFeatureFusion, self).__init__() self.epsilon = epsilon self.weights = nn.Parameter(torch.ones(num_inputs)) # 初始化为均匀分布 def forward(self, inputs): normalized_weights = (self.weights / (torch.sum(self.weights.abs()) + self.epsilon)).unsqueeze(-1).unsqueeze(-1) fused_feature = sum([w * f for w, f in zip(normalized_weights, inputs)]) return fused_feature class BiFPNLayer(nn.Module): """单一层次的BiFPN结构定义""" def __init__(self, feature_sizes=[64, 128, 256], conv_channels=64): super(BiFPNLayer, self).__init__() self.num_levels = len(feature_sizes) # 上采样分支 self.up_sample_convs = nn.ModuleList([ ConvBlock(conv_channels, conv_channels) for _ in range(self.num_levels - 1)]) # 下采样分支 self.down_sample_convs = nn.ModuleList([ ConvBlock(conv_channels, conv_channels) for _ in range(self.num_levels - 1)]) # 加权融合节点 self.weight_fusions_up = nn.ModuleList([ WeightedFeatureFusion(i + 1) for i in range(self.num_levels)]) # 自底向上 self.weight_fusions_down = nn.ModuleList([ WeightedFeatureFusion(self.num_levels - i) for i in range(1, self.num_levels)]) # 自顶向下 def forward(self, features): p_features = [] # 自底向上传播 last_p = None for idx, feat in enumerate(features[::-1]): if last_p is not None: upsampled_last_p = F.interpolate(last_p, scale_factor=2, mode='nearest') current_input = [feat, upsampled_last_p] else: current_input = [feat] weighted_sum = self.weight_fusions_up[idx](current_input) processed_feat = self.up_sample_convs[min(idx, len(self.up_sample_convs)-1)](weighted_sum) last_p = processed_feat p_features.append(processed_feat) final_outputs = [] # 自顶向下传播 last_p = None for idx, feat in enumerate(p_features[::-1][:-1]): # 跳过最后一个元素作为初始输入 downsampled_current = F.max_pool2d(feat, kernel_size=3, stride=2, padding=1) if last_p is not None: combined = [downsampled_current, last_p] else: combined = [downsampled_current] weighted_sum = self.weight_fusions_down[idx](combined) processed_feat = self.down_sample_convs[max(idx, 0)](weighted_sum) last_p = processed_feat final_outputs.insert(0, processed_feat) final_outputs.append(p_features[-1]) # 添加最顶层未参与下采样的特征 return final_outputs ``` --- ##### 2. 整合至主干网络 为了使 BiFPN 成功集成到现有框架中,比如 YOLOv8 或 EfficientNet 中,可以通过替换默认颈部结构的方式完成改造工作: ```python class BackboneWithBiFPN(nn.Module): def __init__(self, backbone_output_shapes, bifpn_repeats=3, bifpn_channel_width=64): super(BackboneWithBiFPN, self).__init__() self.backbone = SomePretrainedModel() # 假设这是预训练好的骨干网实例 self.bifpns = nn.Sequential(*[ BiFPNLayer(backbone_output_shapes, bifpn_channel_width) for _ in range(bifpn_repeats)]) def forward(self, x): base_feats = self.backbone(x) # 获取原始骨干输出列表形式[low_level -> high_level] enhanced_feats = base_feats.copy() for bifpn_layer in self.bifpns: enhanced_feats = bifpn_layer(enhanced_feats) return enhanced_feats ``` 以上代码片段展示了如何将多个堆叠起来形成完整的 BiFPN 层序列[^4]。 --- #### **注意事项** - 如果计划应用于实际项目,请务必验证硬件环境支持情况;某些特定算子可能会因为显存不足等原因引发错误。 - 对于超大规模数据集而言,适当降低重复次数或者简化内部运算逻辑可能是必要的优化手段之一。 --- ####
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值