kaggle noviceがテーブルコンペの取り組み方をまとめてみた

# この記事について

この記事は[kaggle その2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/kaggle-part2) 21日目の記事です。
kaggle歴約半年の自分がテーブルコンペの取り組み方を中心にまとめていこうと思います。
今までにsubmitしたことあるコンペは[IEEE-CIS Fraud Detection](https://www.kaggle.com/c/ieee-fraud-detection)と[Predict Future Sales](https://www.kaggle.com/c/competitive-data-science-predict-future-sales)で、どちらもTop25%でメダル圏内まで達することができませんでした。
同じような境遇の人といろいろ意見交換したり、kaggler先輩の方からこの状態から脱出したきっかけ等聞かせていただけるきっかけになったらいいなと思ってまとめていくので、新たな学びが少ない記事ではあると思いますが、温かい目で見ていただけると幸いです。

# コンペの取り組み方

## 1. 公開されているNotebookの精読

"Most Votes"でソートして、上位に来ているNotebookを2-3個ほど精読します。精読なので、きちんと各セルごとに書かれているコードについて、何を目的として書いているコードなのかというのを考えて、その内容をメモ書きしつつ読むようにしています。あとは下についているコメントも欠かさず目を通すようにして有用な情報があればそれもメモしておくようにします。

あとこの精読の間に今回のコンペではどのようにテーブルデータを整形するのが適切なのかをきちんと確認するようにしています。上位のNotebookでは上の方に来ているデータの前処理のコードがだいたい同じなので、それらを参考にしています。

## 2. 特徴量生成

精読が終わり、テーブルデータの整形方法が分かったあとはひたすらに特徴量生成を行っています。取り出している特徴は以下の通りです。

- カテゴリごとの統計量    
　　　　　`df.groupby([col])[agg_col].agg([agg_type])`
こんな感じのコードを書いて取り出してます。
colやagg_colはEDAのNotebookを参考に大事そうなカテゴリ変数、数値変数から選んでいます。(ちなみに「大事そうな」の基準は、Notebookの作者がこの変数大事そうって書いてあるかどうかです笑)
agg_typeはmax, min, median, q25, q75, iqr, mean, std, kurt, skewを指定しています。 
カテゴリごとの統計量を取り出すときは、一時的に複数のカテゴリを組み合わせた新しいカテゴリ変数を作ったりもしています。
あと、時間に関する情報があるような場合は統計量ってわけではないのですが、隣接している行間でのラグを取ったりもしています。

- 行ごとの統計量
各行ごとの欠損値の数(カテゴリ変数と数値変数それぞれで求める)、0の数

- 目的変数に関係ありそうなカテゴリ変数を使ったtarget encoding
「関係ありそう」と考える基準は、EDAのNotebookを書いている人のコメントです。コメントに「このカテゴリ変数大事そう」って書いてある変数に対してtarget encodingを適用しています。

- カテゴリ変数のfrequency encoding
frequency encodingに関しては目的変数に関係あり無しに関わらず、全部やって入れるようにしています。

- その他の参考にしているNotebookで取り出していた特徴量
これは参考にしたNotebookや'Best Score'でソートして、上位に来ている単一モデルだけで評価しているNotebookの中で、取り出していた特徴量を取り出します。

- 似たデータ形式の過去コンペで使われていた特徴量
課題設定やデータ形式やデータの性質が似ている過去コンペを調べて、上位入賞した解法を読み特殊な特徴抽出方法があればそれを参考に自分が参加しているコンペに対して適用して、特徴量を取り出します。
[IEEE-CIS Fraud Detection](https://www.kaggle.com/c/ieee-fraud-detection) を例にすると、このコンペではデータが不均衡だったので、不均衡データの過去コンペを探すと[TalkingData AdTracking Fraud Detection Challenge](https://www.kaggle.com/c/talkingdata-adtracking-fraud-detection/overview)というコンペを見つけました。これもまたデータが不均衡かつ不正検知のコンペだったので、ここでの特徴量抽出は使えそうと思い、[1st place solution](https://www.kaggle.com/c/talkingdata-adtracking-fraud-detection/discussion/56475)に載っていたLDAを使った特徴量抽出の方法をそのまま真似して入れました。(実際この特徴量を加えた結果モデルの精度としては少し向上しました。)

## 3. 特徴選択(validation)

正直な話、特徴選択(validation)については自分なりのフローが固まっていません。
ここがめちゃくちゃ重要だとは感じているのですが、ここら辺をうまくまとめていただいている資料を見つけられず、非最適だと感じながらも自分なりの手法をやっている次第です。以下で自分のやり方をまとめていきます。
最初に、trainデータとtestデータの分け方を参考にして、trainデータに対してどうvalidationデータを取り出すのか、どのcross validationのやり方を適用するかを考えます。
validationデータの作り方を決めた後、以下の流れを繰り返して特徴選択をしています。

- 1. 参考にしたNotebookから上記の作業で得られた新たな特徴量を加える
- 2. 参考にしたNotebookに載っているLGBMのパラメータについて、"learning_rate"だけ高くしたモデルを作り、新たな特徴を加える前と後で精度が上がるか確かめる。
- 3. 上がった場合は新たに加えた特徴を採用し、下がった場合は新たに加えた特徴量は不採用とする。

2でまとめたような特徴生成を適用するたびに上記のような流れで特徴選択を実施し、自分が作った特徴量が有用かどうかを判定しています。

## 4. 選択した特徴を使ってモデル作成(LGBM)、チューニング
2と3の作業を、コンペの締め切り1週間前まで続けたあと、最終的に採用する特徴量を決定します。
そのあとに、optunaを使ってLGBMのにおけるハイパーパラメータチューニングを行い、採用した特徴量におけるハイパーパラメータの最適値を決定します。

## 5. LGBM以外のモデルのNotebookをチェック。
これはあくまで自分の考えなのですが、アンサンブルやスタッキングは精度向上についてはおまけ程度であると思っています。
そのため2と3の作業を繰り返し、自力でLGBMの単一モデルでスコアが高くすればするほど、あ公開NotebookにあるLGBM以外のモデルをそのまま使いアンサンブルなりスタッキングをすれば精度を上げられると考えています。
そのため4の作業を回している間に、改めて公開NotebookをチェックしてLGBM以外で作成されたmodelを自分のアンサンブル・スタッキング用のモデルとして採用し、最終的なスコアを出すようにしています。

以上が、自分のテーブルコンペの取り組み方です。
まだ歴も短く厳密に固まっているフローではないですが、自分の知識として身についている取り組みについてまとめさせていただきました。


# 終わりに
改めて自分の取り組みを文章にまとめていくと、一連の流れでどこが弱いかを確認することができてよかったと思っています。こういう自由に記事をかける機会をいただけたことに感謝します。(本来の掲載期限に間に合わせることができずすみませんでした...)
自分の場合は、特徴選択のやり方が固まっていない点といろいろ作った特徴量をアンサンブル用のモデルに反映できていない点の2点が弱いと感じています。(他に足りていない部分があったらコメントいただけると嬉しいです。)
最近[kaggle本](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93-%E9%96%80%E8%84%87-%E5%A4%A7%E8%BC%94/dp/4297108437)を購入しようやく手元に届いたので、年末年始は上記2点に関係ありそうな項目を確認し、自分のやり方を見直しながら今取り組んでいるコンペでメダルゲットを目指そうと思います。
また自分なりのやり方を見ていただいた方はわかるかと思いますが、良くも悪くも自分のモデル作成についてはオリジナリティはほぼ皆無です。主に参考にしている情報は、コンペごと公開Notebookと[Kaggleテーブルデータコンペできっと役立つTipsまとめ](https://naotaka1128.hatenadiary.jp/entry/kaggle-compe-tips)の2つです。
それでもTop25%までの成績にいける結果を踏まえると改めて感じたことは以下の2つを感じました。
- 歴代の先輩方の情報をどんどんオープンにしていくスタンスに対する感謝の気持ち
- 基本的なことを忠実にかつ課題に合わせて取り組めることの重要性

自分自身の研鑽も重ねながら、共有できることを共有していくスタイルを大事にこれからもkaggle生活を楽しんでいこうと思います!!