1st Place Solution
はじめに
コンペティションを開催いただいた運営のみなさま、この度は誠にありがとうございました。
最終スコアの掲示まで全く気の抜けないコンペでしたが、自分自身非常に学びある経験となりました。
参加された皆さま、最後までありがとうございました。
下記、拙い部分があり非常に恐縮ですが、解法をまとめましたので、ご参照いただけますと幸いです。
コード
https://github.com/bysk2/probspace_kaokore_status_1st_solution
Summary
序盤
コンペ序盤は単体モデルでの精度向上を目指し、実験を重ねていきました。
特にData Augmentationやモデルのアーキテクチャ周りで試行錯誤を繰り返しました。
中盤
このあたりから、アンサンブルを試していきました。
新しく作成したモデルを迎えたときに、CVまたはLBが上がるかどうかによって採用・不採用を判断しました。
この考え方はKaggleコンペ「Pet Finder2」における6th Place Solutionを参考にしました。
(https://www.kaggle.com/competitions/petfinder-pawpularity-score/discussion/301015)
終盤
アンサンブルの他、Optunaによる探索や後処理を検討しました。
終盤はLBがほぼ上がらず、CVを信じて実験を繰り返す方針で進めました。
上位陣のスコアが非常に密だったため、乖離は少ないと考え、最終SubはCVが良いもの、LBが良いものをそれぞれ一つずつ選び、フィニッシュしました。
Pipeline
最終Subは下記のフローで作成しました。
各実験の詳細は別表にてまとめておりますので、ご参照いただけますと幸いです。
大きく5つのステージに分けて、それぞれまとめました。
https://probspace-stg.s3-ap-northeast-1.amazonaws.com/uploads/user/cd0b7d612080897a7fed0ac61a5047fe/images/UserImage_219/9372483c-2ba8-4abf-85d7-cc55572ef190.png
Stage 1
できるだけ精度の高いPseudo Labelingにしようと考え、多様なモデルを作成し、アンサンブルした結果を採用しました。予測した結果全てのハードラベルを利用しました。
Stage 2
コンペ中盤で精度が鈍化してきたときに、各モデルで外しやすいデータを確認したところ、OOFに対して一部の実験すべてで不正解となっているデータが幾つか見られました。
当該データはノイズになると考え、学習データから外すことを検討しました。こちらのデータを学習データとしてexp_080を実行しました。
なお、学習データは与えられた全量6,446件から6,371件となりました。
Stage 3
Stage1,2を利用したモデルを含めた各結果をOptunaを用いて重み最適化を実施しました。
この結果を最終Subの一つ①に選定しました。
Optunaの主要なパラメータは下記のとおりです。
・timeout : 3,600
・object : maximize
・metric : macro-F1
Stage 4
Stage 3で様々なモデルを組合わせて実験を繰り返したのですが、これ以上結果が変わらなかったため、別の方針を検討しました。
これまではマルチクラス分類モデルを作成していましたが、新しくラベルが0か0以外かを予測するモデル(ローランドモデルと呼んでいます。笑)を作成し、ラベル0の予測確率について再度Optunaを実行しました。
最適化された確率を用いて、元の確率との平均を算出し、採用しました。
Stage 5
学習データを全て用いた全学習モデルを作成し、Stage 4の結果と組み合わせました。
全学習モデルはCVがわからないため、1:4の割合で重みを小さくしてアンサンブルしました。
アンサンブル後のラベルとStage 4で作成した2値分類モデルを比較し、2値分類モデルで0と予測した結果で上書きしたものを最終Subの2つ目としました。
ただし、ラベル2(化身)と予測しているケースについては上書きしないようにしました。
ラベル2は人間の目からみても特徴的であることが明らかだったため、マルチクラス分類モデルの方が高精度だろうと考えたためです。
Public Topは0.916の結果でしたが、上記の方針を一貫した結果を最終的なSub②としました。
最終的なSubの結果は下記の通りです。
・最終Sub①: Public LB: 0.911, Pribate LB: 0.904
・最終Sub②: Public LB: 0.915, Pribate LB: 0.907
結果としては、過去に作成した実験の中にPrivate LBが0.910をたたき出している結果があったのですが、Public LBとの乖離が大きかったため、選ぶことが出来ませんでした。
全体的にCVとLBの関係性が不安定だったため、最終Subを選ぶのに苦労しました。
こちらに関しては皆さまも苦労したのではないかと推察します。
モデル詳細
https://probspace-stg.s3-ap-northeast-1.amazonaws.com/uploads/user/cd0b7d612080897a7fed0ac61a5047fe/images/UserImage_220/37d54da1-5eef-4c05-bbee-565f158b40cf.png
Architecture
timmライブラリで公開されているImageNet事前学習済みモデルを採用しました。
別の方針として、DINOによるtrainデータを事前学習し、その重みを使ってFine Tuningしたモデルも作成しました。
head層は1層~3層とし、MultiSampleDropoutやMixoutを試しました。(https://www.ai-shift.co.jp/techblog/2170)
Augmentation
Albumentationより、下記を採用しました。
・Resize
・ShiftScaleRotate
・HorizontalFlip
・Blur
・Rotate
・HuesaturationValue
・Normalize
また、MixupやCutMixも試しました。(https://github.com/ildoonet/cutmix)
学習データの中に、横向きの画像(お辞儀していたり、横たわっている?)が含まれていたため、RotateやShiftScaleRotateを採用していました(パターン①)。
後半に改めてテストデータを眺めてみると、あまり横向きのデータが無いことが分かり、当該処理を除外したモデルの作成も試みました(パターン②)
- CV
基本的にはStratifiedKFoldを採用しました。
始めは5 foldで進めていましたが、CVが安定しなかったため、4 foldに変更して実験を進めました。
終盤は学習データを増やした8 foldのモデルを作成し、アンサンブルに含めました。
別の方針として、ImageNetの重みづけされたEmbeddingを使って各画像の結果をクラスタリングし、クラスタのラベルを用いてStratifiedKFoldを実行したモデルを作成しました。
・学習データ
前半はtrain dataを全て使用して学習を実施していました。
作成した幾つかのモデルすべてで外しているデータが判明したため、それらのデータは当てるのが難しくノイズになる可能性があると判断し、
学習データから外して実験しました。(exp 080)
また、ラベル0(貴族)かそれ以外かを予測する2値分類モデルを作成するために、ラベルをまとめた学習データを作成しました(exp_098)
最後にtrain dataすべてを学習させた一つのモデルを作成しました。(exp_110)
- その他パラメータ
・Batch_size : 2~32で変更
・epoch数:10~30で変更
・schedular : CosineAneelingLR
・学習率lr : 1e-6~1e-5で変更
・画像サイズ: 224~384で変更
試したがうまくいかなかったこと
- Focal loss: ラベル3(庶民)のデータ数が比較的少なかったため採用しましたが、うまく機能しませんでした。
- 勾配蓄積 : バッチサイズが2と少なかったため、勾配蓄積の実装を試みましたがうまく機能しませんでした。CV,LBともに悪化しました。(実装自体に不安もあります。。。)
- Label Smoothing : 中盤CVの向上が99%→100%に限りなく近づけるような学習になっていると考えられたため、実装しましたが、CVは向上したもののLBが下がりました。
- TTA : Horizontal Flipのみを採用して実装しましたが、TTAを実施する前と結果が変わりませんでした。
- LightGBMによるStacking : いずれもStacking前より精度が悪くなる結果となりました。
- 下記モデルのアンサンブル結果 : 単体でのCV, LBはそこそこ良い結果となりましたが、アンサンブルには用いられませんでした。多様性を生めなかった可能性があります。
・ConvNext
・CLIP
- ImageHashによる類似画像検索→ラベル上書き : 類似画像で抽出されたラベルがすべて同じであれば、testのラベルも同じだろうと考え、実行してみましたが、LB向上にはつながりませんでした。
- 2値分類モデル(1か1以外か):0か0以外かはLB向上に寄与しましたが、同様の方針で1か1以外かを実装するとLBが下がったため、採用しませんでした。2,3については正例が少なく低精度になると考え、実装に至りませんでした。物は試しでやっておけばよかったかもしれません。
まとめ
小さく条件を変えて実験を繰り返し、気づけば122回も提出していました。
コンペを通じて様々な手法を試すことができ、非常に勉強になりました。
素晴らしいコンペを開催いただいた運営の皆さま、コンペを最後まで走り切った参加者の皆さまに改めて御礼申し上げます。
ありがとうございました。