ほろ酔い開発日誌

有意義な技術的Tipsを共有出来たら嬉しいです。Ruby、Railsが好きです。Web開発全般(Rails多め、フロント、サーバー、インフラ)、データ分析、機械学習あたりの記事が中心になる予定です。

Kaggle 「Allstate Claims Severity」を終えての振り返りと整理

約1ヶ月程の期間ちょこちょこ時間を使って、データ分析・データモデリングのコンペのプラットフォームであるKaggleで Allstate Claims Severityというコンペに挑戦しました。

www.kaggle.com

このようなコンペははじめてで学びだらけでした。今回の復習をして今後に活かしていきたいと思うところです。

目次

  1. コンペ期間に行ったこと
  2. 他の方の手法をきいて
  3. 次回以降のアプローチ
  4. おわりに

1. コンペ期間に行ったこと

はじめに順位は、676位 / 3055位 (Public LeaderBoard: 上位22.1%程度) でした。はじめてなのでそんなものですね。(ニューラルネット使えばもっと点数上がったのに時間的にやめておいたのが悔やまれる。。PCスペック低かったし仕方ないと言い訳しときます笑)

データセット

このコンペでは保険会社のデータが使われていて、データとしてはtrain dataが20万弱、test dataが10万強のサンプル数で、カラムはカテゴリカラムが116、数値カラムが14で目的変数であるlossが1つあるといった感じのデータセットです。 手頃な感じでやりやすいもののようです。(普通はもっとデータ量が多くてラップトップPCではきついものが多いようです。。)

Forum

コンペを進めていく上で重要だったのは Forumという意見交換の場を利用していくことでした。初心者からするとものすごい貴重な情報がたくさん載っています。戦略を立てる上でForumに載っている手法を真似して試していきました。

さて、Forumを眺めて点数が取れている手法はXgboostというGradient Boostingのライブラリを用いた手法とNeural Networkの手法(Kerasを用いたもの)でした。 そこで、ひとまずXgboostingの手法を試してみることにしました。

XGBoost のスクリプト

最初に試したのは以下のスクリプトでした。

https://www.kaggle.com/iglovikov/allstate-claims-severity/xgb-1114/code

こちらはxgboostのスクリプトでこれだけである程度の点数がとれます。 xgboost自体も使うのがはじめてだったので参考になりました。

ポイントとしては

  • カテゴリ変数がファクトライズされている(A->0、B->1、、のように数値化)
  • 目的変数を調整している (logを使ってるところ)
  • パラメータが調整されている
  • 評価関数をMAEに変更している(今回の評価関数がMAE)

といったところだと思います。すっきりしたスクリプトでしたが参考になるところは多かったです。これが今回のベースになりました。

パラメータの調整

次にパラメータを調整しようと思いました。

  • グリッドサーチ
  • ランダムサーチ
  • 手動で狙いうち

sklearn とかにも用意されていたり、hyperoptなるものも人気らしいです。 しかし、今回は使わなかったです。なぜかというと時間がかかりすぎると思ったからです。先程のサンプルのコードを1回まわすのに100分強の時間がかかっていたので例えばグリッドサーチなどをやるにしてもある程度どれくらいの値がいいかの感覚もないのできついです。(まだ新しいPC届く前でスペックが低く、実行中は他の作業も出来ない) ただ少しはやってみようと数個値を変えてやってみたところ、max_depthというパラメータをちょっと大きくすると精度があがりました。他は逆に下がるばかりでだめだめでした。 max_depthは木を深くすれば精度が上がるのはまあ当たり前だなーって感じで、むしろ実行時間が長くなってしまって今思うと微妙でした。このあたり、精度と時間のトレードオフも学びです。また、あとから聞いたのですが、このスクリプトはパラメータはある程度調整は出来ていてこれ以上のパラメータ調整はそんなに意味をなさなかったらしいです。

データの処理・加工

順番が前後したのですが、ここでデータがどうなってるかを考えました。(本来なら一番最初にやらなきゃいけないですが) まず、今回のデータセットは欠損値がないというミラクルが起きていたようです。欠損値があれば、そのサンプルは消すが他のサンプルの平均で穴埋めするかとかしないといけなかったです。

