返回列表

2nd place solution: SED + CNN with 7 models ensemble

553. BirdCLEF 2023 | birdclef-2023

开始: 2023-03-07 结束: 2023-05-24 环境监测 数据算法赛
第二名解决方案:SED + CNN 与7个模型的集成

第二名解决方案:SED + CNN 与7个模型的集成

作者:RihanPiggy (Kaggle Grandmaster)
发布时间:2023-05-25
最后更新:2024-04-04
得票数:64

祝贺所有获奖者!感谢Kaggle和康奈尔鸟类学实验室举办这场有趣的比赛。

这是我个人首次获得的金牌,对此成绩我感到很高兴。

这场比赛与往届BirdClef比赛(2020/2021/2022)有很多相似之处。因此我花了很多时间收集往届比赛中顶尖团队的解决方案。特别感谢大家分享这些重要信息!

让我简要介绍一下我的解决方案,我将在几天后更新更详细的说明。

最重要的部分(7个模型集成!)

请查看下方笔记本:
openvino就是你需要的一切!!

训练数据

以下是我的训练数据:

  • 2023/2022/2021/2020比赛数据
  • 2020年额外比赛数据
  • 来自xeno-canto的额外训练数据,包括2023年比赛物种的前景和背景录音(包含背景中仅有2023年比赛物种且少于60秒的录音)

我原本打算从ebird网站收集更多录音,但意识到ebird数据不公开且无法使用。我咨询了主办方并确认了这一点。感谢@tomdenton解答我的问题。

因此,我的训练流程不包含来自ebird网站的录音。

模型架构

首先,我使用了SED架构,与大家相同。

骨干网络包括:

  • tf_efficientnetv2_s_in21k
  • seresnext26t_32x4d
  • tf_efficientnet_b3_ns

它们都使用10秒片段进行训练。

其次,我采用了2021年比赛第二名提出的CNN架构。

骨干网络包括:

  • tf_efficientnetv2_s_in21k
  • resnet34d
  • tf_efficientnet_b3_ns
  • tf_efficientnet_b0_ns

除b0外,其余都使用15秒片段训练。b0使用20秒片段训练。

伪标签与人工标注

我使用SED模型生成伪标签,并通过分位数阈值提取潜在的nocall(无鸟声)片段。然后我通过听录音对潜在nocall进行人工标注。我标注了约1800条录音,但未观察到改进。可能伪标签包含更多假阳性而非假阴性。我没有时间进一步分析预测结果。

模型训练

数据增强方法:

  • 高斯噪声
  • 粉红噪声
  • 增益调整
  • 噪声注入
  • 背景噪声(2020/2021比赛的nocall + 雨林环境音 + 环境声 + freefield1010、warblrb、birdvox中的nocall)
  • 音高偏移
  • 时间偏移
  • 频率遮蔽
  • 时间遮蔽
  • 波形Mixup
  • 频谱图Mixup
  • 以0.5概率降低高频部分
  • 针对背景中仅有2023物种的录音的自Mixup(60秒音频 -> 分割为6×10秒 -> np.sum(audios,axis=0)得到10秒片段)

我使用基于primary_label和secondary_labels计算的权重来处理数据加载器中的不平衡数据集。

训练阶段

我采用两阶段训练:

  1. 在所有数据(834个物种)上预训练
  2. 在2023年物种(264个物种)上微调

两个阶段都先用CrossEntropyLoss训练,再用BCEWithLogitsLoss(reduction='sum')训练。CrossEntropyLoss收敛更快,但BCEWithLogitsLoss得分更高。

为增加多样性,模型使用不同窗口和不同mixup比率训练,部分模型仅用CrossEntropyLoss训练。其中3个模型在30秒片段上微调。

交叉验证策略

  • 对每个验证样本 - 将前60秒切分为片段 -> 预测每个片段 -> 取片段预测的最大值

CV与LB没有明显相关性,但提升LB的正确方法似乎不会显著降低CV。因此我在调优时监控CV指标。

推理过程

对于SED模型,输入10秒片段但仅在中心5秒缩减的CNN图像上应用头部,并使用max(framewise, dim=time)。

此外,SED模型使用tta(2s)测试时增强。

重要提示:将pytorch模型转换为openvino模型可显著减少推理时间(约40%)。(eca_nfnet_l0骨干网络的ONXX无法转换为openvino,因为timm中的stdconv层在前向传播中使用了F.batch_norm的训练模式)。这就是能集成7个模型的奥秘。

模型集成

我花了很多时间理解评估指标。集成方法如下:

  1. (加权平均,LB得分0.84,private得分0.76)对原始logit进行加权平均。这种方法对我而言没有意义,因为模型输出的logit不同不应简单相加,否则结果会有偏。但考虑到logit绝对值可能也影响得分且确实获得最佳LB,我选择用它进行最终提交作为赌博。
  2. (排名平均,LB得分0.83,private得分0.75)将logit转换为排名并对排名进行加权平均。我认为这是合理的集成方式,考虑到我没有可靠的CV。注意:本次比赛提交结果填充了5行1,因此排名应从0开始,防止最大排名在转换为百分位数形式后变为1.0。(例如,0, 0.333, 0.666是好的,而0.333, 0.666, 1.0不好,否则由于那些排名1.0的潜在假阳性会导致得分下降。)

基本上所有单模型在LB上的表现都达到约0.81-0.82,因此各模型权重相似以保持多样性,尽管更高的public LB需要sed v2s和sed b3_ns更大的权重。

观察private LB,加权平均似乎更好。嗯......为什么?

未生效的方法

  • 对比度增强
  • EMA(指数移动平均)
  • BirdNet
  • 根据前后5秒片段调整logit
  • Q变换
同比赛其他方案