kaggle: Porto Seguro's Safe Driver Prediction まとめ

f:id:copypaste_ds:20190201215419p:plain

はじめに

過去コンペまとめ記事の二作目です。タイトルにもあるように今回は2017年9月にkaggleで開催されたPorto Seguro's Safe Driver Predictionをまとめたいと思います。前回はToxic Comment Classification ChallengeというNLPコンペについてまとめたので興味のある方はこちらの記事をご覧ください。他者のアイディアや解法を読んでいるだけで面白いですし勉強になるので、思い返すとここ一週間は過去コンペばかり漁っていたような気がします。飽き性ではありますが今のところは週一本ペースでまとめ記事を書くことを目標にしているのでどうぞよろしくおねがいします。

コンペ概要

Porto Seguro(ブラジル最大の自動車保険および住宅保険会社の一つ)が開催する保険金請求予測コンペです。データは非常にきれいなテーブルデータで、ドメイン知識を含めて特別な知識は必要ありません。
自動車保険加入者が翌年に保険金請求するか否かを予測することは、保険料や保険金を設定する上で非常に重要です。このコンペではドライバーが来年自動車保険に保険金請求をするか否かを予測することを目的としています。
賞金・期間・参加者数などは以下の通りで、参加チームは5169チームと非常に多く人気のコンペであったことがわかります。(実は参加者が多いコンペを狙ってまとめ記事を書いています)

賞金 期間 参加チーム数 参加者数
$12,000 2017/09/30 ~ 2017/11/30 5,169 5,864

データの種類とタスク

テーブルデータを用いた2クラス分類問題です。連続変数・カテゴリ変数・バイナリ変数で構成されており目的変数も2値なので、よくあるデータ形式だと思います。データサイズが小さい、タスクは2クラス分類と一般的、データがきれいなどの理由から初学者にも取り組みやすいことが人気につながったのかもしれません。 正例データのサンプル数が少ない不均衡データで、目的変数の分布は下図のとおりです。画像は後ほど紹介しますが、ここから拝借しました。

f:id:copypaste_ds:20190202214844p:plain

不均衡データの扱いは少し厄介ですが、これも良くあるケースだと思います。
データサイズは以下の通りで、テーブル数は2つでサイズも小さめです。

ファイル名 データサイズ レコード数 カラム数
train.csv 100M 595,212 59
test.csv 164M 892,816 58

ちなみにtrain.csvのheadはこんな感じです。(カラム数が多いので適当に選びました)
連続変数とカテゴリ変数の両方があり、カラム名から変数の意味はわかりません。

f:id:copypaste_ds:20190204105818p:plain

カラムは大きく4つに別れており、それぞれ ind(18種)、reg(3種)、car(16種)、calc(20種)の計57種類です。各カラムの意味は公開されていないため、データの意味や傾向は集計やモデリングを通じて理解していく必要がります。(一応、型の情報としてbinはバイナリ変数、catはカテゴリ変数であることは周知されていました)

評価方法

評価指標は標準化ジニ係数(Normalized Gini Coefficient)です。 標準化ジニ係数は0〜1の値を取る評価指標で1に近いほど良いです。 この指標の直感的理解にはこちらのkernelが役立ちます。一応、コンペ概要ページにも簡単な説明があります。

提出方法

提出のフォーマットは以下のとおりです。idごとに保険金請求する確率を以下のように出力します。

id target
0 0.1
1 0.9
2 1.0

勉強になる Kernel と Discussion

上位解法ほどのスコアは出せませんが、kernelとdiscussionは良いアイディアと実装で溢れています。どのアプローチも勉強になったので簡単にまとめておきます。
最後に紹介しているtkmさんのyoutube動画は、これからkaggleを始めたい方にとてもおすすめです。

Data Preparation & Exploration | Kaggle

