データ分析メモ

主にデータ分析のことについて書きます。

NBME - Score Clinical Patient Notes 振り返り

はじめに

2022年参加した分析コンペの記録 第3弾です.
今回は銀メダル獲得することができました(Private 39th)

NBME - Score Clinical Patient Notes とは

NBME - Score Clinical Patient Notes | Kaggle

NBMEが主催したコンペで、解くべきタスクは「患者の問診メモから症例に関する重要な要素を抽出する」 ことでした.
標準化された患者(特定の臨床例を描写するように予め特訓を受けた人)の問診メモに対し,
「家族の病歴」や「動悸・息切れ」などの症例にあたる箇所の文字列でのindexを予測します.

例えば 患者の問診メモ.
17 y/o M , Dillon Cleveland comes with c/o of palpitaions. Palpitaions are sudden onset ond have been occuring for the last 3-4 months. He has had 1-2 episodes of palpitaions every month. The last episode was accompanied by breathlessness and constricting pressure over chest which releived on its own. No aggravating or relieving factors. No h/o fever, pedal edema, cough, hemoptysis. no h/o of dyspnoea, orthopnoea. no h/o weight loss, tremors. PMH; not allergic to any medications. no known allergies. No similar episode in hte past. Psh; no history Family h/o; Mother has thyroid condition, father had acute MI last year. Social drinker . Sexaully active with girlfriend sincea a year. No h/o STD.

症例の特徴
Family-history-of-MI-OR-Family-history-of-myocardial-infarction

が与えられた場合に、予測するのは
17 y/o M , Dillon Cleveland comes with c/o of palpitaions. Palpitaions are sudden onset ond have been occuring for the last 3-4 months. He has had 1-2 episodes of palpitaions every month. The last episode was accompanied by breathlessness and constricting pressure over chest which releived on its own. No aggravating or relieving factors. No h/o fever, pedal edema, cough, hemoptysis. no h/o of dyspnoea, orthopnoea. no h/o weight loss, tremors. PMH; not allergic to any medications. no known allergies. No similar episode in hte past. Psh; no history Family h/o; Mother has thyroid condition, father had acute MI last year. Social drinker . Sexaully active with girlfriend sincea a year. No h/o STD.
になります. (正確には該当箇所が先頭文字から xx番目~yy番目 のindexでF1 Scoreが評価指標)

私は、英語のリスニング問題みたいな設定だなと思っていました.
最初に設問である症例の特徴を読んでから問診メモを読むと、正解箇所がとてもよく理解できました.
与えられていたデータは下記の通りです.
患者メモ: 42,146件
症例: 143例
1人の患者メモに複数の症例が入っていますので、全体としては612,602件の患者メモと症例がセットになったデータが与えられていました.
ただし、その中で正解キーワードが与えられているのは14,300件ほどしかなく、testデータも20,000件が対象となっていたようです.
つまり与えられているデータのほとんどがラベルがつけられていない状態であり、このデータをうまく活用することが肝であるように思いました.
上位解法でもラベルが与えられていないデータを活用し全体の精度を上げるように工夫されている人が多く、
kaggleでよく使われるPseudo-Labelingがうまく作用したと思います.

また、人がアノテーションをしているため与えられているラベルでも揺れが大きかったです.
具体的には had, hasなどの動詞が抜けていたり、アノテータによってつける箇所がバラバラでしたが
どのアノテータがつけたかなどの情報はないため, 全てを正解させることができないようなデータでした.

コンペ期間中はCVとLBが綺麗に相関しており、その辺りは非常に取り組みやすかったです.
ただしコンペ終盤で複数modelのensembleをしてからはCVが上昇してもLBは思ったほど伸びず
この辺りにアノテーションの揺れなどが絡んでいるかもと考えていました.

やったこと

Solution図

コンペ序盤~中盤

序盤から、nakamaさんによる強強ベースラインが公開されていましたのでそちらを基に改良を加える方針で取り組んでいました.
NBMEコンペの前に行われていたNLP系のコンペ Feedback PrizeからDeBERTa-v3系のモデルが使われ始め、NBMEでもDeBERTa-v3-Largeのモデルを主流に取り組むことにしました.
これまではNLPであれば、RoBERTaが初手で試すモデルとして有力でしたが潮流が少し変わったように思います.

