この記事は、 UUUM Advent Calendar 2018 25日目の記事です。
最近データサイエンス界で盛り上がっているKaggleって知っていますか?知らない方のために簡単に説明すると、データサイエンティストの世界No.1を決める大会のようなものです!詳しくは、こちらを読むと分かりやすいかと思います。
KaggleのチュートリアルといばTitanicやHouse Pricesがとても有名で、巷にはこの2つのコンペに関する記事があふれています。しかし、それ以外のコンペに関する情報は、それほど多くありません。そのため、私がKaggleに取り組み始めた当初は「TitanicとHouse Pricing以外で分析の練習をしてみたいけど、どのコンペが取り組みやすいの?」という状況になり、コンペ選びに苦労しました。
この記事では、分析の練習問題として最適なRestaurant Revenue Predictionについて紹介したいと思います!
コンペの内容
このコンペは、世界中に2,000以上のレストランを運営しているTFIが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を使って売上を予測してみました。
まず、データを読み込みます。
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
を数値に変換するだけにします。
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を使って学習させましょう。ちなみに、パラーメータは適当に設定しています...
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データに適用して、売上を予測しましょう
prediction = rf.predict(df_test[df_train_columns])
最後に提出用のデータセットを作成します。
submission = pd.DataFrame({"Id":df_test.Id, "Prediction":prediction})
submission.to_csv("TFI_submission.csv", index=False)
結果
終了したコンペなのでLeaderboard(順位表)に反映されませんが、もしコンペ期間中であれば2257人中1906位という結果でした😇
特徴量生成やモデルのチューニングなど、何も工夫していないので当然の結果ですね。
まとめ
TFIのコンペは分析目的やデータサイズの観点から考えても、Kaggle初心者にとって非常に取り組みやすいコンペですので、是非チャレンジしてみてください!