データの確認、特徴量抽出、特徴量選択、特徴量のスケーリングまでが簡単にまとめられています。以降の解法を読むにあたって簡単にデータを確認しておきたい方には見ておくことをおすすめします。特徴抽出ではカテゴリ変数をダミー化することに加えて、sklearnのPolynomialFeaturesで変数間の相互作用を表現しています。また特徴量選択ではsklearnのVarianceThresholdやSelectFromModelを用いた方法が紹介されており、とても参考になります。

Stratified KFold+XGBoost+EDA Tutorial(0.281) | Kaggle

xgboostによるモデリングが紹介されています。特徴量抽出やモデリング自体に特に工夫は見られませんが、モデリングする上で必要最小限のコードでテーブルデータコンペ初学者におすすめです。

Resampling strategies for imbalanced datasets | Kaggle

不均衡データの対処法であるunder samplingとover samplingについてまとめられています。pandasの基本メソッドで実装できるものから、不均衡データ処理用のライブラリであるimbalanced learnを用いた手法まで図を用いて直感的に説明されています。特にimbalaned learnを用いたunder sampling(Tomek linksとCluster Centroids)やover sampling(SMOTE)の説明はあまり目にしないため非常に参考になりました。kernelの最後にはおすすめの文献も紹介されており個人的にお気に入りのkernelです。

Python target encoding for categorical features | Kaggle

target encodingの実装と評価が紹介されています。target encodingの実装は単純に目的変数の平均値を求めるのではなく、smoothingやnoise機能が考慮されていて非常に勉強になりました。kernelの評価実験をみると今回はtarget encodingが有効であることがわかります。

Dimensionality reduction (PCA, tSNE) | Kaggle

PCAとtSNEを用いた次元圧縮と可視化が紹介されています。手法の説明はありませんが図が多く考察部分の説明が丁寧なので、初学者でも十分理解できると思います。前処理の有無による結果の違いも紹介されていて参考になりました。今回のデータセットは正例・負例の分離が難しいことを結果から確認できます。それからtoy dataに対するtSNEの挙動についてはこちらのdiscussionで紹介されています。

Tune and compare XGB, LightGBM, RF with Hyperopt | Kaggle

hyperoptを用いたrandam forest, xgboost, lightgbmのパラメータチューニングが紹介されています。最適化手法の説明は無く、探索するパラメータも少ない(実用するには探索項目が少ない)ためこれだけ真似しても使いこなせるかどうか怪しいところですが、サンプルスクリプトがまとめられている点で有用だと思います。(RF, xgboost, lightgbmでデータの渡し方が微妙に異なるので)最近では同じくハイパーパラメータチューニングに使用するoptunaというライブラリが公開されているので、興味がある方は本記事の後半で紹介する日本語の記事を御覧ください。

2-level Stacker | Kaggle

シルバーメダル相当のstackingモデルのスクリプトです。このkernelはコンペ終了後に公開されたそうでスコアも良い非常に強力なkernelです。カテゴリ変数をダミー化した後、lightgbm×3, LogisticRegression×2, ExtraTreesClassifier×2, MLPClassifier×1のアンサンブルをしており、その実装は Ensembleクラスにまとめられています。Ensembleクラスはbase_models, stacker_1, stacker2の3層(数え方が分かりませんがここでは3層ということで)のstackingが実装されており、stacker_1の学習はmode引数で2種類の方法を選択できます。stackingのアイディアを知っている方なら実装もすぐに読めると思うので気になる方は是非読んでみてください。個人的に最も勉強になったkernelです。

Entity Embedding Neural Net | Kaggle

kerasを使ったentity embeddingの実装です。カテゴリ変数ごとembedding layerでカテゴリをベクトル表現したものと量的変数にDenseを通したものを全てconcateして、後段のDenseとdropoutにつなげています。本コンペの2nd solutionと似た解法です。ちなみに、Rossmannコンペの3rd place solutionで紹介されており論文も公開されています。

Gini Coefficient - An Intuitive Explanation | Kaggle

今回コンペの評価指標である標準化ジニ係数ジニ係数を簡単な数値例を交えて紹介しています。

Big GP | Kaggle