序盤はDeBERTa-v3-BaseやDeBERTa-v3-Large, RoBERTa-Largeなどの新旧強いとされているモデルで,
HeadのカスタムやLabel Smoothingなど分類問題で良く使う手法を広く試していました.

この時点で作成したモデルのCVの結果はこちらです。

BackBone CV LB
DeBERTa-Base 0.8629 0.864
DeBERTa-Large 0.8755 0.879
DeBERTa-v3-Base 0.8590 0.861
DeBERTa-v3-Large 0.8810 0.883
DeBERTa-Base x LSTM 0.8611 0.864
DeBERTa-Base x Conv1D 0.8654 0.864
DeBERTa-Base x Layer Concat 0.8617 -
DeBERTa-Base x Multi Sample Dropout 0.8648 0.865
DeBERTa-Base x Label Smoothing Loss 0.8614 -
DeBERTa-Base x Layer Freeze 0.8689 0.866
RoBERTa-Large 0.8714 0.873

実験を素早く行えることから、DeBERTa-Baseを中心に効果ありそうかどうかの見極めを行っていました.
RoBERTaはcharacterレベルの予測をするとtokenizerの都合上indexがズレるという指摘もあり,
trim_offsets=False で使用していました.

ただ、この時LBで上位チームは0.890近くのスコアを出しており何か学習方法やデータでやり方を大きく変えないと追いつけないと感じていました.

コンペ中盤~終盤

LBで上位を走っていたtheoさんのtrain.logの情報から、trainデータだけではなくannotationがされていないデータも使っていることが判明しました.
Pseudo Labelingによってannotationがされていないデータに対して、学習したモデルでの予測ラベルを擬似的に使用し学習する方針へとシフトすることに.
ただし、他のFoldの影響が入らないように Fold1で学習したモデルで全てのデータを予測し、
Fold1のtrainデータ + Fold1で学習したモデルで予測したデータ を作成し学習することにしました.
この学習方法により、DeBERTa-v3-Largeで CV 0.8810 -> 0.8859 へと大幅に向上させることが出来ました.

また、LBのスコアもかなり密で詰まってたこともあり個々のSingle Modelでの精度向上が必要と感じ
MLM(Masked Language Modeling)による事前学習も実施しました.

このPseudo LabelingとMLMによって、RoBERTa-Largeでも十分精度を伸ばすことができ
CV 0.8714 -> 0.8852 へと上がりEnsembleでも使用できそうなモデルを育てるところまで至りました.

今回はこのMLMとPseudoがかなり効いていましたが,それはデータの性質が大きく影響すると考えています.
患者メモに書かれている内容や構造が似ていることや、trainだけで学習したデータでも十分精度が高く得られることから
上手くハマったと思いますが、今後他のNLP系タスクであってもとりあえずMLMは試すと思います.

私はRoBERTa-LargeでCV 0.8852を出して喜んでいましたが、その間にチームメンバーの方が同様の方法で強強Single Modelを具備されていました.

BackBone CV
DeBERTa-v3-Large 0.8904
DeBERTa-v3-Large 0.8926
RoBERTa-Large 0.8903

あとはこれをEnsembleしていくことで精度向上を図っていましたが、この時点で CV 0.89253 LB 0.889 で 0.890の壁にぶち当たっていました.

後処理

Ensembleを進めることによってCVとLBが徐々に乖離し始め, このままでは最終subも選ぶのも難しく
またOOFで当たっていないデータに着目すると Tokenizerが上手く単語を切れてないケースに対応できていないことが分かりましたので
ルールベースの後処理によって外れているケースへの対応を考え始めました.

tokenizerによって先頭文字が抜けるパターンというのは、下記のようなケースです.

本来は, mom has thyroid が正解なのですが、momの先頭のmとその前の文字:との間にスペースがなく
単語が不自然に切られているケースで一文字分取りこぼしています.

同様のケースとして、-ThyroidのTが抜けるパターンもありました.

これに対し、我々のチームで取り組んでいたのは

  • 正規表現パターンで患者のメモを分割して単語化
  • 予測した文章が単語途中から始まってる場合は、単語先頭まで補完

という手法です.

