時系列分析Prophetのテスト（Cross validation）設定方法

時系列分析ライブラリProphetのCross validationでの、各関数パラメータ設定方法👇がちょっと難しかったので、まとめておく。

https://facebook.github.io/prophet/docs/diagnostics.html#cross-validation


## cross_validationのパラメータ
テストパターンを制御するパラメータは以下。

|パラメータ|意味|指定フォーマット|
| ---- | ---- | ---- |
|initial|テストパターン（第1ターム）のトレーニング期間|[pandas.Timedelta](https://pandas.pydata.org/docs/reference/api/pandas.Timedelta.html#pandas-timedelta)|
|period|テストパターンとテストパターンのズレ|[pandas.Timedelta](https://pandas.pydata.org/docs/reference/api/pandas.Timedelta.html#pandas-timedelta)|
|horizon|各テストパターンの長さ|[pandas.Timedelta](https://pandas.pydata.org/docs/reference/api/pandas.Timedelta.html#pandas-timedelta)|
|cutoffs|各テストパターンの開始日時の直前|[pandas.Timestamp](https://pandas.pydata.org/docs/reference/api/pandas.Timestamp.html#pandas-timestamp)のリスト|

イメージ👇
[![Image from Gyazo](https://i.gyazo.com/3f8d9fbc8c3e92fa65c607fcd88ece72.png)](https://gyazo.com/3f8d9fbc8c3e92fa65c607fcd88ece72)

### 重要なのはhorizonとcutoffs

この中で特に重要なパラメータは、**horizon**と**cutoffs**
**cutoffs**で指定した各日時から**horizon**分の期間をpredictしている。

[![Image from Gyazo](https://i.gyazo.com/49d7dfc6f7fbf881150be67ca75556bb.png)](https://gyazo.com/49d7dfc6f7fbf881150be67ca75556bb)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L241

### horizon

指定必須のパラメータ

### cutoffs

**cutoffs**を指定すれば、そのまま利用される。
**cutoffs**を指定しなければ、**initial**と**period**と**horizon**から算出される。

[![Image from Gyazo](https://i.gyazo.com/1be7963f6bcc348038525bd9aa4401d9.png)](https://gyazo.com/1be7963f6bcc348038525bd9aa4401d9)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L134

**cutoffs**の算出方法は、

1. 手持ちデータの最終日時から**horizon**を引いた値
1. 1から**period**を引いた値
1. 2から**period**を引いた値
1. 3から**period**を引いた値・・・

※手持ちデータの初日時 + **initial**より小さくならないところまで続く

[![Image from Gyazo](https://i.gyazo.com/1dc3a0e533815c452a447aa680ff2b93.png)](https://gyazo.com/1dc3a0e533815c452a447aa680ff2b93)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L35

### period

**period**を指定すれば、そのまま利用される。
**period**を指定しなければ、**horizon** × 0.5がセットされる。

[![Image from Gyazo](https://i.gyazo.com/79d817328de62c86a5a646cbbb512d28.png)](https://gyazo.com/79d817328de62c86a5a646cbbb512d28)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L136

### initial

**cutoffs**が指定されておらず、**initial**を指定すれば、そのまま利用される。
**cutoffs**が指定されておらず、**initial**を指定しなければ、**horizon** × 3がセットされる。
※ただし、**horizon** × 3がseasonality_dtより小さい場合、seasonality_dtがセットされる。seasonality_dtは[seasonalities](https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/forecaster.py#L946)から取得され、手持ちデータから周期性を計測できる1年、1週、1日の中の最大のものを指す。例えば、5日間毎時計測した温度の時系列データであれば1日となる。

**cutoffs**が指定されている場合、**initial**には、手持ちデータの初日時から**cutoffs**の最初の日時までの期間がセットされる。

[![Image from Gyazo](https://i.gyazo.com/ff6c7485aeef7c35afe228a0a6d4e799.png)](https://gyazo.com/ff6c7485aeef7c35afe228a0a6d4e799)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L134

## performance_metricsのパラメータ

評価指標の算出単位を制御するパラメータは以下。

|パラメータ|意味|指定フォーマット|
| ---- | ---- | ---- |
|rolling_window|移動平均（中央値）のターム|0から1|
|monthly|月単位で集計するか否か|True/False|

### rolling_window

0.1（デフォルト）の場合、前方10%のデータから、各指標（MSE/RMSE/MAE/MAPE/MDAPE/SMAPE/COVERAGE）が算出される。

イメージ👇
[![Image from Gyazo](https://i.gyazo.com/8578b9dfc48ce90e8b81805c795815b3.png)](https://gyazo.com/8578b9dfc48ce90e8b81805c795815b3)

引用：[Diagnostics | Prophet](https://facebook.github.io/prophet/docs/diagnostics.html#cross-validation)

horizon列でソートして、rolling_window指定値の割合分のデータで[rolling mean](https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L403)もしくは[rolling median](https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L456)を算出している。

[![Image from Gyazo](https://i.gyazo.com/c9906b4456bdae33a7b97d6d4efbd25f.png)](https://gyazo.com/c9906b4456bdae33a7b97d6d4efbd25f)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L376

### monthly

montly = Trueとした場合、日付を月単位に変換してhorizon列に投入される。

 [![Image from Gyazo](https://i.gyazo.com/ddfdda6ad3a658332dae5fca8dc5dbc2.png)](https://gyazo.com/ddfdda6ad3a658332dae5fca8dc5dbc2)

https://github.com/facebook/prophet/blob/0bf05baf3c4ace5e02e18a432ec6c2d734a97034/python/prophet/diagnostics.py#L377