㊙️

Kaggleコンペで楽に銅メダルを取る方法

2025/01/06に公開

Lunranと申します。
先日、Kaggle Competition Expertになりました。

自分のKaggleコンペ参加履歴を振り返ったところ、あまり時間をかけなかったコンペでメダルを獲得していたため、楽に銅メダルを取る方法としてまとめ、直近のコンペでの実施内容と結果を述べます。

実施内容についてはデータサイエンス・機械学習への深い理解や発想力が不要なため、コンペに参加したいが何をすればわからない、という場合に有効かと思います。

以下を前提とさせていただきます。

  • CV(Cross Validation)や過学習(Overfitting)などの言葉を知っている
  • ShakeやPublic/Private LB(Leaderboard)などのKaggle用語を知っている
  • Kaggleの公開ノートブックを読んで、何をしているのかわかる

概要

本記事で述べる方法は「Shakeが起きるコンペを見分けて、公開ノートブックの汎化性能を上げる」というものです。

「Shakeが起きるコンペ」にも色々あるようですが、特に以下の条件を満たすものを対象にします。

  • Public LB上位にsubmit数回の参加者がいる
  • Publicスコアの高いノートブックが公開されていて、Publicスコアに過剰適合している
  • LB上位にMaster以上が少ない

「Publicスコアへの過剰適合」は、いわゆる過学習の他に、Random Seedの探索や「教科書的なセオリーに反するが、なぜかPublicスコアが高くなる設定や処理」を指します。

本手法では、Public LBはあまり気にせず、Private LBでのShakeupを狙います。

その他、本手法の特徴は以下の通りです。

  • PublicスコアよりCVを参考にする
  • 労力は2週間(2時間/日)くらい
  • 銀メダル以上は、おそらく無理

実際に行った内容と結果

Child Mind Institute — Problematic Internet Useにて、実際に行った内容を述べます。

https://www.kaggle.com/competitions/child-mind-institute-problematic-internet-use

結果は銅メダルでした。

Shakeが起きるコンペを見分ける

データセットが表形式でサイズが小さく、計算資源的な参加ハードルが低かったためか、終了1ヶ月前の段階で、参加者が2000人以上いる状態でした。

Public LBを見ると、1位のスコアが0.495であった一方で、200位前後にsubmit数回でスコアが0.492の人が多くいる状態でした。

そしてCodeを見ると、スコアが0.492の公開ノートブックがありました。
https://www.kaggle.com/code/hideyukizushi/cmi-reproducible-results-fixseed-lgb-cpu-lb-492
説明が豊富で理解しやすく、また実行時のランダム性が除かれており、こちらも参加ハードルを下げてくれていました。

このようなコンペでは、参加者がさらに増えることが予想されます(最終的に3500人を超えました)。参加者が1000人以上の場合、銅メダルの条件がTop 10%になるため、参加者は多いほどメダルを獲得しやすくなります。

公開ノートブックは大変ありがたいものなのですが、Publicスコアが高い方がVoteを得やすいためか、Publicスコアへの過剰適合が見られることがあります。
そのため、公開ノートブックをベースとしてPublicスコアをさらに上げようとすると、結果的にPrivate LBで順位が下がる可能性があります。

Volatilityの確認

公開ノートブックのseedを変えて数回submitしたところ、Publicスコアは0.001~0.03下がりました。

スコアが0.03下がると順位は500位ほど下がることになるため、この公開ノートブック、ひいてはこのコンペでは運の要素が大きいことが予想されました。

公開ノートブックの汎化性能を上げる

データの前処理

Discussionで公開されていたEDAに「収縮期血圧(最高血圧)が拡張期血圧(最低血圧)より低い場合がある」とあったため、その場合に値を入れ替える処理を追加しました。

https://www.kaggle.com/code/antoninadolgorukova/cmi-piu-features-eda

また、LightGBMのfeature importanceの上位に「有酸素運動テストの継続時間(秒)」が現れていました。
このカラムは、例えばテスト結果が「10分20秒」の場合、秒数の「20」だけを保持していました。
そのため、別のカラム「有酸素運動テストの継続時間(分)」だけを利用し、このカラムを使用しないよう修正しました。

これらの修正によるスコアへの影響は、以下の通りです。

CV:+0.003、Public LB: +0.017、Private LB: -0.004

Privateスコアに対しては、残念ながらマイナスの影響になりました。

欠損値への対応

学習データに欠損値が多かったため、公開ノートブックでは n_neighbors=10 でKNN imputeを行っていました。
これに対し、n_neighbors=10~50 の異なる値でKNN imputeした学習データを用いて複数のモデルを作成し、結果をアンサンブルするように変更しました。

また、KNN imputeを行うタイミングがfold分割前になっており、これはリークになると考えたためfold分割後に変更しました。

これらの修正によるスコアへの影響は、以下の通りです。

CV: +0.007、Public Score: -0.012、Private Score: +0.027

Publicスコアに対してはマイナスでしたが、Privateスコアに対してはプラスでした。

不均衡データへの対応

学習データでは、正解ラベルSIIに対してサンプルサイズが偏っており、SIIが大きいサンプルが少ない状態でした。
Privateスコア算出に使われる評価データの分布は不明でしたが、より均衡の取れたデータになる方に賭けることにしました。

モデル側の対応

LightGBMとXGBoostのパラメータで不均衡データに対応するオプションがあったため、これを設定しました。('class_weight': 'balanced')

この修正によるスコアへの影響は、以下の通りです。

CV: +0.007、Public Score: -0.016、Private Scoreで+0.013

Publicスコアに対してはマイナスでしたが、Privateスコアに対してはプラスでした。

データ側の対応

imbalanced-learnというライブラリでunder samplingできることがわかったため、Tomek's Links除去と前述のKNN imputeを組み合わせて複数の学習データを作成し、結果をアンサンブルしました。

この修正によるスコアへの影響は、以下の通りです。

CV: -0.011、Public Score: -0.017、Private Score: -0.012

CVが下がったため、この変更は最終回答に含めませんでした。

最後に

この方法では銀メダルを獲得できたとしても運が良かっただけで、金メダルの獲得はおそらく無理です。

データサイエンス・機械学習への理解を深め、Shakeが起こらないコンペで安定して上位に入れるよう、精進したいと思います。

Discussion