この後処理によって CV 0.8881 -> 0.8899 LB 0.887 -> 0.889 へとSingle Modelで向上することができ、Ensembleで LB 0.890 へと伸びました.
ただしここからは色々後処理のルールベースを追加してもCVは上がるけどLBが下がるということが続き
CVとLBが相関していそうなデータだったので CV向上 LB向上 したルールを採用する方針にしました.

CV, LB両方にきくルールを見つけるため当たっていないデータは逐次見ながらルール作って取り組んだものの
最後まで両方に効果的なものは追加できず で終了しました.

ルールベースの後処理は, 非常に地道な作業ですがスコア管理もしやすいメリットがあるので
Deepでポンだけでなくpython実装力も同時に身につけていく必要があると改めて感じています.

最終日付近になり, subのバリエーションを増やしたいということで
全データを使ったmodelを加えました.

結果的にはこの全データ学習modelが最後追加されたことでLB 0.891を達成できたので取り組んで良かったと思います.

全データ学習はCV計算ができないので正直使い所が難しいですが、今回はPsuedo Labeling込みのデータで1epoch回すとおよそ収束することから
全データ学習モデルを加えるに至りました.

最終的なスコアは以下の通りです。

Model CV
DeBERTa-v3-Large 0.8904
DeBERTa-v3-Large 0.8926
DeBERTa-Large 0.8876
RoBERTa-Large 0.8903
DeBERTa-v3-Large all train

結果

Public 0.891 Private 0.891で39thでした.
スコアがかなり密なので, 順位はShakeするかと思いましたが無事Shake Upして銀メダル獲得できたので安堵しています.

所感

DeBERTa-v3-Largeがかなり強く、初手で試すモデルが変わるかもしれないと感じています.
MLM->Pseudo->後処理 と順々に精度が上がる取り組みを続けられ、最後までスコアを伸ばせたことは非常に良かったです.
上位に入った皆様の考えや試したことなども今後まとめていきたいと思います.
また、チームで参加してくれたメンバーにも非常に感謝しています.
これで銀メダルx2 銅メダルx3で、Masterまで金メダルという非常に大きなハードルを残すのみとなりましたが
引き続き精進していきます.

Jigsaw Rate Severity of Toxic Comments 振り返り

はじめに

2022年参加した分析コンペの記録 第2弾です。 前回に引き続き、成績としては芳しくない結果でしたが何かの参考になれば幸いです。 (Private 452th)

Jigsaw Rate Severity of Toxic Comments とは

Jigsaw Rate Severity of Toxic Comments | Kaggle

Alphabet参加のJigsaw/Conversation AIが主催したKaggleでは4回目のコンペです。 過去3回のコンペの中には、WikipediaTalk pageに書かれている有害なコメントを分類するタスクなどがありました。

これまでは既にコメントに対して、有害かそうでないかのアノテーションがされていましたが 今回のJigsawコンペではアノテーション済みの学習データは存在しないことが特徴的でした。

与えられていたデータは評価用の[validation_data.csv] で、アノテータがどちらの文章が有害かを判定した結果です。 1つの文章の組み合わせに複数人のアノテータが評価をしており、必ずしもアノテータ全員の結果が一致するとは限りません。(以下、アノテータによる評価が一致しない例)

worker less toxic more toxic
A ######## ********
B ######## ********
C ******** ########

よって、validation_data.csvでの評価が less < more で全て一致することはあり得ず、理論上の正解限界値は0.824であることがDiscussionで指摘されてました。該当Discussion

参加者が取り組むタスクは、テストデータとして与えられているtextデータに対して有害度をRankingにすることです。

Rankingをもとに、テストのtextデータの組み合わせに対してアノテータの評価と一致するかどうかを競います。

コンペホストからは、モデルの学習に役立つ可能性のあるデータとして過去のJigsawコンペのデータやRudditのデータが推薦されていました。

また、このコンペの特徴としてLBの結果に使われるデータがテストデータの5%しかないことが挙げられます。 テストではトータルで200,000件の組み合わせ評価がされるので、10,000件の組み合わせ結果がLB上に表示されます。 validation_data.csvは30,000件の組み合わせが存在しており、Trust CVが試されるコンペでした。

やったこと

Solution図

f:id:forcelog:20220208185156p:plain
jigsaw_solution

コンペ序盤~中盤

PetFinder2で惨敗した私としては、過去データセットが重要であると睨んでいました。

