Pythonで学ぶ時系列予測 ― e-learningで基礎から実践まで Part 6
はじめに
Part 5では、予測モデルそのものを学びました。
最後に整理した流れは、次のようなものでした。
ここまでで、モデルを作るための部品はひと通りそろいました。
Part 6では、それらを1つの予測プロジェクトとして最初から最後までつなげます。
つまり、今回の主役は新しいモデルではありません。
という仕事の進め方そのものです。
今回も、これまでと同じe-learning形式で進めます。
説明を読む
↓
Notebookで試す
↓
結果を見る
↓
条件を少し変える
↓
確認問題
1. Part 5からPart 6へ
Part 5では、ARIMAの候補を作り、Walk Forward Validationで比較できるようになりました。
しかし実際の仕事では、いきなりARIMAのp、d、qを探すところから始めるわけではありません。
まず考えるべきなのは、
何を、どの時点まで、何のために予測したいのか
です。
そのうえで、予測性能を測る仕組みを作り、単純なBaselineを置き、データを調べます。
中心になる流れは次のとおりです。
Part 6では、この流れを3つのデータで繰り返します。
2. Part 6 ― Projects
原書Part VIはChapter 29からChapter 32までです。
| Lesson | 原書Chapter | 内容 | データ |
|---|---|---|---|
| Lesson 29 | 29 | Time Series Forecast Projects | Projectの進め方 |
| Lesson 30 | 30 | Monthly Armed Robberies in Boston | 月間robberies |
| Lesson 31 | 31 | Annual Water Usage in Baltimore | 年間water usage |
| Lesson 32 | 32 | Monthly Sales of French Champagne | 月間champagne sales |
原書では最初に予測プロジェクト全体の進め方を整理し、そのあと3つのケーススタディを行います。
3つのProjectで使う基本形は共通です。
Problem Description
↓
Test Harness
↓
Persistence
↓
Data Analysis
↓
ARIMA Models
↓
Model Validation
この「同じ型で異なるデータを見る」ことがPart 6のポイントです。
3. Part 6のゴール
Part 6を終えた時点で、次のことができれば十分です。
- 予測問題を文章で定義できる
- Forecast Horizonと評価期間を先に決められる
- 最終Validationをモデル選択から分離できる
- Development期間の中だけでTest Harnessを作れる
- PersistenceをBaselineとして置ける
- グラフと統計量から系列の特徴を整理できる
- ACF / PACFや差分からARIMA候補を考えられる
- 小さな候補集合を同じ条件で比較できる
- 最終Validationはモデル選択の後に一度だけ使える
- Projectごとに変える部分と共通化できる部分を説明できる
- 最後に次時刻の予測まで進められる
最も大切なのは、
最終Validationを見ながらモデルを調整しない
ことです。
最終Validationを何度も見て設定を変えると、そこも実質的には学習データになってしまいます。
4. 学習環境はPart 5をそのまま使う
Part 6でもDocker + JupyterLabを使います。
Windowsのブラウザー
↓
JupyterLab
↓
Notebook
↓
Python
↓
pandas / NumPy / Matplotlib / statsmodels
Part 5までのNotebookはすべて残し、その後ろへPart 6を追加します。
notebooks/
├── 01_environment.ipynb
├── ...
├── 19_box_jenkins.ipynb
├── 20_autoregression.ipynb
├── 21_moving_average_model.ipynb
├── 22_arima.ipynb
├── 23_acf_pacf.ipynb
├── 24_grid_search.ipynb
├── 25_save_predict.ipynb
├── 26_confidence_intervals.ipynb
├── 27_project_process.ipynb
├── 28_boston_robberies.ipynb
├── 29_baltimore_water.ipynb
└── 30_champagne.ipynb
起動方法も同じです。
docker compose up
初回や依存関係を作り直す場合は、
docker compose up --build
です。
5. Part 6で使うデータ
今回は人工データではなく、書籍付属ZIPに含まれている3つのCSVを使います。
| File | 期間 | 件数 | 時間間隔 |
|---|---|---|---|
robberies.csv |
1966-01〜1975-10 | 118 | 月次 |
water.csv |
1885〜1963 | 79 | 年次 |
champagne.csv |
1964-01〜1972-09 | 105 | 月次 |
外部サイトへアクセスしなくても、配布ZIPだけで演習できます。
Part 6ではデータを次の3層に分けて考えます。
全データ
│
├─ Development
│ │
│ ├─ Internal Train
│ └─ Internal Test
│
└─ Final Validation
Internal Test はモデル候補の比較に使います。
Final Validation は最終候補が決まるまで触りません。
Lesson 29 ― Time Series Forecast Projects
学習目標
このLessonでは、次のところまで進みます。
- 予測プロジェクトを手順として整理する
- 5-Step Forecasting Taskを理解する
- 反復型のForecast Development Processを理解する
- Test Harnessを早い段階で固定する理由を説明できる
- Simple Baselineから始める理由を説明できる
6. 予測は「モデル」より先に「問題」を決める
時系列予測では、モデル選びに目が行きがちです。
しかし、最初に決めるのはARIMAではありません。
例えば、雨量を扱うとしても、
10分先を予測する
のと、
6時間先を予測する
のでは、同じデータでも問題が違います。
さらに、
値そのものを予測する
のと、
閾値を超えるかを予測する
のでも評価方法は変わります。
そのためProblem Definitionでは、最低でも次を文章にします。
何を予測するか
どこまで先を予測するか
誰が使うか
何に使うか
どの指標で良し悪しを決めるか
7. 5-Step Forecasting Task
予測作業を大きく5段階に整理します。
難しいモデル名が入っていないところが重要です。
まず問題と情報を整理し、データを見てからモデルへ進みます。
8. 実務では一方向ではなく戻る
もう一つ大切なのが、反復することです。
実際には、評価結果を見てモデルへ戻ります。
データを見ている途中で、追加情報が必要だと分かることもあります。
したがって、Forecast Projectは一度通ったら終わる直線ではありません。
9. 先にTest Harnessを作る
Part 4で学んだ内容がここで効いてきます。
モデルを作る前に、
どの期間をTrainにするか
どの期間をTestにするか
Forecast Horizonはいくつか
Walk Forwardをどう行うか
何を指標にするか
を決めます。
後から評価方法を変えると、モデルに都合のよい評価へ寄せてしまう可能性があります。
Part 6では、各Projectで最初にValidation期間を取り分けます。
10. Simple Baselineから始める
最初のモデルはPersistenceです。
y_hat(t+1) = y(t)
これより良くない複雑なモデルなら、複雑にする意味がありません。
Baselineを先に作ることで、
ARIMAを作れた
ではなく、
ARIMAは単純なPersistenceよりどのくらい改善したか
と考えられます。
11. NotebookでProject Templateを確認する
JupyterLabで、
notebooks/27_project_process.ipynb
を開きます。
このNotebookでは、Part 6で繰り返すProject Templateを表にして確認します。
Problem
↓
Validation Split
↓
Internal Test Harness
↓
Persistence
↓
Analysis
↓
Candidate Models
↓
Selection
↓
Final Validation
↓
Forecast
少し変えてみる
例えば「モデルを検証する」の前に、どんな工程が必要か自分で1つ追加してみます。
答えは1つではありません。
Data Quality Check や Feature / Transform Check を入れても構いません。
Lesson 29 確認問題
問題
なぜ最終ValidationデータをGrid Search中に使ってはいけないのでしょうか。
答えと解説を見る
最終Validationを見ながらパラメータを選ぶと、そのValidationに合うようモデルを調整したことになります。
つまり、最終Validationが事実上の学習データへ変わってしまいます。
候補の比較はDevelopment期間内で行い、Final Validationは最後に一度だけ使うのが基本です。
Lesson 30 ― Project: Monthly Armed Robberies in Boston
学習目標
このLessonでは、Bostonの月間armed robberiesを使って、初めてProject全体を通します。
- 118件の月次データを読み込む
- 最後の12か月をValidationへ分離する
- Persistenceを作る
- Trendや分散の変化を見る
- 小さなARIMA候補集合を比較する
- 未使用Validationで最終候補を確認する
12. 問題を定義する
データは1966年1月から1975年10月までの月間件数です。
Month Robberies
1966-01 41
1966-02 39
1966-03 50
...
ここでは、
過去の月間件数から、次の1か月の件数を予測する
問題として扱います。
最終12か月はValidationとして別にします。
Development: 106 observations
Validation : 12 observations
13. Test Harnessを固定する
Validationを除いたDevelopmentの中でも、候補モデル比較用の内部Testを作ります。
Development
┌────────────────────┬────────────┐
│ Internal Train │ Internal │
│ │ Test │
└────────────────────┴────────────┘
Validationはさらに未来側
NotebookではDevelopment末尾12件を内部Testにしています。
評価方法は、Part 4と同じWalk Forwardです。
14. Persistenceを確認する
まずBaselineを作ります。
次の月 = 今月と同じ
このProjectでは、Persistenceでもある程度追従できますが、大きな増減には遅れます。
モデルを複雑にするなら、このBaselineを明確に上回れるかを見ます。
15. データを分析する
折れ線グラフを見ると、後半ほど値が大きくなっています。
単純に一定平均の周りで揺れている系列ではありません。
見るポイントは次です。
長期的なLevelの上昇
変動幅の変化
差分後の系列
ACF / PACF
原書ではBox-Cox変換も検討します。
今回のNotebookでは、まず変換を増やしすぎず、d=1を含む小さなARIMA候補でProjectの流れを確認します。
16. ARIMA候補を比較する
教材では次の小さな候補集合を使います。
orders = [
(0, 1, 1),
(0, 1, 2),
(1, 1, 0),
(1, 1, 1),
(2, 1, 0),
]
これは「この5個が正解」という意味ではありません。
Part 5で学んだように、ACF / PACFや差分の状態を見て候補を作り、同じ内部Testで比べる練習です。
教材作成時の小さな候補比較では、ARIMA(1,1,0)が内部RMSEで最も小さくなりました。
ただし原書では、Box-Cox変換なども含めて別の候補を検討しています。
そのため、教材の最小候補で得たorderと原書の最終設定が同じになる必要はありません。
17. 最終Validationで確認する
候補を決めたあと、初めて最後の12か月へ適用します。
教材作成時のARIMA(1,1,0)では、Validationでおおむね次の値になりました。
RMSE ≈ 55.4
MAE ≈ 43.4
ここで初めて、
モデル選択に使っていない未来期間でも性能が保たれたか
を確認します。
18. NotebookでBoston Projectを通す
notebooks/28_boston_robberies.ipynb
を開きます。
Notebookでは、
Load
↓
Validation Split
↓
Plot
↓
Persistence
↓
Candidate ARIMA
↓
Internal Evaluation
↓
Final Validation
↓
Next Forecast
を上から順番に実行します。
少し変えてみる
候補に(2,1,1)を追加して、順位が変わるか確認してください。
最終Validationを見てから追加するのではなく、Development内の評価だけで判断します。
Lesson 30 確認問題
問題
内部TestとFinal Validationを分ける理由を説明してください。
答えと解説を見る
内部Testは候補モデルの選択・調整に使うためです。
Final Validationは、その選択プロセスに使っていない未来データで最終候補を確認するために残します。
役割が違うため、同じデータを両方へ使わないことが大切です。
Lesson 31 ― Project: Annual Water Usage in Baltimore
学習目標
次は年次データです。
- 月次と年次で同じProject Templateを使う
- 79件という比較的小さな系列を扱う
- 10年をValidationへ残す
- Trendを差分で扱う
- ARIMA候補をPersistenceと比較する
19. 同じ手順でも時間間隔が違う
Baltimoreのwater usageは1885年から1963年までの年次データです。
Year Water
1885 356
1886 386
1887 397
...
件数は79件です。
最後の10年をValidationとして残します。
Development: 69 observations
Validation : 10 observations
月次データと比べると件数は少ないですが、Projectの流れは同じです。
20. まずグラフを見る
年次water usageは、全期間を通して同じ平均の周りに揺れているわけではありません。
長期的な増加傾向が見えます。
そのため候補ではd=1を中心に考えます。
元系列
↓
1階差分
↓
長期Trendの影響を弱める
Part 3のTrendとStationarityが、ここでそのまま使われます。
21. PersistenceとARIMAを同じ条件で比較する
教材では次の候補を試します。
orders = [
(1, 1, 0),
(2, 1, 0),
(0, 1, 1),
(1, 1, 1),
]
Development末尾10件で比較したところ、教材作成時はARIMA(2,1,0)が最小RMSEになりました。
これは原書で最終的に検討されるorderとも一致します。
内部Testでは、
Persistence RMSE ≈ 17.63
ARIMA RMSE ≈ 17.11
と、差は大きくありません。
このような場合、
ARIMAだから大幅に良い
とは言えません。
複雑さに見合う改善かを考える必要があります。
22. Validationで確認する
ARIMA(2,1,0)を最後の10年へ適用すると、教材作成時にはおおむね、
RMSE ≈ 16.97
MAE ≈ 12.86
となりました。
候補選択時と極端に違う性能になっていないことを確認します。
23. NotebookでWater Usage Projectを通す
notebooks/29_baltimore_water.ipynb
を開きます。
同じ関数を使いながら、CSV列名とValidationサイズ、候補orderだけを変えています。
この共通化がPart 6の重要なところです。
少し変えてみる
test_size=8に変えた場合、候補順位が変わるか確認してください。
Test Harnessを変えるとランキングが変わることがあります。
だからこそ、評価条件はモデルを比較する前に決めておきます。
Lesson 31 確認問題
問題
ARIMAのRMSEがPersistenceより少し小さかった場合、それだけでARIMAを採用してよいでしょうか。
答えと解説を見る
必ずしもそうではありません。
改善幅、モデルの複雑さ、運用のしやすさ、残差、Validationでの安定性などを合わせて考えます。
Baselineとの差がごく小さいなら、単純なモデルの方が実務上使いやすい場合もあります。
Lesson 32 ― Project: Monthly Sales of French Champagne
学習目標
最後のProjectは、強い季節性を持つ月次系列です。
- 12か月周期をグラフから確認する
- 最後の12か月をValidationへ残す
- Seasonal Differenceを使う
- 季節差分後の系列へARIMAを当てる
- 季節性があるProjectでBaselineとの違いを見る
24. Champagne Salesは季節性が強い
データは1964年1月から1972年9月までの月次salesです。
Month Sales
1964-01 2815
1964-02 2672
1964-03 2755
...
105件あり、最後の12か月をValidationへ残します。
Development: 93 observations
Validation : 12 observations
グラフを見ると、年ごとに似たピークと谷が繰り返されます。
単純な1階差分だけではなく、
y(t) - y(t-12)
という12か月Seasonal Differenceが有効そうだと考えられます。
25. Seasonal Differenceをモデルの外側で行う
Notebookでは、元系列を直接ARIMAへ渡すのではなく、各予測時点で、
現在までのhistory
↓
12か月季節差分
↓
ARIMAへfit
↓
差分値を予測
↓
12か月前の元値を加える
↓
元尺度へ戻す
という流れにしています。
これはPart 3で学んだSeasonalityと、Part 5で学んだARIMAを組み合わせた形です。
26. Persistenceとの差が大きいケース
Champagne Salesでは、直前値をそのまま使うPersistenceは強い年周期を捉えられません。
教材の内部Testでは、
Persistence RMSE ≈ 3374
Seasonal Difference + ARIMA RMSE ≈ 825
となり、差が大きく出ました。
これは、
データ構造に合った前処理とモデル化が効く
例として分かりやすい結果です。
27. 小さな候補集合を比較する
教材では次を比較します。
orders = [
(0, 0, 1),
(1, 0, 0),
(1, 0, 1),
(2, 0, 0),
(0, 0, 2),
]
ここでd=0なのは、ARIMAへ渡す前に12か月季節差分をすでに行っているためです。
教材作成時のこの小さな候補集合では、ARIMA(2,0,0)が最小RMSEになりました。
原書では別の探索・bias correctionなども行うため、最終orderは異なります。
ここで学びたいのは数字の一致ではなく、
季節性を見つける
↓
変換する
↓
候補を同条件で比較する
↓
Validationする
という流れです。
28. Final Validation
教材のARIMA(2,0,0)と12か月季節差分を最後の12か月へ適用した場合、作成時にはおおむね、
RMSE ≈ 398.3
MAE ≈ 338.9
となりました。
内部TestよりValidationの方が良いこともありますし、逆もあります。
重要なのは、最終Validationを見てから候補を選び直さないことです。
29. NotebookでChampagne Projectを通す
notebooks/30_champagne.ipynb
を開きます。
ここでは他の2プロジェクトと同じProject Templateを使いながら、seasonal_period=12だけを追加します。
少し変えてみる
seasonal_period=Noneにして同じ候補を評価し、RMSEがどう変わるか確認してください。
季節差分の有無が、予測性能へどれくらい効くか比較できます。
Lesson 32 確認問題
問題
Champagne Projectで、ARIMAのd=0候補を試しているのにTrendやSeasonalityを無視しているわけではないのはなぜでしょうか。
答えと解説を見る
ARIMAへ渡す前に12か月季節差分を行っているからです。
つまり、差分処理をARIMAの内部パラメータdだけに任せず、外側で季節周期12の差分を明示的に行っています。
そのため、季節差分後の系列に対してはd=0のARIMA候補を比較できます。
30. 3つのProjectを比較する
同じProject Templateを使っても、データ構造によって重要なポイントが変わりました。
| Project | 主な特徴 | Validation | モデル化のポイント |
|---|---|---|---|
| Boston Robberies | 月次・Level上昇 | 12か月 | 差分とARIMA候補 |
| Baltimore Water | 年次・長期Trend | 10年 | 1階差分、少数データ |
| Champagne Sales | 月次・強い季節性 | 12か月 | 12か月季節差分 |
共通なのは次です。
Problem
↓
Validation Split
↓
Test Harness
↓
Persistence
↓
Analysis
↓
Candidate Models
↓
Selection
↓
Final Validation
変わるのは、
どの差分を使うか
どの候補を試すか
どの期間をValidationへ残すか
です。
31. Part 6で押さえておきたいこと
1. Project Templateを先に作る
モデルを試すたびに評価方法を変えないようにします。
2. Final Validationは最後まで取っておく
モデル候補を選ぶためには使いません。
3. Persistenceは毎回作る
複雑なモデルが本当に改善したか判断する基準になります。
4. Data Analysisはモデル候補を考えるために行う
きれいなグラフを作るだけではありません。
Trend → differencing?
Seasonality → seasonal difference?
ACF / PACF → p / q候補?
と、次の作業へつなげます。
5. 数字の最小値だけで終わらない
RMSEだけでなく、Validation、残差、モデルの複雑さも見ます。
6. 同じ型を繰り返すと実務へ転用しやすい
データが変わっても、Projectの骨格は再利用できます。
32. Part 6の全体像
Part 6をまとめると、次の流れです。
Part 1では、
予測問題の作り方
を学びました。
Part 2では、
データを整える方法
を学びました。
Part 3では、
時系列の構造
を調べました。
Part 4では、
モデル評価
を作りました。
Part 5では、
予測モデルを作り、選び、保存する
ところまで進みました。
Part 6では、それらをすべて使って、
1つのProjectを最後まで通す
ことができました。
33. 次はPart 7 ― Conclusions
次のPart 7では、このシリーズ全体を振り返ります。
単に復習するだけでなく、
へどう広げていくかを整理します。
Part 1〜6までで、時系列予測を学ぶための基礎となる一本の流れができました。
参考資料
本記事は、次の書籍のPart VIを参考に、現在のPython環境とDocker + JupyterLabを使ったe-learning形式へ組み直しています。
-
Jason Brownlee, Introduction to Time Series Forecasting with Python
-
Part VI: Projects
- Chapter 29: Time Series Forecast Projects
- Chapter 30: Project: Monthly Armed Robberies in Boston
- Chapter 31: Project: Annual Water Usage in Baltimore
- Chapter 32: Project: Monthly Sales of French Champagne
原書のコードは刊行当時のpandas / statsmodels APIを前提としています。
この教材では、pandas 2.2.3、statsmodels 0.14.6 のAPIに合わせて書き直しています。
また、原書ProjectではBox-Cox変換、bias correction、より広いGrid Searchなども行います。
このe-learningでは、3つのProjectを無理なく同じ環境で通せるよう、候補集合を小さくし、Project Processそのものを理解しやすい形へ整理しています。






