04.11.5
MSTL分解
statsmodels 0.14.0 以降の MSTL(series, periods=(24, 168)).fit() の 1 行で使えます。このページでは np.sin と np.cos の 2 本の波に対数トレンドを重ねた 1000 日の人工データを分解し、.seasonal が 2 列になって周期ごとに分かれること、.resid がほぼ 0 に収まることを 4 段のプロットで確かめます。直感 #
電力消費のデータには「1 日の中で昼に高く夜に低い」24 時間周期と、「平日に高く週末に低い」7 日周期が同時に乗っています。STL は周期を 1 つしか指定できないので、24 時間で分解すると 7 日周期がトレンドか残差に紛れ込み、7 日で分解すると 24 時間周期が残差に残ります。MSTL は「まず短い周期 24 で STL を当てて季節成分を引き、残りに長い周期 168 で STL を当てる」という手順を繰り返して、周期ごとの季節成分を別々の列に取り出します。
複数の周期性が重なったデータをトレンド・季節/周期性・残差に分解する #
MSTL は STL 分解(LOESS による季節・トレンド分解)手法を拡張したもので、複数の季節パターンを持つ時系列の分解が可能です。statsmodels の version==0.14.0 以降でのみ使用できます。引数の詳細はドキュメントを確認してください。
K. Bandura, R.J. Hyndman, and C. Bergmeir (2021) MSTL: A Seasonal-Trend Decomposition Algorithm for Time Series with Multiple Seasonal Patterns. arXiv preprint arXiv:2107.13462.
Anacondaを仮想環境として使用している場合、conda install -c conda-forge statsmodelsでインストールされるものは0.13.Xとなっています(2022/11/1時点)。その場合、作業中の仮想環境の中で以下のコマンドを使用して最近のバージョンをインストールしてください。
pip install git+https://github.com/statsmodels/statsmodels
使うライブラリ #
| |
何が起きているか(ステップで見る) #
コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。
見るポイント:元データ = トレンド + 季節成分 + 残差。残差に残った大きな山が異常の候補。
サンプルデータを作成 #
周期の異なる三角関数を 2 本足し、さらに i % 14 のノコギリ波と np.log(i**3 + 1) + np.sqrt(i) の上昇トレンドを重ねます。答えを知っているデータなので、分解後の .seasonal 2 列がそれぞれどの波に対応するかを確かめられます。
| |
| 日付 | 観測値 | |
|---|---|---|
| 0 | 2018-01-01 | 20.000000 |
| 1 | 2018-01-02 | 24.618006 |
| 2 | 2018-01-03 | 26.583476 |
| 3 | 2018-01-04 | 26.587164 |
| 4 | 2018-01-05 | 28.330645 |
| 5 | 2018-01-06 | 32.415653 |
| 6 | 2018-01-07 | 35.578666 |
| 7 | 2018-01-08 | 35.663289 |
| 8 | 2018-01-09 | 34.892380 |
| 9 | 2018-01-10 | 36.617664 |
折れ線で全体の形を見ます。大きなうねり(周期 168)の上に細かいギザギザ(周期 4.8 と 14)が乗り、全体が右上がりになっています。
| |

トレンド・季節/周期性・残差に分解する #
periods に取り出したい周期をタプルで渡し、.fit() を呼ぶだけで分解が終わります。周期は短いものから並べます。
| |
分解結果のトレンド(.trend)、季節/周期性(.seasonal)、残差(.resid)をそれぞれプロットします。今回は周期の異なる三角関数を 2 本足しているので .seasonal には 2 つの列が含まれています。残差のプロットにところどころ山があるものの、ほとんどの領域で残差が 0 に近く、きれいに分解できていることが確認できます。
| |

使いどころと落とし穴 #
MSTL は電力・来店数・Web アクセスのように「1 日」と「1 週間」の周期が重なるデータで威力を発揮します。周期の候補は ACF や FFT のピークから拾い、periods を昇順に並べて渡します。周期を入れ忘れると、その成分はこのページの i % 14 のようにトレンドや残差に紛れるので、分解後は必ず .resid に周期的な山が残っていないかを確かめてください。1 周期しかないデータなら STL で十分で、statsmodels 0.13 以前の環境では MSTL 自体が import できない点にも注意が必要です。