また、昨年参加したNLP系のコンペ CommonLitの1st solutionでも外部データセットを用いた解法が紹介されていましたので 過去のデータ&類似した外部データ での学習に重点的に取り組みました。

外部データはHateSpeechDataを基に、英語のデータセットWikiSNSでのデータをいくつかピックアップして使用することにしました。(以下、使用したデータセット)

DataSet Target 概要 Link
Ruddit Offensive Redditから抽出されたコメント github
wiki-attack attack 英語版Wikipediaの100k以上のコメント github
toxic-spans all toxic or not toxic SemEval2021で使われたデータセット github

さらに過去コンペで既に学習されたモデルがHuggingFaceにあげられていたのでそちらも活用しました。 unitary/toxic-bert

この時点で作成したモデルのCVの結果はこちらです。

BackBone Dataset CV
unitary/toxic-bert jigsaw-classification 0.693337
unitary/toxic-roberta jigsaw-unbiased 0.699714
unitary/toxic-xlmroberta jigsaw-multilingual 0.697921
unitary/toxic-albert jigsaw-classification 0.694334
unitary/toxic-albert jigsaw-unbiased 0.685897
unitary/toxic-bert Ruddit 0.647270
roberta-base jigsaw-unbiased 0.697124
deberta-base jigsaw-unbiased 0.698585
Luke-base wiki-attack 0.687126
TFIDF x Ridge wiki-attack 0.678956
TFIDF x Ridge jigsaw-classification 0.689053
TFIDF x Ridge Ruddit 0.632490

ここまでを単純平均したEnsembleでは CV: 0.707849 LB: 0.77870 でした。

LB上では0.8はおろか、0.9を超えるチームもあり外部データを軸にしたこの作戦では厳しいのかと思い始めていました。

ただこの結果がPrivateでは0.81181で一番高かったので、ここから作戦を変えたのが大きな敗因だと考えています。

コンペ終盤

中盤まで試していた結果から、validation_data.csvで less < moreが成り立たないものに着目しました。 BERT系のモデルからはLast LayerのAttentionも出力し、なぜ当たらないのかの考察をしたところ

  • Toxicと思われる単語にAttentionが強い
  • 当たっていない文章はToxicと思われる単語が入っていないことがあり、皮肉やアカウントBANされたことへの謝罪などが入っている

と目星をつけていきました。

※実際にアノテータのless < more多数決と予測値の傾向が一致しなかった例.

※生のデータを載せますので、不快に思われる可能性のあるテキストが含まれます

-------------------- less toxic --------------------

LOL; charles, you are a real fag aren't you? siding with chinks?? 
go fuck yourself, asswipe! we don't need no chinks in here. 
FAG
-------------------- more toxic --------------------
"
I'm not the one who added that source, neither had I actually read it before hand. On the subject of ""that you or any other Cradle fan made"" - that sounds fairly ridiculous, as you could just as well say that about any topic on Wikipedia. I'm not arguing this because I think there's a source that was added that proves it, it seems to be fairly obvious as the only difference was the back ground (at one point there was a picture of the original on Wikipedia, which was linked from this article, but it got deleted). It's like saying that the Sigil of Baphomet requires a source to say it was based off a pentagram. ≈  "


-------------------- less toxic --------------------
Wesley Bartz likes to suck cock. Loves that cock. He can't live without the cock
-------------------- more toxic --------------------
Yay! Here's a cookie... oh wait I ate them all. ^_^; Well, rain check on that cookie. )  

そこで、これは過去のデータだけを学んでいては当たらないのではと考え、validation_data.csvで学習するように作戦変更をしました。 モデルも中盤まで試していた中で、RoBERTa-BaseとDeBERTa-Baseが良さそうだったことも踏まえ

使用するモデルはBytePairTokenのTokenizerを使っているRoBERTaと、WordPieceTokenのDeBERTaを軸にアンサンブルする方向で考えモデルを作成するに至りました。

validation_data.csv の学習

validation_data.csvの学習をするにあたり、重要なのはCross Validationの方法です。

例えばWorker(アノテータ)でStratifiedKFoldをするとFold間で同じ文章の組み合わせが出現することになるので、

Fold間で同じ文章の組み合わせが出現しないようなCross Validationを考える必要があります。

幸いにも公開CodeでGrandMasterのtitoさんがFold間での同じ文章の組み合わせが出ないような戦略を共有してくれていたので、そちらを使用しました。Jigsaw CV strategy

