04.10.3
【ベンチマーク】複数の周期が重なるデータ
seasonal_periods を 1 つしか持てないので、週次に合わせると年次を取りこぼし、年次に合わせると 365 個の季節係数で推定が不安定になります。このページでは振幅 10 の週次と振幅 25 の年次を重ねた 730 日の合成データに 6 つのモデルを当て、末尾 28 日の MASE で比べます。年次の波を sin(2πkt/365.25) と cos(2πkt/365.25) の 3 次までのフーリエ項として SARIMAX の exog に渡す方法が、週次と年次を同時に捉えて唯一 MASE を大きく下げます。残差の ACF を見ると、週次だけのモデルには年次成分の名残が長周期の相関として残ることが確認できます。電力消費量・気温・Webトラフィックなど、「曜日の波」と「年間の波」が同時に存在するデータは多い。ここでは2つの周期が重なる合成データを生成し、季節パラメーターが1つしか設定できないモデルの限界と、フーリエ特徴量による回避策を検証する。
1. データの特徴 #
このシナリオの難しさは、seasonal_periods を 1 つしか指定できないモデル(Holt-Winters や SARIMAX の基本形)が大半であることです。週次パターン(sp=7)を指定すれば年次パターンを見逃し、年次パターン(sp=365)を指定すれば季節係数が 365 個になってパラメータ数が爆発し、2 年分 730 点では 1 係数あたり 2 点しか使えずフィッティングが不安定になります。回避策は、長い周期の方を少数の sin/cos 項で近似して外生変数に渡すことで、3 次のフーリエ項なら 6 列で年次の滑らかな波を表せます。
何が起きているか(ステップで見る) #
コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。
見るポイント:水準 → 傾き → 季節 と要素を足すほど、未来への伸ばし方が豊かになる。
2. 合成データの生成 #
次のコードは、水準 200 に周期 7 日・振幅 10 の波、周期 365.25 日・振幅 25 の波、1 日 0.02 のトレンド、標準偏差 5 のノイズを足した 730 日の系列を作ります。上段に全期間、下段に直近 60 日を拡大して描き、週次の波が見えるようにします。
| |
3. 比較するパイプライン #
| モデル | 季節性の扱い | 備考 |
|---|---|---|
| 季節ナイーブ (sp=7) | 週次のみ | 年次は無視 |
| SES | なし | 両方無視 |
| Holt-Winters 加法 (sp=7) | 週次のみ | 年次は残差に漏出 |
| ARIMA(2,1,1) | なし | 両方無視 |
| SARIMAX(1,0,1)(1,1,1,7) | 週次のみ | 年次は捉えられない |
| SARIMAX + フーリエ(年次) | 週次 + 年次 | sin/cos項を外生変数に追加 |
4. 実験と結果 #
次のコードは年次周期を 3 次のフーリエ項(6 列)に変換する make_fourier を定義し、6 つのモデルで 28 日先を予測して MASE を横棒グラフにします。季節ナイーブ基準の m=7 で MASE を計算し、1 を下回った棒だけ緑で塗ります。
| |
読み方のポイント #
SARIMAX + フーリエだけが週次と年次の両方を捉え、MASE が最も低い緑の棒になります。SARIMAX(7) と HW加法(7) は週次は捉えるものの、振幅 25 の年次成分が残差に漏れるため MASE が 1 を切るかどうかの境目にとどまり、テスト 28 日間の年次の局面によっては季節ナイーブに負けることもあります。SES と ARIMA(2,1,1) は季節性を持たないので曜日の波に毎日 ±10 ずれ、MASE が 1 を大きく超えて赤くなります。棒グラフの順序は実行環境の statsmodels のバージョンで多少入れ替わりますが、「フーリエ付きが最良、季節性なしが最悪」という構図は変わりません。
5. 誤差パターン分析 #
MASE では「どの周期を取りこぼしたか」が分かりません。次のコードは SARIMAX + フーリエ、SARIMAX(7)、SES の 3 つについて、左にテスト 28 日の実測と予測、右に残差の ACF(ラグ 14 まで)を並べ、残差に週次や年次の名残が残っているかを確かめます。
| |
SARIMAX + フーリエの残差はほぼ白色雑音になり、ACF の 14 本の棒は信頼区間の帯の中に収まります。SARIMAX(7) の残差には年次成分の名残が「ラグ 1〜5 で正の相関が緩やかに減る」形の長周期の自己相関として現れ、左の図では予測の破線が実測の点列から一定方向にずれています。SES は曜日の波を全く持たないので、残差に周期 7 の波がそのまま残り、ACF のラグ 7 と 14 に顕著なスパイクが立ちます。
6. よくある失敗パターン #
最初の失敗は seasonal_periods=365 を直接指定することで、Holt-Winters なら 365 個の季節係数を 2 年分 730 点から推定することになり、1 係数あたり 2 点では収束しないか過学習します。年次のような長い周期は 3〜5 次のフーリエ項(6〜10 列)で近似し、exog に渡すのが現実的です。二つ目は季節成分を 1 つ指定して満足することで、seasonal_periods=7 で MASE が 0.9 を切っても、残差 ACF に長周期の相関が残っていれば年次を取りこぼしています。plot_acf で残差を確認し、帯を超える棒の周期から足りない成分を特定します。三つ目はフーリエ項の次数を上げすぎることで、10 次(20 列)にすると年次の波に細かいギザギザまで当てはめ、2 年分のデータでは学習期間だけに合う形になります。
- ウォークフォワード検証 — 時系列の正しい評価手法
- MASE — 季節ナイーブ基準の精度指標
- ARIMA モデル — 自己回帰と移動平均
- ホルト・ウィンター法 — 季節性を含む指数平滑法