Edited at
UUUMDay 25

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

この記事は、 UUUM Advent Calendar 2018 25日目の記事です。

最近データサイエンス界で盛り上がっているKaggleって知っていますか?知らない方のために簡単に説明すると、データサイエンティストの世界No.1を決める大会のようなものです!詳しくは、こちらを読むと分かりやすいかと思います。

KaggleのチュートリアルといばTitanicHouse 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)


結果

Kaggleに提出したところ、以下の結果が返ってきました。

終了したコンペなのでLeaderboard(順位表)に反映されませんが、もしコンペ期間中であれば2257人中1906位という結果でした😇

特徴量生成やモデルのチューニングなど、何も工夫していないので当然の結果ですね。


まとめ

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