あと、カテゴリ変数はファクトライズ(A->0, B->1、、)してあったのですが、XGBoostの場合はこれで問題ないようです。モデルによってはonehot-encodingとかしないといけないのでちょっと困惑ポイントでした。直感的には木で分岐していくのでonehot-encodingじゃなくてもよいようです。

データ分析については以下の投稿が参考になりました。

https://www.kaggle.com/achalshah/allstate-claims-severity/allstate-feature-analysis-python

次元削除・特徴量作成

これ以上同一モデルで点数を上げるには特徴量をいじるしかないということで取り組むことにしました。

PCA

まず、やったのはPCA (主成分分析)という次元削除の手法を試してみました。PCAはざっくりいうと出来るだけ情報量を失わないように特徴量を減らす手法です。

今回は数値のデータが14つあるので、14->7に次元を削除してみました。それで予測を行うと点数が下がってしまいました。ただ、これは当たり前でそもそも情報量を落としているので基本的には点数は下がります。特徴を適当にいじれば点数上がるような感じでやってみてもダメですね。次元削除と特徴量を作ることは別ですね。次元を下げると計算量が少なくなるので今後効果的に使えるといいなと思います。

相関

それで次にloss(目的変数)と相関の高い特徴量を生み出すことに挑戦しました。今回のコンペのデータはカラムの名前に意味がなく全く手がかりがないので相関で考えることにしました。数値データのうちランダムに組み合わせて(足し合わせたり、logをとったり)相関が既存のカラムより高くなったものを新たな特徴量として追加しました。(大体20個くらい新しい特徴量が出来ました) しかし、逆に点数が下がってしまい失敗でした。

カテゴリデータの組み合わせ

Forumで上がっているもので点数が上がっている特徴量作成のやり方として、カテゴリデータを使ったものがありました。 任意の2つのカテゴリデータから1つの新たな特徴量を作成します。 例えば一方がAでもう片方がBならABというカラムが出来上がります。 その後に、数字にするのですがA、B、...、Z、AA、AB、...、AZ、BB、のような順に数をつけます。例えば、A->0、B->1、AA->27のような数です。

カテゴリデータは116個あるので全部使うと数が多すぎるので35個の特徴量を使いました。Forumに載ってるものをそのまま使いましたが、おそらくXGBoostのfeature importanceの上位35個を使ったものと思われます。feature importanceは分岐の使われた回数を示すらしいです。xgboostのライブラリ中のメソッドから簡単に順位を出すことが出来ます。

これは点数アップにつながりました。

アンサンブル

違うモデルを組み合わせると点数が上がるということでやってみようと思いました。本当はNearal Networkを使いたいところだったのですがまわす時間がなくて諦め、他のモデルも試さずにコンペが終わりそうだったので、とりあえず、XGBoostのいくつか試したものを加重平均してみました。これだけでも点数が上がったのでアンサンブルすごいなーと思いました。

2. 他の方の手法をきいて

コンペが終わってから、同じコンペに挑戦していた研究室の先輩のお話を聞いてとても参考になったのでまとめます。(今回のコンペの上位4%以内の方)

XGBoostのチューニング

今回はForumのスクリプトがパラメータのチューニングを行っていたのでもともといい感じにチューニングしてありました。実際のところはどのようにやればいいのかききました。

大体の感覚として以下のような感じらしいです。

eta: 0.3~0.01 (0.3はチューニング用で、0.01でトレーニングをやる)
Max depth: 6~12
Subsample: 0.5~1.0
Colsample: 0.25~0.7,0.8
Round: 100000 (Early stopping を利用)

randomサーチかマニュアルでパラメータを探すようです。Kaggleの上位者程、勘でパラメータを調整するらしいです。 今回調整したのは上記のパラメータの範囲で適当に試して決めたとのことです。 学習率はパラメータ調整のときは高めに設定して学習して100epochくらいまわして比較したみたいです。 僕はパラメータ調整のときも時間をかけてしまっていたので参考になりました。

ちなみに、Nearal NetworkのほうはForumに出てるスクリプトのunit数、epoch数を増やしたものを使ったとのこと。

目的変数変換や目的関数の重要性

