機械学習エンジニアの備忘録

主に自分が勉強したことのメモ

【Kaggle】鳥コンペ振り返り

はじめに

先日終了したKaggleのCornell Birdcall Identificationに参加し、1390人中122位(Top9%)で銅メダルを獲得することができました。
www.kaggle.com

f:id:rikeiin:20200921220543p:plain

本記事では自分のソリューションと上位陣のソリューションを簡単にまとめておこうと思います。

コンペ概要

与えられた音声データにどの鳥の鳴き声が含まれているかを推定するマルチラベルの分類タスクです。
学習データとして264種類の鳥に対してそれぞれ音声ファイル(mp3)が与えられており、長さ、ファイル数ともにばらばらです。
予測の際は3地点で採取された音に対して、site1とsite2では5秒毎、site3では音声ファイルごとにラベルを予測して提出する必要があります。
今回はcode competitionだったため、推論はすべてkaggleのnotebook上で行う必要があります。

コンペ中に取り組み

コンペ終了の約1ヶ月前から公開されているEDAやdiscussionを読み始めてスタートしました。
まずはわかりやすいtawaraさんやAraiさんのnotebookを参考に学習から推論までの一連のパイプラインを作ろうとしましたが、ここが一番苦労したかもしれません。。
そもそもテストのサンプルデータとサンプルの提出用csvがわかりづらく、どう提出のcsvを作ればいいのかわかりませんでした。
さらにtest audioがnotebookのcommit中には現れずにsubmissionボタンを押してからしか出現しないという仕様?により一連のパイプラインを作るのに一週間したらほど費やしてしまいました。

この時点で残り約3週間、音声データコンペは初めてだったので公開notebookやdiscussionの情報から自分ができそうなものを試していく方針で進めていきました。

学習データはシングルラベルでテストデータはマルチラベル、サンプルのテストデータがほとんどない、ということでLBと相関があるローカルのCVが全く作れずコンペ中は暗闇の中を進んでいる気分でした。
さらに、自力では最後まで公開notebookのパブリックスコアは超えられずになかなか辛い戦いでした。。

最終的な自分のソリューション

データ準備

  • 入力は音声波形をLogmelspecに変換した二次元画像でチャンネル数は1
  • 画像サイズ512
    • 公開notebookはほとんど224のサイズを使っていましたが、今まで自分が画像コンペに参加してきた経験上入力サイズを上げるとスコアがあがることが多かったのでサイズを上げてみましたが、実際に効果がありました。

Data Augmentation

notebookで公開されていた音声波形に対するものをいくつか使用。

  • TimeShifting
  • SpeedTuning
  • AddGaussianNoise
  • PitchShift
  • Gain
  • PolarityInversion
  • StretchAudio

Model

  • EfficientNet-B4
    • B2~B5まで試してもっともスコアが良かったB4を採用

Training

  • Stratified Kfoldで5CV
  • secondary labelを0.5のラベルで含めて学習
  • Loss
    • BCEWithLogitsLoss
  • Optimizer
    • Adam (learning rate 0.001)
  • CosineAnnealingLR(T=10)
  • epoch 50

需要はないとおもいますがGithubでも公開しています。

github.com

ensemble

最終的に以下の2手法で提出

  • EfficientNet-B4 + image size 512の5fold平均
  • EfficientNet-B4 + image size 320 + secondary labelの5fold平均

試したが効かなかったこと

  • external data
    • 効果があったといっている人が多かったが自分はなぜかあまり効果がなかった。ローカルのval Lossは明らかに下るがLBのスコアはむしろ下がっていた。(自分のresampleなどの前処理がバグっていた可能性。。)
  • logmelspecに対するmixup
    • 上位陣も多数使っていたが効果がなかった。なにかコツがあるんだろうか?
  • denoise処理
    • 公開されていた音声に対するノイズ削減処理を試してみた。自分の耳で聞くと明らかに鳥の鳴き声がわかりやすくなった気がするがあまりスコア向上にはつながらなかった。また、推論時間が大幅に増えるので結局採用しなかった。

結果

最後まで公開notebookを超えられなかったので諦めていたがshake up?してぎりぎり銅圏内に入ることができました!

上位ソリューション

