489. BirdCLEF 2022 | birdclef-2022
祝贺所有参赛者,感谢主办方举办这次比赛。这是我第3次参加BirdCLEF比赛,也是我第一次获得金牌。虽然这次我依然延续了临近结束才参赛的传统……距离截止日期前5-6天才提交了第一次结果。生活中总得有些改变。
借此机会,我将描述我在挑战过程中想到的一些想法。希望这些内容对其他参赛者和主办方也有参考价值。我的工作在很大程度上基于我的BirdCLEF 2021论文。此外,在我的BirdCLEF 2021和2020 Cornell Birdcall总结中也可以找到一些细节。
在今年的比赛中,有两个主要挑战需要解决:(1) 巨大的域差异,测试数据噪声非常大 以及 (2) 长尾类别分布,稀有类别的样本很少。
为了解决第一个挑战,我使用了传统的伪标签(PL)两步训练法:在第一轮中,模型学习鸟类信号的位置;在第二轮中,施加大量噪声。有了分割标签,模型就知道在严重噪声下去哪里寻找真实信号。除了粉红噪声和信号衰减外,还使用了雨林数据作为噪声源。
为了解决第二个挑战并使模型对不同的鸟叫声具有鲁棒性,我在大型2021+2022 BirdCLEF数据集上进行了预训练(2022数据的大小约为2021的1/5)。在微调期间,我保持骨干网络冻结,仅在2022数据上训练头部。我将所有不计分的类别分配给“unknown”标签,并进行了加权采样,概率以每个类别的样本数为条件,即 w~N^0.5。
与传统的音频模型相比,我在解决方案中使用的其中一个新颖之处是Constant Q-transform,而不是mel-scale频谱图甚至pcen。生成的频谱图质量要好得多,如下图所示:噪声影响更小,高频域细节丰富,对比度高,并且易于映射到序列模型(无需关心FFT中添加的填充)。但是,我没有时间对模型性能进行定量比较。CQT1992v2是nnAudio.Spectrogram库中CQT的一个非常有效的Pytorch(GPU)实现,可以轻松集成到模型中(确保禁用CQT的梯度)。在训练期间,我对变换输出使用了对数变换:x = (64*x + 1).log()。
self.qtransform = CQT1992v2(sr=32000, fmin=256, n_bins=160,
hop_length=250, output_format='Magnitude', norm=1,
window='tukey',bins_per_octave=27,)
我使用了半监督预训练的ResNeXt50和MiT-B2 transformer,以及Segformer骨干网络。最后一个卷积层后面跟着一个卷积,将特征图折叠成向量序列 (nemb=1024),然后是一个Transformer层,最后是一个头部,使用注意力机制产生序列和剪辑输出(有点类似于SED模型):
class AttHead(nn.Module):
def __init__(self, n_in,