あとは less < moreの関係性を学ばせるためにMarginRankingLossを使用し、moreとlessでmarginだけ離すように学習をしています。

モデルはBytePairTokenベースでRoBERTaに加えてGPT2も回し始めるに至ったのですが、GPT2は学習がうまく進まなかったので別Taskと合わせて学習させるようにマルチヘッドにしました。

この時、別Taskで解かせていたのはDetoxifyを使った予測値を学習させるようにしています。

また、過去のJigsawコンペ解法を参考に最終層のEmbeddingだけでなく最終から4層分のEmbeddingをConcatするなども同時に試しております。参考

最終から4層分のEmbeddingを入れるのは層ごとに異なるレベルの文章表現を学習していると言われているからであり、下層には表面的な特徴、中層には構文的な特徴、そして上層には意味的な特徴があると考えられています。

今回は特に単語などの表面的ではなく構文的な特徴なども加味したかったので上記方法を取るに至りました。

validation_data.csvを上記方法で学習するようになった結果、CV Scoreは大きく前進しこの方法でいけると信じ切っていましたので中盤まで使っていた別データセットのモデルはすべて使わないと判断しました.....

Model CV
RoBERTa-Base 0.72898
DeBERTa-Base 0.73502
GPT-2 0.74409
GPT-2(Concat Layer) 0.75203

今思うと、ここでのマルチヘッドでの学習が何かリークしていたのかCVが高く出過ぎていたなと思います。

他にチームメンバーが試していたこと

私が試したこととその経緯については上記で書いたとおりですが、チームメンバーが試したこともざっくり紹介します。

  • 過去コンペでのMLM(Masked-Language Modeling)による事前学習 → validation_data.csvによる学習
  • 過去コンペとRudditデータでそれぞれTF-IDF x Ridgeによる線形モデルでの学習

最終的なスコアは以下の通りです。

Model CV
RoBERTa-Base 0.72898
DeBERTa-Base 0.73502
GPT-2 0.74409
GPT-2(Concat Layer) 0.75203
RoBERTa-Base w/ MLM 0.70403
TFIDF x Ridge mean 0.69214
Ensemble 0.74223

結果

453thで惨敗です。中盤まで試していた外部データセットも混ぜた結果をEnsembleしておけば良かったと反省をしております。

所感

NLP系のモデルの学習や、MarginRankingLossなど新たな学びも多くありましたのでこれがまた自分の糧になっているとポジティブに考えることにします。

運要素が強いなど言われておりましたが、信じられるCVを作ることができるかやモデルが良くなっていると信じ抜くことが非常に重要だったと思います。

上位に入った皆様の考えや試したことなども今後まとめていきたいと思います。

PetFinder2 振り返り

はじめに

2022年からは自分の備忘録も込みでコンペの振り返りを発信していこうと決めました。

どんなに成績が悪くても自分なりの学びを残せていけたらと思います。

PetFinder2 コンペとは

PetFinder.my - Pawpularity Contest | Kaggle

petfinder.myに登録されている犬と猫の写真から人気度を回帰予測するテーマでした。

人気度はPawpularityというスコアでPetFinder.myが独自に算出されている指標で、トラフィック情報を元に算出されているようです。

使用できるデータは犬や猫が映っている画像以外に、画像に関するメタデータが与えられていました。メタデータは全て0 or 1のフラグ情報のみとなっています。

このコンペ特有のポイントといえば、1日2subしか出来ないということが挙げられます。通常は1日5subまで出来ることが多いですが2subしか出来ないので、とりあえず実験回して出してみるということがやりづらかったです。

これまで以上にCVの重要性が大きかったように思います。

やったこと

コンペ初期

2021年はSwinTransformerの登場から、画像コンペではSwinTransformerを試すようになっていましたのでこのコンペでも初手としてSwinTransformerを試しました。

回帰問題ということもあって、Loss関数にはRMSEを使用していましたが思った以上にスコアが伸びず....

Discussionを眺めていると「targetの値を0~1に変換し、Loss関数にBinaryCrossEntropyを使用する」というアイデアが共有されていました。

回帰を分類問題のように解くこの手法は、3年前のコンペから使われている手法のようです。参考 Elo Merchant Category Recommendation | Kaggle

