Prophetは時系列モデルを簡単に扱える手法です。 Facebookから発表され、Pythonからも使用することができます。
モデリングでいじれる部分がかなり多いので、何本かの記事に分けて試していきます。
使い方
sklearn-likeな呼び出しになっています。
predict前の準備のみ注意が必要です。
from fbprophet import Prophet mdl = Prophet() #データをfit mdl.fit(mdl_df) #predict future = mdl.make_future_dataframe(periods=0,freq='D') pred = mdl.predict(future)
使ってみる
テストデータをつくる
テストデータをつくって試してみます。 今回は
- 祝日
- 曜日周期
- 外部効果でベースがあがる
- よくわからないトレンド
- 別の変量効果
といろいろな要素を盛り込んでみます。
import math import random import pandas as pd import jpholiday N = 365 #祝日効果 dt = pd.Series(pd.date_range(start='2019-01-01',periods=N)) f = lambda x : random.random() * 5 if jpholiday.is_holiday_name(x) else 0 hol = dt.apply(f) #外部効果で突然上がる効果 trend1 = [ 2/(1 + math.exp(-1*(i - N/2) * 0.1)) for i in range(N)] #変な周期性効果 trend2 = [ math.cos(i * 0.25) for i in range(N)] #曜日効果 season_base = [ random.random() for i in range(7)] season = [season_base[i%7] for i in range(N)] #別の変数 x = pd.Series([random.random() * 0.01 for i in range(N)]).cumsum() y = x.apply(lambda x : x * 1.25 + random.gauss(mu=0.5,sigma=0.25)) #ノイズ noise = [random.random() for i in range(N)] df = pd.DataFrame( { "trend1":trend1, "trend2":trend2, "season":season, "noise":noise, "hol":hol, "y":y } ) #上記の要素を足し合わせる ts = df.apply(lambda x : sum(x),axis=1) ts.plot()
データの読み込みとモデリング
ほとんどいじらずにフィッティングしてみます。
つっこむデータはds
、y
というカラム名で入れる必要があります。
mdl_df = pd.DataFrame( { "ds":pd.date_range(start='2019-01-01',periods=365), 'y':ts } )
フィッティングしていきます。
一年分のデータかつ,時間情報はないので、weekly
以外の季節性をオフにしています。(勝手にオフにはしてくれるのですが、わかりやすくするため)
from fbprophet import Prophet mdl = Prophet( yearly_seasonality=False, weekly_seasonality=True, daily_seasonality=False ) mdl.fit( mdl_df ) future = mdl.make_future_dataframe(periods=0,freq='D') pred = mdl.predict(future)
pred.head() pred.yhat.plot() ts.plot()
なんとなくこれでも、緩やかな形はとらえてくれてはいます。実務上、とてもざっくりみるだけならこれでもよいこともあるかもしれません。
ただし、外部効果としていれてロジスティックの形などはほとんどとれていません。時系列の分析としては、まだまだ仮定を入れていく必要がありそうです。
予測してみる
periodsの期間を長くとるだけです。
future = mdl.make_future_dataframe(periods=365,freq='D') pred = mdl.predict(future) pred.yhat.plot() ts.plot()