6位の解法です。
⿃コンペ反省会6位解法チーム「Deepでポン」Hidehisa Arai1
View Slide
⾃⼰紹介@kaggle_araisanhttps://www.kaggle.com/hidehisaarai1213かつてKaggle Masterのアライさんという名前でKaggleをやっていたアライグマ東⼤航空宇宙の修⼠3年⽣をしながらNABLASという会社でパートタイムResearcherをしているAudioデータは昨年のFreesound AudioTagging 2019のコンペティションが初めてでその後業務でチョットダケ扱っていた2
結果Public 2nd (0.628) → Private 6th (0.668)3
解法概要4• 3ステージの学習によって段階的にラベルのノイズを除去• Sound Event Detection(SED)スタイルの学習および推論• 全データで学習 + EMAのモデル11個の重み付き和でアンサンブル
コンペの主課題Train/Testの乖離 (Domain Shift) WeakかつNoisyなラベル1. ⾳データの出⾃• Train: Xeno Cantoに収録者がアップロード• Test: (おそらく)野外設置型マイクロフォンで取っている2. アノテーション• Train: アップローダがつけた⾳クリップごとのラベル• Test: アノテータがつけたchunk(⼩区間)ごとのラベルTrainのラベルはクリップごとにしか存在しない(weak label)上に、主ラベルは1つのみsecondary_labelsという副ラベルがある場合もあるが信頼性はまちまち(noisy label)secondary_labelsはアップローダがつけていない場合もあり、複数種の⿃が鳴いていてもついていない場合もある(missing label)nocallクラスはTestにしか存在しない5
モチベーション ‒ domain shiftDomain Shiftを分解して考える: ⼊⼒、: ラベル、∗: 真のラベル(観測できない)"#$": "#$" → "#$"を推定するのが今回のタスク !"#$%≠ (!&'!)TrainとTestでは⼊⼒の性質が異なる• 集⾳環境の違いに由来• Testは遠くの⽅で⿃が鳴いていることが多くSNRが⼩さめ• ⿃の声以外の⾳イベントの頻度や種類・傾向なども異なる(と考えられる) !"#$%∗ ≠ (!&'!∗ )TrainとTestでは真のラベルの出現頻度が異なる• 集⾳場所の違いなどに由来• 集⾳地点の⿃の分布や鳴き⽅の差が反映されて分布差が出る• Testはパッシブなため、nocallが多いことも分布差につながっている!"#$%≠ !&'!TrainとTestでは⼊出⼒の対応関係がそもそも違う• アノテーション⽅法の違いに由来• Trainはアノテータが投稿者なのでアノテーションには⼤きなばらつきがある• Testはアノテーションがコントロールされている上、chunk levelでラベルがある6
モチベーション ‒ domain shiftTrainとTestでは⼊⼒の性質が異なる• 集⾳環境の違いに由来• Testは遠くの⽅で⿃が鳴いていることが多くSNRが⼩さめ• ⿃の声以外の⾳イベントの頻度や種類・傾向なども異なる(と考えられる)TrainとTestでは真のラベルの出現頻度が異なる• 集⾳場所の違いなどに由来• 集⾳地点の⿃の分布や鳴き⽅の差が反映されて分布差が出る• Testはパッシブなため、nocallが多いことも分布差につながっている!"#$%≠ !&'!TrainとTestでは⼊出⼒の対応関係がそもそも違う• アノテーション⽅法の違いに由来• Trainはアノテータが投稿者なのでアノテーションには⼤きなばらつきがある• Testはアノテーションがコントロールされている上、chunk levelでラベルがあるData Augmentationであり得るバリエーションを網羅ラベル⽐率を変えたデータで学習させたモデルをアンサンブルラベルの修正を⾏なって!"#$%を!&'!に近づける7 !"#$%≠ (!&'!) !"#$%∗ ≠ (!&'!∗ )
モチベーション ‒ label noiseLabel Noiseを分解して考えるWeak labelはnoisy labelラベルがクリップごとにしか存在しないこと⾃体がnoisyLabelにある⿃の声がない場合がある主ラベルは概ね信じていいが、⾳クリップ上でまばらな場合が多い副ラベルはよりまばらでほとんど聞こえない場合もあるLabelにない⿃の声がある場合もある2/3の学習データは副ラベルがない副ラベルをつけるかどうかは投稿者に委ねられているため、missing labelもある8ラベル: aldfly, leafly, amered, canwar ラベル: warvir
モチベーション ‒ label noise9Weak labelはnoisy labelラベルがクリップごとにしか存在しないこと⾃体がnoisyLabelにある⿃の声がない場合がある主ラベルは概ね信じていいが、⾳クリップ上でまばらな場合が多い副ラベルはよりまばらでほとんど聞こえない場合もあるLabelにない⿃の声がある場合もある2/3の学習データは副ラベルがない副ラベルをつけるかどうかは投稿者に委ねられているため、missing labelもある学習を⻑いchunkで⾏うことでchunkにラベル中の⿃の声が⼊るようにする蒸留により信頼度の低いラベルを排除学習させたモデルで副ラベルがないデータからmissing labelを発⾒
Sound Event Detection (SED)10今回のタスクを解くには⼤きく⼆つの⽴場があるAudio Tagging Sound Event Detection⼊⼒の⾳クリップ単位でラベルづけを⾏う ⼊⼒に時間情報込みでラベルづけを⾏う時間⽅向に集約(max, mean, attention,…)Feature Extractor特徴マップ⼊⼒(waveform,melspec,…)特徴抽出CNNなど Feature Extractor特徴マップ⼊⼒(waveform,melspec,…)特徴抽出CNNなどPointwiseClassifierClassifierClip-level予測Frame-level予測時間⽅向に集約(max, mean, attention,…)出⼒はClip-level予測とFrame-level予測の2つ
Stage 1115fold PANNsでmissing labelを⾒つける• PANNsのCnn14DecisionLevelAtt• ⼊⼒は30sでクロップしたchunk←Weak label対策• Data Augmentation ←()のシフト対策• Gaussian Noise• Pitch Shift• Volume Up/Down• Lossはclipwise outputとframewise outputの両⽅にかける• 5fold学習し、Out-of-Foldの予測でTrain全体の予測を作る• 副ラベルがないデータに絞って確率が>0.9かつ主ラベルではないクラスを副ラベルに追加←missinglabel対策Attention map要素積をとった後時間⽅向に潰して集約Feature ExtractorSegment-wise予測Clip-level予測(maxで集約)Clip-level予測(attentionで集約)ℒ = , (!"" + 0.5(, (#!$)Attention map→ 0.578(public) / 0.619(private) (銀圏)
Stage 2125foldのSEDモデルでラベルの蒸留• PANNsのアーキテクチャを継承• CNNをResNeSt50に変更• Stage1で⾒つけた追加ラベル使⽤ ←missing label対策• ⼊⼒は20sでクロップしたchunk←Weak label対策• Data Augmentation ←()のシフト対策• Gaussian Noise• Pitch Shift• Volume Up/Down• 3channel input (melspec, pcen, melspec ** 1.5)• Lossはclipwise outputとframewise outputの両⽅にかける• 5fold学習し、Out-of-FoldのFrame-wise予測を得る• 元のラベルをoofの予測で修正 ←noisy label対策264n_frame(≠len(y))クロップされたchunkFrame-wise予測元のClipごとのラベルChunk内の予測(確率値)をframe⽅向にmaxで集約し閾値をかけるnp.logical_and修正されたラベル閾値を変えることで修正の度合いを変化させモデルに多様性を与えられる→ 0.601(public) / 0.655(private) (⾦圏)
Stage 313ラベル修正の度合いを変化させた複数のモデルをAlldata + EMAで学習しアンサンブルの種を⽤意• PANNsのアーキテクチャ + ResNeSt50/EfficientNet-B0• Train Dataset/Train ExtendedのAll data training• Stage1で⾒つけた追加ラベル使⽤ ←missing label対策• ⼊⼒は20sでクロップしたchunk←Weak label対策• Data Augmentation ←()のシフト対策• Gaussian Noise• Pitch Shift• Volume Up/Down• 3channel input (melspec, pcen, melspec ** 1.5)• Lossはclipwise outputとframewise outputの両⽅にかける(EfficientNetはFocalLossを使⽤)• 元のラベルをoofの予測で修正 ←noisy label対策• Oof予測にかける閾値を0.3-0.7で変えてラベル修正の度合いを変化させる ←(∗)のシフト対策• 合計11個のモデルの重み付け平均(重みはpublic LB参考に⼿動調整)※ All data + EMA: Foldを切らずに全データをTrainに使い、重みのExponential MovingAverageをとったモデルを使うこと→ 0.628(public) / 0.668(private) (⾦圏)librosa.power_to_db(librosa.feature.melspectrogram(y, ))librosa.pcen(librosa.feature.melspectrogram(y))librosa.power_to_db(librosa.feature.melspectrogram(y) ** 1.5)
なぜ負けたのか?14優勝したいなら圧倒的な差をつけないと厳しいコンペだったラスト2週間の戦略の失敗• 新しいことを試さず、アンサンブルの種をずっと作っていた• 学習時間が2倍強になるためExtendedデータセットをギリギリまで使わなかった• Stage2とStage3でprivate scoreはほとんど変わっていなかった・・・(丸1ヶ⽉無駄に)締め切り前⽇に気付くアライグマ
その他諸々15その他反省点• Seedを固定する関数にバグがあり再現性が取れなくなった、しかも気がついたのがStage3の学習をしていたとき• パイプラインが複雑化した結果、新しく加えた変更で過去の実験が再現できなくなった• 結局1実験1scriptが⼀番わかりやすい(CPMPも⾔ってる)• Augmentationをエイヤで決めたのがたまたまワークしてしまったので使い続けていたが、pitch shiftが死ぬほど遅かったので削れば1.5倍くらい実験ができたはず・・・• 優勝者の解法でおそらくhard votingがかなり効いていたが、試しもせず可能性を排除してしまった効かなかったこと• Mixup• Logとる前に混ぜる(2nd,36th)• ラベルはUnionをとる(3rd ,36th)などが効いたらしい• Calltype classification• 実は⿃の鳴き声は複数パターンある• ⼤雑把に⾔ってもCallとSongはかなり異なるので別のクラスとして扱う• Calltypeというカラムがあったので⼿作業で綺麗にして871クラス分類するも変わらず• Larger model• 5thのOlegによると局所受容野が⼤きすぎるとダメらしい時間があればやりたかったこと• モデルを増やす• ラベルの修正を繰り返す• Locationとelevation予測を分類の修正に使う• ⿃の共起情報をもとに予測を後処理で修正• 背景雑⾳を混ぜ込む
Goldメダルはどうやれば取れるのか?• コンペの主題(メインの課題)を正確に把握すること• Bengaliのようにあまりはっきりと書かれていない場合もある• 最近はnoisy labelやdomain shiftが多かった(MLの研究の場でもホットな話題)• Discussion / Notebookには⼀通り⽬を通す• 公開情報で役に⽴つことは全てやるのが前提• 「みんながやっていること」は全部やった上でやっている⼈が少なさそうなことを試す• Notebookはノイズも多いのでDiscussion重視⽬(特にGMとか強そうなMasterが集まってるところ)• 難しいタスクは案外⽳場• とりあえず⼿をつけやすいタスクは乱戦模様になりがち• 0.000xを競うタスクは⼿数の勝負になることもある• 2sub/dayはソロの味⽅• Discussion/Notebookを投稿すると⾃分に有利になることもある• 議論が進む• コンペの流れを⽀配できる16