上位解法でもLoss関数にはBCE(BinaryCrossEntropy)を使っている人がほとんどで、回帰を解く方法の1つとして今後も試されるものと思います。

Loss関数にBCEを使えばいいと分かってからは、他の探索に入りました。

コンペ中期

メタデータは与えられているものの画像から得られる情報がメインとなっているのでこれまでの画像コンペの知見を活かしながら、CVを下げるように実験を回していました。

具体的にはDataset、Augmentation、Model、学習方法の観点で考えていました。

Dataset

Discussionを読んでいるといくつかDatasetに関するスレッドが建てられており、私がその中でも使用していたのは以下の2つです。

  1. Petの顔画像中心のデータセット(EfficientDetやYOLOなど)

  2. 重複している画像を削除したデータセット

今回のデータセットの中で何かできることを終始探していたのですが、ここが大きな敗因だと考えています。

Augmentation

Albumentationに搭載されているAugmentationで意味ありそうなものは順々に試していきました。
独自でAugmentationを考えていたものとしては、アスペクト比が変わらないようにリサイズするような手法なども試していましたが精度向上には寄与していなかったように思います。
最終的に使用したAugmentationは以下の通りです。

A.Compose([
            A.Resize(config.img_size, config.img_size),
            A.HorizontalFlip(p=0.5),
            A.VerticalFlip(p=0.5),
            A.Blur(p=0.3),
            A.RandomBrightnessContrast(p=0.5),
            A.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1),
            A.Normalize(mean=[0.485, 0.456, 0.406],
                        std=[0.229, 0.224, 0.225],
                        max_pixel_value=255.0,
                        p=1.0),
            ToTensorV2(),
])

Model

SwinTransformerなどのVision Transformer系とCNN系を試していました。
基本的にはtimmに搭載されているモデルの中からImageNetの結果を見ながら試していました。
timm以外では、コンペ終盤に出てきたConvNextも最後の足掻きとして試してみました。
Ensembleに最後用いたモデルとその結果を紹介します。スコアが多少弱くてもEnsembleでいい感じにならないかと甘い考えを持っていました。

※通常のコンペであればとりあえずCVと比較するためにSubをしながらLBの値も確認していたと思いますが、2subしか出来ないのでCVしか出してないものもありますのでCV値のみ紹介します。

Model Dataset CV
swin_base_patch4_window12_384_in22k 顔中心 18.10664
vit_base_resnet50_384 顔中心 18.01175
deit_base_patch16_384 顔中心 18.01672
swin_large_patch4_window12_384_in22k 顔中心 17.77069
convnext_base 顔中心 17.93557
tf_efficientnet_b5_ns 顔中心 18.40857
dm_nfnet_f4 顔中心 18.47753
swin_large_patch4_window12_384_in22k 重複削除 17.48302
swin_base_patch4_window12_384_in22k 重複削除 17.58015
deit_base_patch16_384 重複削除 17.86186
vit_large_r50_s32_384 重複削除 17.74853
tf_efficientnet_b5_ns 重複削除 18.40857

※使用したDatasetの違いで同じモデルでも複数存在しています

学習方法

画像コンペでよく見かけるSelf-Supervised Learningや、Mixupなどを試していました。
いくつか試したものを箇条書きでまとめます。精度向上に働かなかったものもありますが、私のやり方が間違っていると思いますので上位解法とソースを基に勉強させていただきます。

  • Mixup
  • TTA
    • 最終的には時間の関係上外しました
  • 最初2epochと最後2epochはAugmentationしない
  • Label Distribution Loss
  • 1つのバッチの中でランキングを当てるように学習
    • 全く収束しませんでした
  • 2つの画像を比較して、どちらが人気かを当てるように学習
    • 試したのが終盤でSubの中には入れられなかったです
    • 入れてもあまり寄与していなかっただろうと思います

コンペ終盤

Ensembleに使えるモデルをたくさん作っておいて最後にEnsembleを試しました。
公開CodeやDiscssionでSVRの話が出ていたので、Ensembleはできる限り弱学習器を使う方がいいように思っていました。
1st Stageでは上記のModelから予測値を算出し、2nd Stageでは各モデルの予測値をInputにSVR, Ridge, Lassoによる回帰予測を実施しました。最後、SVR、Ridge、Lassoから出てくる予測値は平均値にすることで出来る限り過学習がない方向で最終Subを作成しています。