Genetic Programmingで作成した特徴量を使用したkernelです。はじめてGPの特徴量を見たときは「これが黒魔術か...!!」と驚いた記憶があります。kernelには特徴量作成ロジックについての言及はありませんが、upuraさんが以前ブログに書いていたので実装に興味のある方はこちらを参考にすると良さそうです。

Kaggle Tutorial on this competition

tkmさんのkaggle 入門動画が共有されています。動画ではPorto Seguroコンペの概要、分析環境構築(GCP登録、Ubuntu設定、データ読込)、モデリング(ロジスティック回帰、Cross Validation、Grid Search、xgboost)、submit方法などがわかりやすくデモ形式で紹介されています。私はこの動画のおかげでkaggleに入門することができたのでとても感謝しています。
この他にも、BigQueryでkaggle入門動画がyoutubeに上がっています。こちらはPorto Seguroコンペと直接関係はないのですが、私がBigQueryを使うきっかけとなった動画で「BigQuery気になってるけど、まだ使ったことない」という方にとてもオススメです。
個人的にとてもお世話になった動画たちなので目立つリンクを貼っておきます。

www.youtube.com

www.youtube.com

上位解法概要

上位解法はLightGBMとNNのアンサンブル解法が目立ちます。テーブルコンペの定石であるLightGBMにモデルの多様性を意識したNNモデルを用意できるかが一つポイントだったのかもしれません。NNのモデリングに関しては1st ~ 3rdで全く解法が異なっているため読んでいて楽しかったです。今回も1st ~ 3rdまでの解法をまとめたいと思います。

f:id:copypaste_ds:20190203154110p:plain

1st place solution: 1st place with representation learning | Kaggle

使用したモデルはLightGBM×1, NN×5(これとは別に特徴量抽出用にNN×5)で各モデルのパラメータ設定は表のとおりです。全てのモデルで準備する特徴量は同じ(表のf0)で、予測モデルがNNの場合は前段にDAE(Denosing autoencoder)による特徴量抽出をしています。予測時には6つのモデルの平均値を求めたそうです。

f:id:copypaste_ds:20190203205513p:plain

DAEで表現学習をする前に、最低限の加工としてcalc系のカラムを全て除外し、カテゴリ変数をダミー化しています。(特徴量抽出が好きじゃないので特徴量抽出は基本的にNNに任せたらしい) DAEのノイズはswap noiseで一定の確率で別レコードの値で入れ替えることでノイズとしたそうです。(画像データのようにflip, rotateなどはできず、gaussian, uniform noiseも不適切と考えたため) またスケーリングはRankGaussを使用したそうです。RankGaussの説明はこのサイトが参考になります。DAEの学習にはtrainとtestの両方を使用しており、testが多かったことは好都合だったとのこと。ただしprivate LB scoreにはあまり効果がなかったようです。

2nd place solution: 三个臭皮匠's approach(s) | Kaggle

public5位からshake upにより2位入賞。localCVとpublicのスコアが一致していたため shake up は予想外だったとのこと。trust CVで、localCVの結果が改善された時だけsubmitしていたそうです。 コメント欄を含めると他のチームメンバーの解法も共有されていますが、ここではチームリーダーのLittle Boatさん解法をまとめます。LightGBMとNNのモデルを作成したようです。(どちらもkernelでスクリプトが吸収されているので詳細を知りたい方はそちらも是非)

LightGBM: 2nd Place Lightgbm Solution | Kaggle

以下の特徴量を追加して予測を行ったようです。

  • 各レコードの欠損数
  • カテゴリ変数をOne Hot encoding
  • ind系特徴量を全て連結しカテゴリ変数とする
  • カテゴリ変数のカウント情報

NN: 2nd place solution NN model | Kaggle

