時系列分析の基礎を整理する (入門)

## 概要
自学の為、過去に学習した時系列分析理論の基礎を整理していきたい
はじめは、厳密性よりは全体的な地図を描けるよう、粗い粒度から進めてみたいと思う
(コンパクトな構成にするため、コードは最小限)

(https://zenn.dev/t_shi/articles/7bc8787f4477b4 と同一です)

## 内容
### 時系列データの特徴を3行で
強引にまとめると
1. データ生成過程**DGP**から、時間に従って変化する**確率分布**をモデル化する
2. **DGP**から時点のデータが得られたと過程し、理論的な期待値や分散を求める
3. 時系列データ = `短期の自己相関 + 周期的変動 + トレンド + 外因性 + ホワイトノイズ`

t時点におけるデータはたった一点しかないが、それは、時点における確率分布の中から、得た一点であると仮定する

### 先ずは一通り試してみる際のイメージ
![](https://storage.googleapis.com/zenn-user-upload/7de9881fcdc2-20240715.png)
1. 前処理 = 自己相関, 偏自己相関分析 / 定常化変換処理 (diff, log) / ADFによる単位根検定
2. モデリング = 今回はSARIMA / AIC / 残差plotによる確認
3. 予測
4. 評価 = RMSE, MAPFなど

(2)に関して、一般に基礎理論の記事では、AR, MA, ARIMA, SARIMAと順を追って説明する事が多いが
記事としてのコンパクトさを優先した結果として、いきなり`SARIMA`で進めることにした
(VARやProphetは割愛)

### SARIMA
![](https://storage.googleapis.com/zenn-user-upload/b736923a176f-20240715.png)
一周期が`s`であるデータにおいて、(月単位ならs=12)ARIMAの次数`(p,d,q)`及び、季節性の次数`(P,D,Q)`を指定する

ざっくりと、SARIMAモデルまでの変遷
1. AR = 自己回帰モデル
2. MA = 移動平均モデル
3. ARMA = (1)+(2)。定常データに使える、非定常には使えない
4. ARIMA = (3)を非定常でも利用できるよう、差分系列をとって、定常過程に変換してからARMAモデルを使う
5. SARIMA = ARIMA + 季節性成分

https://towardsdatascience.com/time-series-forecasting-with-arima-sarima-and-sarimax-ee61099e78f6

### 実際に動かしてみる
データは [Kaggle - Air Passengers](https://www.kaggle.com/datasets/chirag19/air-passengers)を使用

#### 1. 前処理
非定常過程が定常過程になるように、変換処理を施す
|#|原系列|差分系列|対数系列|対数差分系列|
|-|-|-|-|-|
|処理|*|diff|log|log + diff|
|Graph|![](https://storage.googleapis.com/zenn-user-upload/d598b283471f-20240715.png)|![](https://storage.googleapis.com/zenn-user-upload/abd9a11b8bc1-20240715.png)|![](https://storage.googleapis.com/zenn-user-upload/1c5da3182f23-20240715.png)|![](https://storage.googleapis.com/zenn-user-upload/a157c4594b8a-20240715.png)|
|ADF|![](https://storage.googleapis.com/zenn-user-upload/8d729dbababf-20240715.png)|![](https://storage.googleapis.com/zenn-user-upload/0081b6113715-20240715.png)|![](https://storage.googleapis.com/zenn-user-upload/fad60b2b9fcb-20240715.png)|![](https://storage.googleapis.com/zenn-user-upload/103e5b50879f-20240715.png)|
|p値|0.99|0.054|0.416|0.048|

右端の**対数差分系列**であれば、**p値が0.048** (4.8%)で**Ho (帰無仮説)が棄却**される
つまり、**単位根は存在せず、定常過程**とみなせる

今回は割愛しているが、その他、非定常な時系列データを定常化する処理として
1. トレンド除去
2. 差分化 = n期前データとの差分を取る
3. Box-Cox変換 = Box-Coxは対数変換を一般化したもの


#### 2. モデリング
SARIMAモデルのパラメータは、AICが最小化されるように自動判定する
(1)の過程に反し、改善の余地がある状況を明確に再現したい意図もあり
入力データは無変換のデータを利用する (= `df["Passengers"]`)
```python
import pmdarima as pm

arima_model = pm.auto_arima(df["Passengers"], seasonal=True, m=12, trace=True, n_jobs=-1, maxiter=10)
```
![](https://storage.googleapis.com/zenn-user-upload/71ce7e315e34-20240715.png)
`SARIMA(0,1,1)(2,1,1)[12]`がベストと判定された

推定されたパラメータに対して、残差プロットをベースにモデルの適合度を検証する
```python
arima_model.plot_diagnostics(figsize=(14,10))
```
![](https://storage.googleapis.com/zenn-user-upload/343595254637-20240715.png)
- 残差はホワイトノイズに近く見えるが、一部外れ値がある
- 正規分布というより、やや左に傾いている
- コレログラムからlagは0から外れている箇所もあり、若干の周期性
が見受けられる (改善の余地が見受けられる)

#### 3. 予測
予測値のグラフを書く
```python
from pmdarima import model_selection

df_train, df_test = model_selection.train_test_split(df["Passengers"], test_size=12)
test_pred, test_pred_ci = arima_model.predict(n_periods=df_test.shape[0], return_conf_int=True)

plot_graph(df_train, df_test, test_pred, test_pred_ci) # 実装は省略
```
![](https://storage.googleapis.com/zenn-user-upload/54f66e876537-20240715.png)
グラフの形状は学習できている印象はあるが、値が大きく上振れしている為、精度に課題がある事が分かる

#### 4. 評価
```python
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_percentage_error

print(f"RMSE: {np.sqrt(mean_squared_error(df_test, test_pred))}")
print(f"MAPE: {np.sqrt(mean_absolute_percentage_error(df_test, test_pred))}")

# RMSE: 41.592855995849725
# MAPE: 0.2968483480823645
```
予測モデルの予測が、実際の観測値と比較して、平均して29%の誤差があるという状況は決して良くはない
**改善余地がある為、変換処理等を再検討し、精度向上に努めていく**
(当該ブログとしては、一旦ここまで)

## 参考
[ 書籍 ]
- [時系列分析と状態空間モデルの基礎 - RとStanで学ぶ理論と実装](https://www.amazon.co.jp/%E6%99%82%E7%B3%BB%E5%88%97%E5%88%86%E6%9E%90%E3%81%A8%E7%8A%B6%E6%85%8B%E7%A9%BA%E9%96%93%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E5%9F%BA%E7%A4%8E-R%E3%81%A8Stan%E3%81%A7%E5%AD%A6%E3%81%B6%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E9%A6%AC%E5%A0%B4-%E7%9C%9F%E5%93%89/dp/4903814874)

[ web ]
- [セールスアナリティクス - （Python版）複数季節性を持つ時系列データをモデル化する方法（TBATSモデルとARIMAモデル）
](https://www.salesanalytics.co.jp/datascience/datascience116/)
- [ROXX開発者ブログ - 時系列分析による時系列データの解析と未来予測（ARIMA, SARIMA）](https://techblog.roxx.co.jp/?page=1693480040)
- [Time Series Forecasting with ARIMA , SARIMA and SARIMAX
](https://towardsdatascience.com/time-series-forecasting-with-arima-sarima-and-sarimax-ee61099e78f6)

## 総括
実用時に参照する全体像を掴める資料を作るのが目的なので、上澄みを掬った内容になっている点、ご容赦いただけますと幸いです
(数学を専門とする方にはお叱りを受けそう・・)

以上