あれもPython,これもPython

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

PythonでProphetを使いたい(2:トレンドと転換)

時系列はトレンド + 周期性 + その他に分けて分析します。

今回はProphetのモデルのトレンドに仮定を追加したり、変化点を取り出すことで上記の式のトレンド部分の予測の調整/分析します。

▼こちらの記事で、Prophetのデフォルト予測まで実施しました。 esu-ko.hatenablog.com

Prophetのトレンドはデフォルトでは線形という仮定を置いており、予測の形は下記のようになっています。 f:id:esu-ko:20200911200212p:plain

しかし、この切りあがり停滞する形の外部要因にあたりがついており、このような線形の上昇がない、という前提をいれたい場合があります。

予測の調査

このような前提をいれたい場合、トレンドの上限に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()

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

トレンド転換の仕組み

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()

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

これをみると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')

f:id:esu-ko:20200912222542p:plain トレンド転換の位置の日付がわかったので、これをベースに施策/外部変化がなかったといった定性調査ができそうです。