以下の特徴量を追加して予測を行ったようです。

  • 各レコードの欠損数
  • 変数の相互作用項(効果的だったもののみ)
  • ind、reg, car系特徴量を全て文字列で連結しカテゴリ変数とする
  • 特徴量を3グループに分割しxgboostで2グループを説明変数、1グループを目的変数として学習した後、予測値を特徴量として追加
  • カテゴリ変数のカウント情報追加
  • 2つの特徴量を用いて一方をグループのキーに、一方を集計対象とみなして基本統計量(mean, std, max, min, median)を算出(有効だった組合せのみ)

モデルの構造は、各カテゴリを6次元にembeddingしたものと量的変数をconcateした後に、Dense(512) -> PReLU -> BN -> Dropout(0.75) -> Dense(64) -> PReLU -> BN -> Dropout(0.5) -> Dense(1) するというもの。スケーリングには StandardScalerを使用していました。

3nd place solution: 3rd place solution | Kaggle

public1074位からshake upで3位入賞した解法です。shake upを狙っていたそうですが本人もさすがに驚いたようです。
モデルはlightgbm×1とNN×1のアンサンブルと非常にシンプルで、正直モデルの強みや特徴がどこにあるのかよくわかりませんでした。モデリングの特徴を箇条書きでまとめます。

  1. calc系のカラムを除外し、LightGBMのCV scoreを確認しながら他にも9つのカラムを除外する
  2. カテゴリ変数をOne Hot Encoding
  3. LightGBMのパイパーパラメータは表現力を抑える(lambda_l1=10, num_leaves=24など)
  4. NNは3層で Dense(4096) _> Dropout(0.5) -> Dense(1024) -> Dropout(0.5) -> Dense(256) で、ネットワーク構造はあまり重要ではなかったとのこと

その他の上位解法

discussionは解法の宝庫ですね。余力がある方はこちらもぜひ。

順位 リンク
8th Approach(3rd in public and 8th in private) | Kaggle
8th Taylor-made NN for 0.285 PLB (part of solution of 8º) | Kaggle
9th 9th place solution | Kaggle
12th 12th place solution | Kaggle
17th 17th solution - seed selection, NN, ensembling.. | Kaggle
18th 18th Place Solution - Careful Ensembling + Resampling Diversity | Kaggle
20th genetic algorithm solution (20th place) - very long read | Kaggle
21th Keep It Simple (21st solution & *mea culpa* for missing gold) | Kaggle
23th 23rd place solution | Kaggle
25th Safe Driver Prediction top 1%, LightGBM (0.29132) | Kaggle
29th Solution 1178 Public / 29 Private | Kaggle
31st 31th/5k+ with 1 single model without stacking and blending possible, wow! | Kaggle
35th 35th place solution | Kaggle
37th 39th solution | Kaggle
39th 39th solution utilizing Pr(is_test|X) by adversarial validation | Kaggle

日本語記事

Kaggleで世界11位になったデータ解析手法〜Sansan高際睦起の模範コードに学ぶ - エンジニアHub|若手Webエンジニアのキャリアを考える!

株式会社Sansanのデータサイエンティストが、Port Seguroコンペを題材に前処理・特徴量抽出・予測モデルについて紹介しています。コードや考え方を初心者でわかるようにQ&A形式で説明されていてわかりやすいです。

世界一のデータサイエンティストを目指して 〜Kaggle参加レポート〜 - Kysmo’s Tech Blog

株式会社キスモの役員の方がPort Seguroコンペの参加記録を書いています。こちらもQ&A形式で説明されていて非常にわかりやすいです。

OptunaとLightGBMを使って、Kaggle過去コンペにsubmitする | Enigmo Life

Port Seguroコンペのデータを使ってOptunaでLightGBMのパラメータチューニングをしている記事です。

おわりに

今回はPort Seguroコンペについてまとめました。テーブルコンペでもNNが積極的に使用されていることは驚きでした。一方でNNのモデリングは1st ~ 3rdで全く異なることから察するに、NNの定石はまだできていないのかもしれません。他のコンペの解法も眺めながら傾向を掴んでいきたいです。次回はメルカリコンペかAvitoあたりをまとめるつもりですのでそちらも読んでいただけると励みになります。