データ分析プラットフォームProbspaceの対戦ゲームムデータ分析甲子園(通称:スプラトゥーンコンペ、イカコンペ)のに参加し、9位に入賞しました!
今回もPublicLBでは4位だったのですが、Shake downしてしまい、汎用性をもったモデルの構築の難しさを改めて実感しました。
今回のコンペは、スプラトゥーンというNintendo Switchのゲームの勝敗を、武器やステージなどのデータから推測するというタスクでした。
私はこのゲームをプレイしたことがなく、ドメイン知識が全くなかったので、Python機械学習クックブック [ Chris Albon ]を使って、掲載されている手法をいろいろ勉強するつもりで、取り組みました。
この本では手法の1つ1つを"レシピ"という単位でまとまっていたので、どのレシピをどこで使ったかも、紹介していきたいと思います。
では、振り返ってまいります。
1.全体構成
今回は、前述の通り、ゲーム自体の知識がなかったので、データ自体の分析はそこそこに、とにかく、いろんな手法を使ってみました。
今回初めて使ったモデルもあり非常に勉強になりました。
全体像としては、以下のとおり3つの前処理をした特徴量を使った6種類の予測結果を加重平均したモデルが最もprivateスコアが高かったモデルとなりました。
2.前処理
前処理は、以下の3通りを用意しました。
【前処理①】
こちらは、Probspace のトピックで公開させていただいたベースラインで使用している前処理になります。
欠損値には、全て-1を設定しています。
また、カテゴリ変数は全てターゲットエンコードしています。
【前処理②】
上記、前処理①で作成した特徴量を、feature tools を利用して、水増ししました。
具体的には、それぞれの特徴量を足し算、引き算、掛け算した特徴量を追加しました。
featuretoolsについては、@momijiameさんの以下の記事を参考にさせていただきました。
【前処理③】
こちらは、カテゴリ変数のうち、武器関係の特徴量はOne-Hotベクトルに変換して、それ以外の変数はラベルごとの数値に変換しています。
欠損値については、どちらも欠損値を表す文字列に変換しておいて、1つのカテゴリとして上記の変換を行いました。
武器関係のOne-Hotベクトルに変換については、Python機械学習クックブック [ Chris Albon ]の「レシピ5.1 名義カテゴリ特徴量の数値化」にあった複数クラスのエンコーダーMultiLabelBinarizer()を利用しました。
また、それ以外のカテゴリ変数はの数値に変換については、Pandasのfactorize()を使用しました。factorize()については、@QUANONさんの以下の記事を参考にさせていただきました。」
3.モデル構築
今回は、前述の通りPython機械学習クックブック [ Chris Albon ]のモデルをいろいろと組み合わせて試していきました。
この中で、今回privateスコアが最も高かったのは、以下の6つ入力とモデルの組み合わせからの出力を加重平均したもとなりました。
前処理①の特徴量→GaussianNBを1層目、BernoulliNBを2層目にしたStacking
1つ目は、ガウシアンナイーブベイズクラス分類器(GaussianNB())と、ベルヌーイナイーブベイズクラス分類器(BernoulliNB())をStackingした構成になります。
ナイーブベイス分類機は、ベイズの定理を利用した、単純ベイズ確率モデルとのことです。(理論等についてはこれから勉強します!)
ガウシアンナイーブベイズクラス分類器(GaussianNB())は、分布が正規分布になることを前提として分類する分類機で、Python機械学習クックブック [ Chris Albon ]の「レシピ18.1 連続値特徴量に対するクラス分類器の訓練」にあった、GaussianNB()を利用しました。
ベルヌーイナイーブベイズクラス分類器(BernoulliNB())は、分布がベルヌーイ分布になることを前提として分類する分類機で、Python機械学習クックブック [ Chris Albon ]の「レシピ18.3 2クラス特徴量に対するナイーブベイズクラス分類器の訓練」にあった、BernoulliNB()を利用しました。
前処理②の特徴量→LogisticRegression
2つ目は、ロジスティック回帰(LogisticRegression)を利用した構成となります。
言わずとしれた2値分類のモデルになります。「回帰」と名前がついていますが、分類モデルに使えるモデルです。
Python機械学習クックブック [ Chris Albon ]の「レシピ16.1 2クラス分類器の訓練」にあった、LogisticRegression()を利用しました。
3つ目以降は、定番の勾配ブースティング決定木 (Gradient Boosting Decision Tree) の精度が良かったので採用しています。
前処理③の特徴量→XGboost
3つ目は、勾配ブースティング決定木 (Gradient Boosting Decision Tree) の一つである、XGboostになります。
XGboostについては、@momijiameさんの以下の記事を参考にさせていただきました。
前処理①の特徴量、前処理②の特徴量、前処理③の特徴量:LightGBM
4つ目から6つ目は、前処理①から③をそれぞれLightGBMで学習したモデルになります。
LightGBMについては、@codexa_netさんの以下の記事を参考にさせていただきました。
それぞれの予測結果の加重平均を最終的なサブミットとすることで、Publicスコアが0.567396、Privateスコアが0.564008の精度を得ることができました。
4.まとめ
今回は、ゲームの勝敗予測ということで、ドメイン知識がなく辛いなと考えていたのですが、Python機械学習クックブック [ Chris Albon ]を活用させていただき、いろいろなレシピを活用させていただくことで、なんとか1桁台の順位を獲得することができました。
欲を言えば、今回もまたShakeDownしてしまったので、PublicとPrivateの精度を同等にできる汎用的なモデルを作成できなかったところが反省点です。こちらについては、血行続いているので、対策を勉強していきたいと思います。
5.謝辞
コンペを運営してくださいました、ProbSpaceの運営の皆様、コンペに参加してくださった皆様に心より感謝申し上げます。
また、今回、十二分に活用させていただいたPython機械学習クックブック [ Chris Albon ]の著者のChris Albon様、訳者の中田 秀基様、出版社のオライリー・ジャパンの皆様、ブログ等を参考にさせていただきました、@momijiameさん、@QUANONさん、@codexa_netさんに、この場を借りて厚く御礼申し上げます。
私も、皆さんの用に有用な情報発信ができるよう、これからも精進していきたいと思います。
【過去記事】
これまでの道のりは以下の記事をご参照ください。