時系列はトレンド + 周期性 + その他に分けて分析します。
今回はProphetのモデルのトレンドに仮定を追加したり、変化点を取り出すことで上記の式のトレンド部分の予測の調整/分析します。
▼こちらの記事で、Prophetのデフォルト予測まで実施しました。 esu-ko.hatenablog.com
Prophetのトレンドはデフォルトでは線形という仮定を置いており、予測の形は下記のようになっています。
しかし、この切りあがり停滞する形の外部要因にあたりがついており、このような線形の上昇がない、という前提をいれたい場合があります。
予測の調査
このような前提をいれたい場合、トレンドの上限にcapをつけます。
付け方は、データにcap
というカラムを追加するのと、mdlにgrowth = 'logistic'
を設定します。
今回はデータをもとに6くらいで停滞する、という判断がされた、という前提にします。
mdl_df['cap'] = 6 #mdl_df['floor'] = 0 mdl = Prophet( yearly_seasonality=False, weekly_seasonality=True, daily_seasonality=False, growth = 'logistic' #非線形のトレンドを仮定 ) mdl.fit( mdl_df ) future = mdl.make_future_dataframe(periods=365,freq='D') future['cap'] = 6 #future['floor'] = 0 pred = mdl.predict(future)
※加工する場合はfloor
という前提をつけます。
可視化すると下記のようになり、上昇後は横ばいになっていることがうかがえます。
pred.yhat.plot() ts.plot()
トレンド転換の仕組み
Prophetのトレンド転換は、転換となる点をばらまいて、その転換の強さを推定しています。
import numpy as np #転換点 cp = mdl.changepoints #delta:転換の強さ deltas = mdl.params['delta'].mean(0) #changepoint_prior_scale:フィットさせる強さ mdl = Prophet( yearly_seasonality=False, weekly_seasonality=True, daily_seasonality=False, growth = 'logistic', changepoint_prior_scale=0.5 #これ )
時系列データを見るときに転換点はいつであった可能性が高いのか、を定量的に把握したいことがあり、それを抽出できると非常に便利です。
# 転換点と転換可能性のdf cp_df = pd.DataFrame( { "ds":cp, "deltas":deltas } ) cp_df.set_index('ds').plot.barh()
これをみると6月ごろに大きな転換が、前半にちょいちょいトレンドが動いていたことがわかります。
トレンド動きと、転換点の強さを実測データに重ねてみると、議論をするときに便利です。
#上位1/4のみ可視化する #75パーセンタイルを閾値 th = cp_df['deltas'].quantile(0.75) #抽出して予測データと結合 f = lambda x : x if abs(x) >= th else np.nan w_cp_df = pred[['ds','trend','yhat']].merge(cp_df.assign(deltas = cp_df.deltas.apply(f)),how='left') # 以下可視化 ts.plot() plt.plot(w_cp_df['trend']) #転換位置にvlinesで線を引く y_min_v = 0 #線の下限 y_max_v = 10 #線の上限 plt.vlines(w_cp_df[w_cp_df['deltas'].notna()].index,ymin=y_min_v,ymax=y_max_v,linestyle="dotted",color='green')
トレンド転換の位置の日付がわかったので、これをベースに施策/外部変化がなかったといった定性調査ができそうです。