Kaggleコンペで楽に銅メダルを取る方法
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にて、実際に行った内容を述べます。
結果は銅メダルでした。
Shakeが起きるコンペを見分ける
データセットが表形式でサイズが小さく、計算資源的な参加ハードルが低かったためか、終了1ヶ月前の段階で、参加者が2000人以上いる状態でした。
Public LBを見ると、1位のスコアが0.495であった一方で、200位前後にsubmit数回でスコアが0.492の人が多くいる状態でした。
そしてCodeを見ると、スコアが0.492の公開ノートブックがありました。
説明が豊富で理解しやすく、また実行時のランダム性が除かれており、こちらも参加ハードルを下げてくれていました。このようなコンペでは、参加者がさらに増えることが予想されます(最終的に3500人を超えました)。参加者が1000人以上の場合、銅メダルの条件がTop 10%になるため、参加者は多いほどメダルを獲得しやすくなります。
公開ノートブックは大変ありがたいものなのですが、Publicスコアが高い方がVoteを得やすいためか、Publicスコアへの過剰適合が見られることがあります。
そのため、公開ノートブックをベースとしてPublicスコアをさらに上げようとすると、結果的にPrivate LBで順位が下がる可能性があります。
Volatilityの確認
公開ノートブックのseedを変えて数回submitしたところ、Publicスコアは0.001~0.03下がりました。
スコアが0.03下がると順位は500位ほど下がることになるため、この公開ノートブック、ひいてはこのコンペでは運の要素が大きいことが予想されました。
公開ノートブックの汎化性能を上げる
データの前処理
Discussionで公開されていた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