あれもPython,これもPython

Pythonメモ※本サイトはアフィリエイトを利用しています

pythonでProphetを使いたい(5:祝日効果を追加したい)

周期性の設定まで完了したため、その他(ノイズなど)の分析を行っていきます。 まず、あまりフィットしていない日付を見てみます。

future = mdl.make_future_dataframe(periods=0,freq='D')
future['cap'] = 6
pred  = mdl.predict(future)

tmp = pred[['ds','yhat']].assign(y=ts).set_index('ds')
not_fitted_dt = (tmp.y-tmp.yhat).sort_values(ascending=False).head(10).index

#はずれが大きい順に日をならべる
pd.Series(not_fitted_dt).apply(jpholiday.is_holiday_name)
0         憲法記念日
1          春分の日
2         みどりの日
3           海の日
4        勤労感謝の日
5          敬老の日
6          成人の日
7    こどもの日 振替休日
8         こどもの日
9       即位礼正殿の儀

きちんと祝日たちでした。
単純にこの差を祝日効果にしてもいいかもしれませんが、せっかくなのでモデルに組み込んでみます。

コード

まずはProphetの祝日設定用のデータフレームを作成します。
属性として祝日名と日付を持つ必要があります。

dt = pd.Series(pd.date_range(start='2019-01-01',periods=N))
hols = dt.apply(jpholiday.is_holiday_name )

dts = pd.DataFrame(
    {
      'holiday':dt.apply(jpholiday.is_holiday_name),
      'ds':dt.values,
      'lower_window': 0,
      'upper_window': 1,  
    }
)

あとはモデルと予測用のデータにholidaysにこのデータを渡します。

フィッティング

mdl = Prophet(
    yearly_seasonality=False,
    weekly_seasonality=True,
    daily_seasonality=False,
    growth = 'logistic',
    changepoint_prior_scale=0.3,
    #祝日効果
    holidays = dts[dts['holiday'].notna()],
    holidays_prior_scale=1.0 #祝日効果の強さをいじるパラメータ
)
mdl_df['cap'] = 6
#fitの前
mdl.add_seasonality(name = '_25',period=25,fourier_order=10)
mdl.fit(
    mdl_df
)
future = mdl.make_future_dataframe(periods=0,freq='D')
future['cap'] = 6
future['holiday'] = hols.values
pred  = mdl.predict(future)

#可視化
mdl_df.y.plot()
pred.yhat.plot()

f:id:esu-ko:20200913172408p:plain

祝日時に同じように上がる用になりました。 各祝日の影響を見ておきます。

import japanize_matplotlib

#祝日情報
mdl.holidays
hol_name = mdl.holidays['holiday']
hol_e = pred[hol_name.to_list()]
hol_e.max().plot.barh()

f:id:esu-ko:20200913172525p:plain

※なお、曜日効果や祝日効果をすべて合わせたものがadditive_terms,multiplicative_termsになります。