Kaggle - 初心者でも取り組みやすいコンペの紹介

この記事は、 [UUUM Advent Calendar 2018](https://qiita.com/advent-calendar/2018/uuum) 25日目の記事です。

最近データサイエンス界で盛り上がっている[Kaggle](https://www.kaggle.com)って知っていますか？知らない方のために簡単に説明すると、データサイエンティストの世界No.1を決める大会のようなものです！詳しくは、[こちら](https://note.mu/currypurin/n/nf390914c721e)を読むと分かりやすいかと思います。

Kaggleのチュートリアルといば[Titanic](https://www.kaggle.com/c/titanic)や[House Prices](https://www.kaggle.com/c/house-prices-advanced-regression-techniques)がとても有名で、巷にはこの2つのコンペに関する記事があふれています。しかし、それ以外のコンペに関する情報は、それほど多くありません。そのため、私がKaggleに取り組み始めた当初は「TitanicとHouse Pricing以外で分析の練習をしてみたいけど、どのコンペが取り組みやすいの？」という状況になり、コンペ選びに苦労しました。

この記事では、分析の練習問題として最適な[Restaurant Revenue Prediction](https://www.kaggle.com/c/restaurant-revenue-prediction)について紹介したいと思います！

## コンペの内容
このコンペは、世界中に2,000以上のレストランを運営している[TFI](https://www.tabfoods.com/)が2015年に開催しました。

- **背景**
TFIではレンストランを新規に出店する場合、個人の判断や経験に基づく主観的なアプローチによって、出店日時・場所を決定しています。しかし、異なる地域や文化圏に出店する際には、この主観的なアプローチだと予測を立てることが難しく限界があります。そこで、新規出店戦略に有効な数理モデルを見つけることで、出店にかかるリスクを低減したいと考えています。
	
	
- **分析目的**
店舗の物件データや店舗が立地する人口統計データ、または商業統計データから、店舗の年間売上を予測
	
- **評価指標**
Root Mean Squared Error
$$
RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y_i})^2}
$$
	
## データ概要
このコンペでは、3つのデータセットが提示されています。

- train.csv
	- 学習用のデータ
	- 137店舗のデータが含まれる
	- 売上データがある
- test.csv
	- 検証用のデータ
	- 100,000店舗のデータが含まれている
	- 売上のデータがない
- sampleSubmission.csv
	- 提出するデータセットのサンプル


trainデータとtestデータに含まれている各特徴量は以下の通りです。

|特徴量|説明|
|:---:|:---:|
|Id|レストランId|
|Open Date|開店日|
|City|レストランの所在地|
|City Group|都市の規模|
|Type|業態|
|P1 ~ P37|物件データや人口統計データ、商業統計データ|
|Revenue|年間の売上 __←これを予測する__|

## 実際に予測してみる
必要最低限の前処理+RandomForestを使って売上を予測してみました。

まず、データを読み込みます。

```python
import pandas as pd

df_train = pd.read_csv('./path/to/train.csv')
df_test = pd.read_csv('./path/to/test.csv')
```

続いて、前処理をしていきましょう。
このデータには欠損がないので、`Open Date`,`City`, `City Group`, `Type`を数値に変換するだけにします。

```python
import datetime
from sklearn.preprocessing import LabelEncoder

#目的変数を抽出
revenue = df_train["revenue"]
del df_train["revenue"]

#前処理がしやすい様に、trainとtestを結合
df_whole = pd.concat([df_train, df_test], axis=0)

#Open Dateを年・月・日に分解
df_whole["Open Date"] = pd.to_datetime(df_whole["Open Date"])
df_whole["Year"] = df_whole["Open Date"].apply(lambda x:x.year)
df_whole["Month"] = df_whole["Open Date"].apply(lambda x:x.month)
df_whole["Day"] = df_whole["Open Date"].apply(lambda x:x.day)

#Cityを数値に変換
le = LabelEncoder()
df_whole["City"] = le.fit_transform(df_whole["City"])

# City Groupを数値に変換 Other -> 0, Big Cities -> 1
df_whole["City Group"] = df_whole["City Group"].map({"Other":0, "Big Cities":1})

#Typeを数値に変換 FC -> 0, IL -> 1, DT -> 2, MB -> 3
df_whole["Type"] = df_whole["Type"].map({"FC":0, "IL":1, "DT":2, "MB":3})

#再びtrainとtestに分割
df_train = df_whole.iloc[:df_train.shape[0]]
df_test = df_whole.iloc[df_train.shape[0]:]
```

前処理が完了したので、最後にRandomForestを使って学習させましょう。ちなみに、パラーメータは適当に設定しています...

```python
from sklearn.ensemble import RandomForestRegressor

#学習に使う特徴量を取得
df_train_columns = [col for col in df_train.columns if col not in ["Id", "Open Date"]]

#RandomForestで学習させる
rf = RandomForestRegressor(
	n_estimators=200, 
	max_depth=5, 
	max_features=0.5, 
	random_state=449,
	n_jobs=-1
)
rf.fit(df_train[df_train_columns], revenue)
```

学習させたRandomForestをtestデータに適用して、売上を予測しましょう

```python
prediction = rf.predict(df_test[df_train_columns])
```

最後に提出用のデータセットを作成します。

```python
submission = pd.DataFrame({"Id":df_test.Id, "Prediction":prediction})
submission.to_csv("TFI_submission.csv", index=False)
```

## 結果
Kaggleに提出したところ、以下の結果が返ってきました。
<img width="947" alt="TFI_result.png" src="https://qiita-image-store.s3.amazonaws.com/0/314319/2bcc9fdc-82d6-8f55-54ed-26642fc4096e.png">

終了したコンペなのでLeaderboard(順位表)に反映されませんが、もしコンペ期間中であれば2257人中**1906位**という結果でした😇
特徴量生成やモデルのチューニングなど、何も工夫していないので当然の結果ですね。

## まとめ
TFIのコンペは分析目的やデータサイズの観点から考えても、Kaggle初心者にとって非常に取り組みやすいコンペですので、是非チャレンジしてみてください！