Pythonで学ぶ時系列予測 ― e-learningで基礎から実践まで Part 4
はじめに
Part 3では、時系列の中にどのような時間構造があるのかを見てきました。
最後に確認した流れは、次のようなものでした。
ここまでで、
この系列はどんな性質を持っているのか
を調べる準備はできました。
Part 4では、次の段階へ進みます。
テーマは Evaluate Models ― 予測モデルの評価 です。
予測モデルを作ると、数字として予測値は出せます。
ただし、予測値が出たことと、そのモデルが役に立つことは同じではありません。
例えば、
予測値 = 25.4
と表示されても、それだけでは良い予測かどうか分かりません。
比較するには、少なくとも次のことを決める必要があります。
- どこまでを学習期間にするか
- どこからを評価期間にするか
- 時系列の順序をどう守るか
- 誤差を何で測るか
- 単純な予測より良いか
- 残差にまだ規則性が残っていないか
Part 4では、この評価の土台を順番に作ります。
今回もPart 3と同じく、
説明を読む
↓
Notebookで試す
↓
結果を見る
↓
条件を少し変える
↓
確認問題
という流れで進めます。
1. Part 3からPart 4へ
Part 3では、時系列をモデルへ入れる前に、TrendやSeasonality、Stationarityなどを確認しました。
Part 4では、その知識を使いながら、
予測モデルをどのような条件で試し、何をもって良いと判断するか
を考えます。
Mermaidで表すと、Part 4の中心は次の流れです。
さらに原書の最後では、同じ時系列を別の予測問題へ組み替える Reframing も扱います。
Part 4の終わりでは、
時系列
↓
時間順に評価する
↓
誤差を計算する
↓
基準モデルと比べる
↓
残差を調べる
↓
必要なら問題設定を組み替える
ところまで進みます。
2. Part 4 ― Evaluate Models
原書のPart 4はChapter 16からChapter 20までです。
このe-learningでも5つのLessonとして進めます。
| Lesson | 原書Chapter | 内容 | 主に使うもの |
|---|---|---|---|
| Lesson 16 | 16 | Backtest Forecast Models | Train/Test / Walk Forward |
| Lesson 17 | 17 | Forecasting Performance Measures | Bias / MAE / MSE / RMSE |
| Lesson 18 | 18 | Persistence Model | Naive Baseline |
| Lesson 19 | 19 | Residual Forecast Errors | Line / Histogram / Q-Q / ACF |
| Lesson 20 | 20 | Reframe Forecasting Problems | Regression / Classification / Horizon |
Part 3までは、主にデータ側を見てきました。
Part 4では、
データだけでなく
評価方法そのものが正しいか
を見るようになります。
3. Part 4のゴール
Part 4を終えた時点で、次のことができれば十分です。
- 時系列を時間順にTrain/Testへ分けられる
- ランダムシャッフルが危険な理由を説明できる
- Walk Forward Validationの流れを説明できる
- Expanding Windowと固定Testの関係を理解できる
- Forecast Errorの符号を説明できる
- Forecast Biasを計算できる
- MAE、MSE、RMSEの違いを説明できる
- Persistenceをベースラインとして実装できる
- 複雑なモデルはベースラインと比較すべきだと理解できる
- 残差を時系列として確認できる
- Histogram、Q-Q Plot、ACFで残差を調べられる
- 残差がWhite Noiseに近いか考えられる
- 同じ時系列をOne-step、Multi-step、分類問題へ組み替えられる
- Forecast Horizonを変えると問題そのものが変わると理解できる
Part 4では、まだARIMAそのものを中心には扱いません。
まず、どの予測モデルにも共通する評価方法を固めるPartです。
4. 学習環境はPart 3をそのまま使う
Part 4でもDocker + JupyterLabをそのまま使います。
Windowsのブラウザー
↓
JupyterLab
↓
Notebook
↓
Python
↓
pandas / NumPy / Matplotlib / statsmodels
Part 3までのNotebookは残し、新しいNotebookを後ろへ追加します。
notebooks/
├── 01_environment.ipynb
├── 02_load_explore.ipynb
├── 03_feature_engineering.ipynb
├── 04_visualization.ipynb
├── 05_resampling_interpolation.ipynb
├── 06_power_transforms.ipynb
├── 07_moving_average.ipynb
├── 08_white_noise.ipynb
├── 09_random_walk.ipynb
├── 10_decomposition.ipynb
├── 11_trend.ipynb
├── 12_seasonality.ipynb
├── 13_stationarity.ipynb
├── 14_backtesting.ipynb
├── 15_performance_measures.ipynb
├── 16_persistence.ipynb
├── 17_residual_analysis.ipynb
└── 18_reframing.ipynb
Part 1からPart 4までを、1つの教材プロジェクトとして続けて使います。
起動方法は変わりません。
docker compose up
初回や依存関係を作り直す場合は、
docker compose up --build
を使います。
5. Part 4で使うデータ
Part 4では、評価方法そのものを見やすくするため、教材用の日次時系列を追加します。
data/part4_evaluation.csv
中身は次の2列です。
timestamp,value
2026-01-01,30.000
2026-01-02,31.255
2026-01-03,32.585
...
このデータには教材として、
- 緩やかなTrend
- 7日周期
- 直前値の影響を受けるNoise
を入れています。
実在の観測データではありません。
外部サイトに依存せず、BacktestやPersistence、残差解析を同じ条件で何度でも試せるようにした人工データです。
再生成する場合は、
python src/make_part4_data.py
を実行します。
Lesson 16 ― Backtest Forecast Models
学習目標
このLessonでは、次の内容を確認します。
- 時間順のTrain/Test分割
- なぜ時系列をランダムシャッフルしないのか
- Backtestとは何か
- Walk Forward Validation
- Expanding Window
- 評価期間をそろえる意味
6.1 予測モデルは未来で試す
通常の表形式データでは、Train/Testをランダムに分けることがあります。
しかし時系列では、時間に意味があります。
例えば2026年1月から6月までのデータがある場合、自然な評価は次のようになります。
過去 ------------------------------------→ 未来
Train | Test
1月 2月 3月 4月 | 5月 6月
未来側でモデルを評価することで、実際の予測に近い条件になります。
時系列で無条件にランダムシャッフルすると、未来のデータがTrainへ入り、過去のデータがTestへ入ることがあります。
それでは、
未来を知った状態で過去を当てる
ような評価になりかねません。
6.2 Notebookで時間順に分割する
14_backtesting.ipynb を開きます。
frame = pd.read_csv(
ROOT / "data" / "part4_evaluation.csv",
parse_dates=["timestamp"],
).set_index("timestamp")
series = frame["value"]
後半25%をTestへ回します。
train, test = chronological_train_test_split(
series,
test_size=0.25,
)
この関数ではランダムシャッフルを行いません。
先頭 ----------------------- 分割点 ----------------------- 末尾
Train Test
という順序を保ちます。
6.3 1回のTrain/Testだけで十分か
1回だけのTrain/Test分割は分かりやすい方法です。
ただし、分割点をどこに置くかで評価結果が変わることがあります。
例えば、
Train ---------------------- Test
だけでなく、
Train -------- Test
Train ------------- Test
Train ------------------ Test
のように複数の時点で繰り返し評価すると、モデルの挙動をより詳しく確認できます。
これがWalk Forward Validationにつながります。
6.4 Walk Forward Validation
時系列では、時間を前へ進めながら、予測と観測を繰り返す方法がよく使われます。
過去データで学習
↓
次の1時刻を予測
↓
実測値を確認
↓
その実測値を履歴へ追加
↓
次の時刻を予測
Part 4では、Trainを先頭から広げていく Expanding Window を使います。
1回目 [ Train ] [Test]
2回目 [ Train ] [Test]
3回目 [ Train ] [Test]
Notebookでは、分割Indexを作って確認します。
splits = expanding_window_splits(
n_obs=len(series),
initial_train_size=120,
horizon=1,
step=1,
)
6.5 情報漏洩を防ぐ順序
Walk Forwardで重要なのは、実測値を履歴へ追加するタイミングです。
正しい順序は、
履歴
↓
予測
↓
実測値を見る
↓
履歴へ追加
です。
予測する前にその時刻の実測値を履歴へ入れてはいけません。
これは単純なPersistenceでも、ARIMAでも、機械学習でも同じです。
条件を変えてみる
Notebookの、
initial_train_size=120
を、
90
120
150
へ変えてみます。
評価に使える期間がどう変わるか確認します。
確認問題
時系列データを通常の train_test_split(..., shuffle=True) でランダム分割すると、なぜ問題になることがあるでしょうか。
答えと解説を見る
未来側の観測値がTrainへ入り、過去側の観測値がTestへ入る可能性があるためです。
時系列予測では、実際には利用できない未来情報を使って学習すると、性能を過大評価する危険があります。
基本は、過去で学習して未来で評価する順序を保ちます。
Lesson 17 ― Forecasting Performance Measures
学習目標
- Forecast Errorを計算する
- Forecast Biasを理解する
- MAEを計算する
- MSEを計算する
- RMSEを計算する
- それぞれの指標の特徴を説明する
7.1 Forecast Error
実測値を y、予測値を ŷ とすると、この教材ではForecast Errorを、
error = actual - forecast
とします。
例えば、
actual = 12
forecast = 10
なら、
error = 2
です。
逆に、
actual = 10
forecast = 12
なら、
error = -2
になります。
符号には、予測がどちら側へ外れたかという情報があります。
7.2 Forecast Bias
Forecast Errorを平均すると、予測の偏りを見ることができます。
Bias = mean(error)
Biasが大きく正なら、平均的に予測が小さめです。
Biasが大きく負なら、平均的に予測が大きめです。
ただし、正負の誤差は互いに打ち消し合います。
そのためBiasだけで予測精度を評価することはできません。
7.3 MAE
MAEは Mean Absolute Error です。
MAE = mean(|error|)
誤差の絶対値を平均します。
特徴は分かりやすく、元データと同じ単位で読めることです。
例えば水位データがmなら、MAEもmとして考えられます。
7.4 MSE
MSEは Mean Squared Error です。
MSE = mean(error²)
大きな誤差を2乗するので、大きな外れをより強く評価します。
一方で単位も2乗されるため、そのまま直感的に読むのは少し難しくなります。
7.5 RMSE
RMSEはMSEの平方根です。
RMSE = sqrt(MSE)
MSEと同じように大きな誤差を重く扱いつつ、元データと同じ単位へ戻ります。
時系列予測でよく利用される指標の一つです。
7.6 Notebookで計算する
15_performance_measures.ipynb では、まず小さな数値で確認します。
actual = np.array([10.0, 12.0, 13.0, 15.0])
forecast = np.array([9.0, 13.0, 12.0, 16.0])
誤差は、
errors = forecast_errors(actual, forecast)
で計算します。
続いて、
metrics = forecast_metrics(actual, forecast)
から、
Bias
MAE
MSE
RMSE
をまとめて確認します。
小さなデータで式と結果を対応させてから、Part 4の評価データへ適用します。
7.7 指標は1つだけ見ればよいか
必ずしもそうではありません。
例えば、
- Biasは方向の偏り
- MAEは平均的な誤差の大きさ
- RMSEは大きな誤差を強く意識した値
として見ることができます。
また、異なるスケールのデータ間でMAEやRMSEを単純比較すると、値の大きい系列が不利になります。
指標は問題の目的と単位を考えて選びます。
条件を変えてみる
予測値へ一律に、
forecast + 1.0
を加えて、Bias、MAE、MSE、RMSEがどう変化するか確認します。
確認問題
MAEとRMSEの両方が小さいモデルAと、MAEは同程度でもRMSEだけ大きいモデルBがあるとします。モデルBでは何が起きている可能性があるでしょうか。
答えと解説を見る
モデルBでは、一部に大きな誤差が発生している可能性があります。
RMSEは誤差を2乗してから平均するため、大きな誤差の影響を受けやすい指標です。
平均的には似ていても、重大な外れを避けたい用途ではRMSEの差が重要になることがあります。
Lesson 18 ― Persistence Model
学習目標
- Persistenceとは何か説明する
- ベースラインが必要な理由を理解する
- PersistenceをPythonで実装する
- Test期間だけで評価する
- 複雑なモデルとの比較基準を作る
8.1 複雑なモデルを作る前に基準を置く
時系列予測では、ARIMAや機械学習を作る前に、単純な予測を基準として用意します。
最も分かりやすいものがPersistenceです。
考え方は、
次の値は現在値と同じ
です。
数式で書けば、
ŷ(t+1) = y(t)
です。
非常に単純ですが、ゆっくり変化する系列では意外に強い基準になることがあります。
8.2 なぜPersistenceと比べるのか
例えば、高度な予測モデルを作って、
RMSE = 2.8
だったとします。
これだけでは良いかどうか判断できません。
もしPersistenceが、
RMSE = 2.1
なら、高度なモデルの方が悪いことになります。
逆に、
Persistence RMSE = 4.0
Model RMSE = 2.1
なら、モデルによって改善したと判断しやすくなります。
つまり、
モデルのRMSE
ではなく、
単純な基準と比べて、どれだけ改善したか
を見るわけです。
8.3 NotebookでPersistenceを作る
16_persistence.ipynb を開きます。
persistence = persistence_forecast(series)
内部では、
series.shift(1)
を使っています。
t-1 の実測値 → t の予測値
という対応です。
8.4 Test期間だけで評価する
ベースラインも、比較するモデルと同じTest期間で評価します。
train, test = chronological_train_test_split(
series,
test_size=0.25,
)
Test先頭の予測には、Trainの最後の観測値が必要です。
Notebookでは、Train最後の1行とTestをつないでから shift(1) を適用します。
これは地味ですが、時系列評価では重要な部分です。
8.5 Seasonal Naiveもベースラインになる
周期性が強い場合は、
次の値 = 1周期前の値
を基準にすることもできます。
日次データで週周期なら、
seasonal_naive = series.shift(7)
です。
単純なベースラインも、データの構造に合わせて選びます。
Part 3でSeasonalityを調べたことが、ここにつながります。
確認問題
高度なモデルのRMSEが 3.2、PersistenceのRMSEが 2.7 だった場合、高度なモデルを採用してよいでしょうか。
答えと解説を見る
RMSEだけを見る限り、Persistenceの方が良い結果です。
高度なモデルを採用する前に、なぜ単純な基準を超えられなかったのかを確認する必要があります。
複雑なモデルだから優れているとは限りません。
Lesson 19 ― Visualize Residual Forecast Errors
学習目標
- 予測残差を作る
- 残差の時系列グラフを見る
- 残差の平均と分布を見る
- Histogramを見る
- Q-Q Plotを見る
- 残差の自己相関を見る
- White Noiseとの関係を思い出す
9.1 予測値を出して終わりではない
モデル評価では、誤差の値だけでなく、誤差そのものを時系列として見ます。
ここでは、
Residual = Actual - Forecast
として確認します。
理想的には、モデルが利用できる構造を取り切ったあと、残差には分かりやすい構造が残らないことが望まれます。
Part 3で学んだWhite Noiseを思い出します。
モデルで説明できる構造
↓
予測へ利用
↓
残ったもの
↓
できればWhite Noiseに近い
9.2 残差のLine Plot
まず時間順に残差を描きます。
確認するのは、
- 0付近を中心に動くか
- 時間とともに増加・減少していないか
- 途中でばらつきが大きく変わらないか
- 同じ形が周期的に繰り返していないか
です。
Part 3のTrend、Seasonality、Stationarityが、ここでも使われます。
9.3 Summary Statistics
残差の平均が0から大きくずれていれば、Biasが残っています。
print(residual.describe())
だけでも、
mean
std
min
max
を確認できます。
ただし、数値だけでなくグラフも一緒に見ます。
9.4 Histogram
Histogramでは残差の分布を見ます。
residual.hist(bins=12)
0付近を中心に左右へ広がっているか、極端な偏りや外れがないかを確認します。
9.5 Q-Q Plot
Q-Q Plotは、残差の分布が正規分布からどの程度離れているかを見る一つの方法です。
qqplot(residual, line="s")
点が基準線から大きく外れている場合は、裾の重さや歪みなどが考えられます。
予測残差が必ず正規分布でなければならないわけではありません。
ここでは分布の特徴を確認する図として使います。
9.6 残差のAutocorrelation
残差に自己相関が残っている場合、モデルがまだ利用できる時間構造を取り切れていない可能性があります。
plot_acf(
residual,
lags=25,
zero=False,
)
例えばLag 7に強い相関が残っているなら、週周期が予測モデルに十分入っていないかもしれません。
ここで、Part 3のWhite NoiseとACFの話がそのままつながります。
9.7 Notebookでまとめて確認する
17_residual_analysis.ipynb では、PersistenceのWalk Forward結果から残差を作り、
Line Plot
Histogram
Q-Q Plot
ACF
を順番に表示します。
一つの図だけで「良い残差」と判断しないことがポイントです。
条件を変えてみる
Persistenceではなく、7日前の値を使うSeasonal Naiveの残差を作り、ACFを比較してみます。
週周期が残差から弱まるか確認します。
確認問題
残差のACFでLag 7に大きな相関が残っていた場合、どのように考えられるでしょうか。
答えと解説を見る
7時刻周期の構造がモデルに十分取り込まれていない可能性があります。
日次データなら週周期のSeasonalityが残っていることも考えられます。
残差がWhite Noiseに近づいているかという視点で、モデルや特徴量を見直します。
Lesson 20 ― Reframe Time Series Forecasting Problems
学習目標
- 同じ時系列でも問題設定を変えられると理解する
- One-step Regressionを作る
- Multi-step Regressionを作る
- Classificationへ組み替える
- Forecast Horizonの違いを考える
10.1 「何を予測するか」を組み替える
時系列予測の問題は1通りではありません。
同じデータでも、目的によって違う形へ変換できます。
例えば、
数値を当てたい
なら回帰です。
上がるか下がるか知りたい
なら分類にできます。
明日だけ知りたい
のと、
1週間分まとめて知りたい
のでも問題設定が違います。
10.2 One-step Regression
Part 1で学んだSliding Windowを思い出します。
y(t-3), y(t-2), y(t-1)
↓
y(t)
Notebookでは、
one_step = make_supervised_frame(
series,
n_lags=3,
horizon=1,
)
とします。
生成される列は、
lag_3
lag_2
lag_1
target_t
です。
10.3 Multi-step Regression
今度は1時刻だけでなく、複数の未来を同時に作ります。
y(t-3), y(t-2), y(t-1)
↓
y(t), y(t+1), y(t+2)
multi_step = make_supervised_frame(
series,
n_lags=3,
horizon=3,
)
となります。
Forecast Horizonを伸ばすほど、一般には予測は難しくなります。
10.4 Classificationへ変える
数値そのものを当てず、
次の値が上昇するか
を予測することもできます。
例えば、
上昇 = 1
それ以外 = 0
です。
Notebookでは、
classification = make_direction_classification_frame(
series,
n_lags=3,
)
を使います。
目的変数は target_up です。
同じ元データでも、回帰と分類では評価指標も変わります。
10.5 Forecast Horizonを先に決める
モデルを選ぶ前に、どこまで先を予測するか決めます。
例えば10分データなら、
1 step = 10分先
6 steps = 60分先
18 steps = 3時間先
です。
同じモデルでも、10分先と3時間先では難しさが違います。
さらに、
3時間後だけを予測する
のと、
10分後から3時間後まで18個を予測する
のも別の問題です。
予測モデルの比較は、同じForecast Horizonで行う必要があります。
条件を変えてみる
Notebookで、
n_lags=7, horizon=1
と、
n_lags=28, horizon=7
を作ります。
入力列が増え、利用できる学習行が減ることを確認します。
確認問題
「1時間後の値を予測するモデルA」と「10分後の値を予測するモデルB」のRMSEを、そのまま比べてどちらが良いモデルか判断してよいでしょうか。
答えと解説を見る
そのまま比較するのは適切ではありません。
Forecast Horizonが違うため、解いている問題の難しさや目的が違います。
モデル比較では、基本的に同じ予測対象、同じForecast Horizon、同じTest期間をそろえます。
11. Part 4でつながったこと
Part 4の内容をまとめると、次の流れになります。
時間順Train / Test
↓
Walk Forward Validation
↓
Forecast Error
↓
Bias / MAE / MSE / RMSE
↓
Persistenceで基準を作る
↓
残差を調べる
↓
必要なら予測問題をReframeする
ここで大切なのは、誤差指標を1個計算することだけではありません。
予測モデルを評価するときは、
評価期間
予測方法
Forecast Horizon
ベースライン
誤差指標
残差
を一つのセットとして考えます。
12. Part 4で覚えておきたいポイント
1. 時系列では時間順を守る
未来情報がTrainへ入らないようにします。
2. Walk Forwardで実運用に近づける
予測→観測→履歴更新、という順序を守ります。
3. 誤差指標には役割の違いがある
Bias、MAE、MSE、RMSEは同じものを見ているわけではありません。
4. Persistenceを必ず意識する
複雑なモデルを作る前に、単純な基準を超えられるか確認します。
5. 残差に構造が残っていないか見る
残差がWhite Noiseに近いかを、Line Plot、Histogram、Q-Q Plot、ACFなどで確認します。
6. 問題設定をそろえて比較する
Forecast HorizonやTest期間が違うモデルを、単純にRMSEだけで比べないようにします。
13. Part 4の全体像
Part 1では、
何を入力にして、何を未来として予測するか
を考えました。
Part 2では、
予測へ使えるデータへ整える
ことを学びました。
Part 3では、
時系列の中にどんな構造があるか
を確認しました。
Part 4では、
その予測をどう正しく評価するか
を整理しました。
次は、いよいよ具体的なForecast Modelへ進みます。
14. 次はPart 5 ― Forecast Models
Part 5では、古典的な時系列予測モデルを実際に作ります。
原書では、Box-Jenkins Methodから始まり、Autoregression、Moving Average、ARIMA、ACF/PACFなどへ進みます。
流れのイメージは次のようになります。
Part 4で評価方法を先に固めたので、Part 5では、
ARIMAを動かしたらRMSEが出た
で終わらず、
Persistenceより良いか
Walk Forwardでどうか
残差に自己相関が残っていないか
まで確認できるようになります。
参考資料
本記事は、次の書籍のPart 4を参考に、現在のPython環境とDocker + JupyterLabを使ったe-learning形式へ組み直しています。
-
Jason Brownlee, Introduction to Time Series Forecasting with Python, Part IV: Evaluate Models
- Chapter 16: Backtest Forecast Models
- Chapter 17: Forecasting Performance Measures
- Chapter 18: Persistence Model for Forecasting
- Chapter 19: Visualize Residual Forecast Errors
- Chapter 20: Reframe Time Series Forecasting Problems
原書のコードは刊行当時のPythonライブラリを前提としている箇所があります。
この教材ではPart 1〜Part 3の構成を引き継ぎ、現在のPython環境で動かしやすい形へ整理しています。










