612. BirdCLEF 2024 | birdclef-2024
感谢 Kaggle、主办方以及所有的参赛者。参加这场激动人心的比赛是一次非凡的经历。以下是我们第四名解决方案的概览。这一成就确实是团队努力的结果,@ajobseeker 和 @tamotamo 做出了同等的贡献。我很感激有机会在这次比赛中与他们合作。
更新 (2024-06-23):
添加了推理 Notebook 和训练代码。
推理 Notebook: https://www.kaggle.com/code/yokuyama/bc24-4th-place/notebook
训练代码 (Melspec 模型): https://github.com/yoku001/BirdCLEF2024-4th-place-solution-melspec
训练代码 (原始信号模型): https://github.com/tamotamo17/BirdCLEF2024-4th-place-solution-raw-signal
| 模型 | 公共分数 | 私有分数 | 公共分数 (+TTA) | 私有分数 (+TTA) |
|---|---|---|---|---|
| Melspec 模型 B (inception-next-nano) | 0.668 | 0.623 | ||
| Melspec 模型 A (rexnet_150) | 0.676 | 0.641 | 0.690 | 0.649 |
| Melspec 模型 A (seresnext26ts) | 0.682 | 0.645 | 0.693 | 0.651 |
| 原始信号模型 C (tf_efficientnet_b0_ns) | 0.673 | 0.620 | 0.691 | 0.636 |
| 加权平均 (Weighted Mean) | 0.717 | 0.667 | 0.731 | 0.676 |
| 加权平均 + 几何平均 | 0.732 | 0.677 | ||
| 加权平均 + 几何平均 + 平滑 | 0.741 | 0.685 | ||
| 加权平均 + 几何平均 + 平滑 + 截断 (最终提交) | 0.7469 | 0.6877 | ||
| 加权平均 + 几何平均 + 平滑 + 截断 + 与邻居取最大值 | 0.749 | 0.689 |
0.15*模型 B + 0.25*模型 A (rexnet_150) + 0.3*模型 A (seresnext26ts) + 0.3*模型 C(0.15*模型 B + 0.25*模型 A (rexnet_150) + 0.3*模型 A (seresnext26ts) + 0.3*模型 C) + 0.3*(模型 A (rexnet_150) * 模型 C)**(0.5)我们 heavily 参考了 2023 年第二名解决方案 的代码来构建此模型的训练和推理 pipeline。非常感谢 @honglihang 分享如此宝贵的信息。他们的代码库非常强大,经过少量修改,我们就能够创建一个 LB 分数为 0.68 的单一模型。
seresnext26tsrexnet_150 (2021-2023 预训练)验证策略 部分)inception-next-nano 带注意力头 (attention head)
from timm.models.inception_next import _create_inception_next
from timm.models.inception_next import InceptionDWConv2d
from timm.models._registry import register_model
@register_model
def inception_next_nano(pretrained=False, **kwargs):
print("inception_next_nano")
model_args = dict(
depths=(2, 2, 8, 2), dims=(80, 160, 320, 640),
token_mixers=InceptionDWConv2d,
)
return _create_inception_next('inception_next_nano', pretrained=False, **dict(model_args, **kwargs))
该模型 inspired by HMS 第二名解决方案。非常感谢 @cooolz!他们提供了 他们解决方案 的详细解释。
tf_efficientnet_b0_ns 带 SED 头使用训练数据进行验证并没有给我们可靠的结果,所以我们转向了合成数据方法。
虽然这种验证方法与 LB 结果并不完全相关,但与使用前 5 秒裁剪方法相比,它提供了更合理的结果。更多细节请参考 此 Notebook。
为了提高时间序列预测的准确性,我们采用了类似于子像素超分辨率的技术。在推理期间,我们不仅预测 5 秒的帧,还预测了偏移 2.5 秒的帧。然后我们将这些结果组合作为 TTA。这种方法有助于完善整体预测。
为了加快模型的推理时间,我们使用了 OpenVINO。此外,我们实施了 训练后量化 将模型转换为 INT8。
对于量化校准数据集,我们使用了模型的训练数据集,应用了诸如添加背景噪声和增益变化等增强。我们相信这些增强将有助于创建更适合处理更广泛测试数据场景的量化模型。
结果令人印象深刻:我们的推理速度显著提高,量化模型的运行速度提高了30-40%。
在执行量化时,选择要量化的层至关重要。我们观察到,排除头层 (head layers) 的量化往往会提高模型的准确性。
names = ['/head/Gemm/WithoutBiases', '/global_pool/Pow', '/global_pool/GlobalAveragePool', '/global_pool/Pow_1', '/global_pool/Clip']
quantized_model = nncf.quantize(
model, calibration_dataset, subset_size=600,
ignored_scope=nncf.IgnoredScope(names=names),
)
我们仅在提交截止日期前三天才开始进行量化工作,留给我们彻底验证集成和量化组合的时间不足。因此,我们在两次最终提交中仅在一次中使用了量化模型。(权衡:我们减少了此次提交的 TTA 运行次数。)
我们最终发现,启用量化并没有显著影响公共/私有分数。
通过使用几个技巧,我们能够在公共和私有榜单上将分数提高约 0.01。