結果

1694thで大惨敗です。Publicも1112thで公開Codeすら超えられませんでした。
ただ自分なりの意地で公開Codeをコピーする気にはなれず、最後まで自力でモデル作成と学習方法で何か工夫できないか模索していました。
この経験は次に活きると信じています.....!

上位解法

2021年1月16日時点でDiscussionに上がっていたものをいくつか紹介します。

1st Solution

1st Place - Winning Solution

ImageNetで学習した重みによる埋め込み次元をSVRで学習していたようです。
使用したモデルはtimmでViT系とCNN系、CLIPのようです。
ここからは所感ですが、CLIPを使う発想はなかったこととFineTuningすらしていないことが衝撃でした。
FineTuningすらしていないのは今回のコンペ特有だとは思いますが、
予測値を使うのではなく埋め込み次元を基にSVRを使うのは試すべきだったと反省しています。

2nd Solution

Tentative 2nd place solution

SwinTransformerをベースにViT系をいくつかEnsembleされているようです。
Loss関数にはBCE以外にPoisson、MSEやCEなども使われているのでこの辺りも自分と大きな違いかと思います。
また、前回のPetFinderコンペと重複している画像は前回コンペのメタデータをjoinしながら学習されていたようです。
その際にTargetの分布が崩れないようにjoin出来ないデータも全て学習したというのが2ndになった要因と考えられているようです。
Targetや予測分布を確認することや、前回コンペや類似テーマは追うべきということを教わりました。

3rd Solution

3rd place Solution

SwinTransformerとVision TransformerとCaitを使用しながら、SVRをHeadに学習をしたようです。
またStackingとして単純な線形モデルを使用して各モデルの予測値の重みを計算されたようです。
1stと同様、とてもシンプルな解法なのですが全結合層の前のEmbeddingからSVRに入れて学習するのがよかったのだろうと思います。

4th Solution

4th place solution

2nd Solutionと同様に前回コンペと重複している画像は前回のメタデータをjoinした後処理を実施されているようです。
ConvNextを使用しつつConvNextがかなり高いスコアを出しているのも特徴かと思います。
猫専用モデルや犬専用モデルなども作られていたようで、手数の多さやアイデア量もまだまだ足りないなと自覚しました。

6th Solution

6th Place - Multitask Learning

画像の前処理としてアスペクト比が崩れないように正方形にCropされていたようです。
CNNの学習ではHead層を学習するためにBackboneの重みは固定するという方法を紹介してくれています。
Codeのリンクも付いているので勉強します。
また画像サイズに合わせて、Augmentationを変えているのも非常に興味深い点です。
メタデータとしてCatDogラベルを追加しています。
Hill Climbingのところにとても重要なことが書かれています。この辺りはさすがChrisです。脱帽です。
Singleモデルで優れたCVを持っていなくてもこれまでのモデルとアンサンブルしてCVとLBが改善されればOKというのは 頭でわかっていてもなかなか実践することが難しかったです。
どうしてもSingleモデルでのベストを追い求めてしまうのですが、このHill Climbingのやり方で今後試していこうと思います。

9th Solution

9th place solution

DLDLモデルを使用していることが最も大きな違いですので紹介します。
ラベルの順序に意味があるようなケース(年齢など)では有効だと考えられますので、論文とソースをみたいと思います。

18th Solution

18th solution. Single swin transformer, with code.

CPMPさんによる解法紹介です。
ordinal regressionを用いたSwinTransformerのSingleモデルでこのスコアを達成されたようです。
今回のタスクにとてもfitする方法だと思いますし、さすがの引き出しの多さだと思います。

所感

今回のPetFinderコンペはCVもLBもあまり良くならない期間が非常に長く苦しいコンペでした。
結果も奮わず情けないですが、上位解法を基にまた勉強し直そうと思います。
今回の反省点はこちらです。

  • 前回コンペや類似テーマはちゃんと追う
  • 全結合からのEmbeddingを使う
    • 毎回うまくいくわけではないと思いますが、Do Everythingの精神で試すべき
  • Singleモデルの向上にとらわれず、Ensembleで上がれば良しとする
  • テーマに沿ったLoss関数を考える

とても悔しいので次のコンペで挽回します。
最後まで読んでいただきありがとうございました。