tacoriceの日記

間違い等あれば指摘して頂けたら嬉しいです。

鳥コンペのふり返り

はじめに

 先日終了したKaggleのCornell Birdcall Identificationに参加しました。初めての音声認識コンペだったこともあり思ったようにいかず辛いコンペでしたが、音声処理や最近の音声認識のトレンド等色々勉強になったので記録として残したいと思います。
www.kaggle.com

 

コンペ概要

 音声データ(mp3)にどの鳥(264種類)の鳴き声が含まれているかを推定するマルチラベル分類のタスクです。
Code competitionであるので、推論はkaggleのカーネル上で行う必要があります。
学習データはシングルラベルですが、テストデータはマルチラベルでした。

 f:id:pino080:20200924072559p:plain

 

音声認識への取り組み方

 まず、最近の音声系の機械学習では音声データを画像に変換して、画像認識タスクとして解くことが主流のようです。これは、音声データを画像認識として落としこめばうまく学習できるのではという発想からきているようです。
機械学習分野の研究者、技術者は発想が豊かですね!

 具体的な手法については以下の記事で紹介されていますが、音声データをlogmel変換したメルスペクトログラムを画像としてとらえ、特徴抽出に2D CNNベースのモデルを使用し、CNNの出力である特徴マップで分類を行うという手法をとっています。出力はバッチサイズ、チャネル、周波数、時間の4次元あります。

qiita.com

 

 一方で、音声認識におけるデータ拡張手法は一般的な画像認識におけるデータオーギュメンテーションとは異なりSpecAugmentと呼ばれる手法がとられています。SpecAugmentでは時間方向での伸縮や以下画像のような周波数軸でのマスキングや時間軸でのマスキングの3種類が提案されており、認識性能の向上に大きく貢献しています。

f:id:pino080:20200924062601p:plain

qiita.com

 

実際のコンペの取り組み

 コンペ終了の約2週間前からスタートしました。音声認識コンペは初めてだったので公開カーネルやdiscussionの情報から自分でもできそうな手法を試していく方針で進めていきました。また、音声データの前処理の実装は追いつかなかったのでほぼ公開カーネルのものを引用させて頂きました。この辺の処理に関するカーネルがなければ参加できていなかったとさえ感じます。(thanks@Arai&Tawara)

 今回のコンペでは、事前学習のモデルとして主流のPANNsとResNeStを用いたものが多かった印象です。discussionでも、事前学習モデルの違いはスコアアップにほとんど差がないと議論されていたこともあり、それ以外のモデルは使用しませんでした。
 SpecAugmentの周波数マスキング(横方向)と時間マスキングを追加したり、値を大きくすると学習時のlossの減少が大きく、学習スピードが増加しました。ただ、publicスコアは向上しませんでした。また、CNNの構造や、画像サイズを変更しても、手元のCVは向上するのですが、publicスコアの向上は全く見られず、なおかつ、LBと相関があるCVが全くできないという状況でした。
 結局終盤まで、単体モデルでは公開カーネルを超えることができなかったので、方針をかえ、最後の三日間はスコアの良いアンサンブルの組み合わせを探すという方向に切り替えました。
手法としては、PANNsモデルの予測の閾値を高めに設定し、nocall(鳴き声なし)と予測される部分にResNeStモデルの予測結果で補完するという疑似的なアンサンブルの手法を取りました。
少し荒業な気がしますが、この結果何とか公開カーネルの壁を越えpublicで銅圏に食い込むことができました。

ソリューション

・ResNeSt50_fast model

image size: 224x547

loss:BCE

optimizer:Adam(lr=0.001)

scheduler:CosineAnnealingLR(T_max=10)

DataAugment:
・mixup
・SpecAugment

fold:StratifiedKFold(n_splits=5)

melspectrogram parameters:
・n_mels: 128
・fmin: 20
・fmax: 16000

threshold:0.46

 

・PANNs model

loss:BCE

optimizer:Adam(lr=0.001)

scheduler;CosineAnnealingLR(T_max=10)

DataAugment:
・waveform
・mixup
・SpecAugment

fold:StratifiedKFold(n_splits=5)

melspectrogram parameters:
・window_size=1024
・hop_size=320
・sample_rate=32000
・mel_bins=64
・fmin=50
・fmax=14000

threshold=0.7

 

 

結果

結果はpublic101位private123位でした。

少しシェイクダウンしてしまいましたが、なんとか銅メダル獲得です!

f:id:pino080:20200923050907p:plain

 

反省点

 今回、CNNの構造等のパラメータ変更中心にさわってみましたが、publicスコアの向上は全くみられませんでした。コンペ終了後の上位入賞者のソリューションをみると、音声ファイルから手動で鳴き声が現れてない部分を削除することや実際に音声ファイルをきいてクロップ時間変更をする等の前処理の部分で工夫しているものが多かった印象です。そこに関しては全然取り組めなかったのが大きな反省点です。

 

おわりに

CVの結果とLBが全く連動しておらず、色々と辛いコンペでしたが、学びも多く有意義な時間であったと思います。

kaggleに取り組む上で最も重要な忍耐力もだいぶ向上したと思います(笑)

今後も色々なコンペに挑戦していきたいです。

 

それからですが・・・

 

f:id:pino080:20200923050412p:plain

 通算でメダル二枚ゲットできたのでKaggle Expert昇格です!(パチパチ)
 
次はKaggle Masterを目指して腕を磨いていきたいです。