日付データから得られる特徴量の観察

インターンの懇親会に参加したとき、「解決したい問題によっては日付のデータが重要になることもある」という助言がプロの人からぽろっと出ていた。

インターンの時には日付の扱いがよくわからず使わずに終わってしまった。
さりげなくどんな感じに変換して扱うのがよいか聞いておいた。日付の月や時間だけを抽出して扱うだけでも特徴量として使えるとのことだった。
扱うのが上手い人は日付から曜日に変換して曜日を特徴量として追加する人もいるらしい。さらには気象庁から天気のデータを持ってくる人もいるだとか。

日付の扱い方を練習したいと思い、またKaggleからいい感じのデータセットを漁って分類モデルを作ることにした。

コードはここ

github.com

今回使ったのはこのデータセット

My Uber Drives | Kaggle

Uberというアプリを利用した顧客さんのデータのようだ。利用した日、終了日、ドライブの距離などがあるっぽい。

分類に使うモデルではなくデータを解析して新たな発見を得るという感じのデータセットな気がするが、このデータセットの属性からドライブの利用目的を判定するモデルを作ることにする。利用目的はビジネス、パーソナルとカテゴリで分類されていた。

まずはどんなデータが格納されているか5行ほど見ることにする。
f:id:Owatank:20171002172725p:plain

ここで、利用目的として平日ならビジネス、休日ならパーソナルが多いんじゃないか?、乗った日の時刻によって利用目的は変わるのではないか、月によって利用目的に変動がありそうだと3つほど仮説を立てて新しい属性として開始日から月と時刻をげちっとする。

def time_hour_split(x):
    t = str(x['START_DATE*'])
    t = t.split()
    ret = t[1].split(':')
    return ret[0]

def date_month_split(x):
    t = str(x['START_DATE*'])
    t = t.split()
    ret = t[0].split('-')
    return ret[1]


# START_DATE* から日付の時刻と月を分けて新たな属性として追加する
df['START_HOUR_TIME'] = df.apply(lambda x: time_hour_split(x), axis=1) 
df['MONTH'] = df.apply(lambda x: date_month_split(x), axis=1)

計算量を考えない雑なコードだとこれでできた。

折角なので曜日も取得することにする。

df['START_DATE*'] = pd.to_datetime(df['START_DATE*'])

# 日付から曜日を取得
df['weekday'] = df['START_DATE*'].dt.dayofweek

対象とする属性をtp_datatimeで型変換を行い、dayofweekというのを使うことで曜日を得られるそうだ。便利!!!
新たな属性を追加したデータセットは以下のような感じになった。

f:id:Owatank:20171002173625p:plain

曜日は 0 = 月曜日 であってるはず。

判別に必要なカテゴリの分布はこんな感じだった。

f:id:Owatank:20171002173823p:plain

0がBusinessで、1がPersonal。偏ってるというレベルではない。

各属性からエントロピーを計算する。
f:id:Owatank:20171002174011p:plain

親のエントロピー0.3533593なため、0.07とかはかなり大きい気がしなくもない。
日付から取り出した月がかなり貢献できそうなことがわかる。
weekdayは利用しないことにする。

これらの属性を特徴量としてモデルを構築していく。
キノコと同じようにTensorflowを使ったロジスティック回帰とXGBoostで比べっこする。
Log_lossによる評価の結果
f:id:Owatank:20171002174329p:plain

決定木の勝利だった。

かなり正と負の偏りがあったのでダウンサンプリングを行ってみた。コードはここ

二乗誤差による評価の結果
f:id:Owatank:20171002174811p:plain

Log_lossではXgboostの方でエラーが出てしまった。
ロジスティック回帰の方の二乗誤差は0.0476177だったので、ダウンサンプリングを行なった結果の方が悪いとわかる。

これは現実においてもBusinessで利用する人のが多く、データセットのカテゴリの事前確率と現実の事前確率がほぼ同じという考えでいいのかな?
もし半分の確率でBusinessかPersonalが発生するならダウンサンプリングで偏りを無くした方がいい時もあるのかも。