今回の目的変数のlossは歪度が正で、右に裾が広がる形をしていました。これにlogを取ると正規分布に近いかたちになります。このあたりの調整はForumでは先人がやってくれていたので、今回は大丈夫でKaggleでは基本的に誰かが見つけてくれるようなのですが、もしこれに気づかないと勝負にならないので注意が必要だということです。また、今回の評価関数のMAEは2回微分までを用意出来ない形なので近似した関数を目的関数におきました。これも適切に設定することが大事のようです。テーラー展開とかを使って近似させることもあるようです。

このあたりは、Kaggleでは誰かが先にやってしまうので単純にこれによって点数差がつくことはほとんどないらしいのですが、上位を狙うためにはForumで共有される前段階で気づいて他の施策を行わないと時間的に勝てないみたいです。

特徴量作成 (XGBoost)

特徴量の作成方法としては、上記のカテゴリの組み合わせと同様のことをやっていたみたいです。

feature importanceの上位50個くらいをとってやったみたいです。さらに2つの組み合わせだけではなく、3つ、4つまで行ったとのことです。

それでどのカテゴリを組み合わせればよいかは以下のxgbfiというものを利用するとよいみたいです。

github.com

また、数値カラムも適当な組み合わせで+-×÷の四則演算を試したようですが点数には寄与しなかったみたいです。

カテゴリと数値のカラムも両方をカテゴリデータとして扱うか、療法を数値データとして扱うことで特徴量を作ることも出来るとのことでした。

アンサンブル

今回は加重平均を使ってXGBoostとNeural Networkをアンサンブルさせたとのことですが、もっと点数をあげるにはスタッキングというやり方を行うとよかったとのことです。

加重平均したモデルとしては、Neural Network 1つとXGBoost3つでした。その3つは違う特徴量によって作られたものです。

スタッキングは複数の分類器でtrainデータを用いて予測を出し、その結果をまとめて新たな特徴量にし、それを新たなモデルにかける手法です。

ちょっと面倒ですが精度は出るみたいです。

他の分類器

色々な分類器を試した(もしくは試したかった)ようです。例えば、

  • SVR
  • KNN
  • Xtra Trees
  • Random Forest
  • Liner Regression
  • Regularized Regression
  • Light GBM
  • Vowpal Wabbit

その他諸々、聞きたいことをことごとく聞けたので良かったです笑 今回のわからない部分を聞けたの一般論的な部分もちょっとわかった気がします。 それと上位に食い込むにはどうすれば良いかのイメージが出来ました。

3. 次回以降のアプローチ

ここはすごくざっくり。

まず、データを分析する。特に

  • データの基本情報を見る。(データ数、特徴量、相関、分布、など)
  • 欠損値がないか

とか。

XGBoostとNeural Networkのアンサンブルをやってみる。この2つである程度の精度は基本的に出るらしい。 目的変数、目的関数、評価関数はちゃんと考える。 epoch数少なめにパラメータ調整。

特徴量を考える。feature importanceとかxgbfiとか。特徴量の意味がわかる場合はそこから考える。

過去に終わったコンペですが、下記のコンペを復習も兼ねてやります。

www.kaggle.com

ちなみに、今回僕がやったコンペも期間は終わりましたが、サブミットして点数も返ってくるので挑戦出来ます。

Neural Networkのスクリプトは3日かかったよ、とも聞いたので根気強く待つのも大切ですね。(今回僕は1日まわしても終わらなくて諦めました)

あと、Forumに上位者がどういうことをやったかを共有してくれているので見ようと思います。

#1st Place Solution - Allstate Claims Severity | Kaggle

#2nd Place Solution - Allstate Claims Severity | Kaggle

Faron's 3rd Place Solution - Allstate Claims Severity | Kaggle

GIBA - #7 Place Solution - Allstate Claims Severity | Kaggle

#8 solution - Allstate Claims Severity | Kaggle

12th place solution - Allstate Claims Severity | Kaggle

#16 place solution and some questions about it. - Allstate Claims Severity | Kaggle

コンペが終わっても学びが多いです。

4. 終わりに

細かいことの説明はしていませんが、大まかにやったことをログとして書きました。学びが多かったので次に活かしたいです。 Forumなどを読んで理解を深めたいと思います。

また、学習したことは共有したいと思っています。