公開してくれているソリューションをざっとまとめて見ました。
自分が読み間違えている部分もあると思うので間違っていたらぜひ教えて下さい。

1st (https://www.kaggle.com/c/birdsong-recognition/discussion/183208)

  • based on sound event detection (SED) model
  • no external data
  • data augmentation
    • pink noise
    • gaussian noise
    • gaussian snr
    • gain (volume adjustment)
  • model
    • sedでバックボーンをdensenet121
      • パラメータを減らして過学習を防ぐ
    • attentionのclamptanh
  • training
    • mixup
    • specAugmetation
    • trainining on 30 second clip
    • bce loss & secondary label
  • threshold
    • framewise_output, clipwise_outputともに0.3
    • framewise, clipwiseともに現れた鳥を予測に
    • specAugした10TTA
  • CV vs LB
    • local CVできなかったのでLBを参考にした
  • ensemble
    • LB scoreを参考に13modelの4vote

2nd (https://www.kaggle.com/c/birdsong-recognition/discussion/183269)

  • 約20000の音声ファイルから手動で鳴き声が現れてない部分を削除した(!)
  • powerを0.5から3に。0.5だと背景ノイズが鳴き声に近くなる
  • 異なる背景ノイズをミックス
  • 0.5の確率でupper frequencyを減らした
  • 6 model ensemble

3rd (https://www.kaggle.com/c/birdsong-recognition/discussion/183199)

  • aggressiveなdata augmetation
    • gaussian noise with a sound to noise ratio up to 0.5
    • background noise
      • 鳴き声が含まれていない背景音をミックス
    • modified mixup
      • 通常のmixupと変えてラベルをそのままの強さで
        • 両方とも正しいラベルを予測させる
    • random clopではなくout-of-foldで正解予測確率が高い部分をクリップ
  • model
    • 4 model ensemble
      • resnext, resnest and external data
  • 後処理
    • しきい値0.5
    • 前後の窓のscoreも集約して確率の上位を答えとする
      • site 1,2は上位3つ
      • site3は音の長さによって

4th (https://www.kaggle.com/c/birdsong-recognition/discussion/183339)

  • use external data
  • 音の強さで鳴き声が現れていそうな部分をクロップ
  • feature extraction
    • パラメータを変えたlogmelの3チャンネル
    • secondary labels
  • model
    • efficientnetB3~B5
    • multi-sample dropout
  • training
    • data aug
      • gain
      • background noise
      • low frequency cutoff
    • mixup
  • 4 model ensemble

5th (https://www.kaggle.com/c/birdsong-recognition/discussion/183300)

  • sed model
  • data aug
    • backgrounds (all from external data thread)
    • pink and brown noise
    • pitch shift
    • low pass filtering
    • spec augments (time and frequency masking)
  • energy base crop & label smoothing (secondary label)
  • longer input (10~30sec)

反省・所感

上位のソリューションを見るにかなりアグレッシブなDataAugmentationをかけているものが多いですね。
discussionでtrainとtestのSNRがかなり違うことが議論されていたので学習データに対して大きなノイズを加えてることで対応していたようです。
自分も外部ファイルからbackground noiseを加えたりpink noiseやbrown noiseを入れたりといろいろとやれたなあと思いました。(pink noiseが効くことはdiscussionにてホストが発言していたことに気づかなかった。。)
SpecAugmentも忘れていました。。

また学習データから如何に鳥の鳴き声をクロップするかが重要だったようです。
普通にやると1ファイルからランダムに5秒クロップする方法になるんですが上位ソリューションは頑張って鳴き声が含まれてそうな部分をクロップする処理をしています。
SEDを使う場合もPeriodを10〜30秒で長くとることで鳴き声が含まれない部分をクロップしてしまうリスクを減らす効果があるようです。

やはりデータを自分の耳で聞くことは重要ですね。画像コンペのときもそうですが自分でしっかりデータを確認することの重要性を再確認しました。


最後までパブリックのnotebookスコアを超えられなくて苦しかったですが最終的に銅が取れてよかったです。
コンペの内容も面白く、音声データの扱いもかなり勉強になったので参加してよかったなと思います。

今後も面白そうなコンペがあれば参加していきたいです。