K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

VAR モデルの多変量予測

上級

04.8.1

VAR モデルの多変量予測

最終更新 2020-09-24 読了時間 3 分
まとめ
VAR(ベクトル自己回帰)は、複数の系列それぞれを「全系列の過去 p 期の線形結合」で表し、系列どうしの影響を同時に推定するモデルです。単変量の AR では x の過去だけで x を予測しますが、VAR なら「y の 1 期前が x に効く」という関係も係数として取り込めます。このページでは statsmodels.tsa.api.VAR に 2 系列の DataFrame を渡し、fit(2) でラグ 2 の係数を推定して forecast() で 6 か月先を同時に予測します。読み終えると、k_ar 個の直近値を予測の初期値として渡す理由と、ラグ数を select_order の AIC/BIC で選ぶ流れを説明できるようになります。

ARIMA モデル で「自分の過去 p 期で現在を回帰する」AR の考え方を先に押さえておくと、VAR がそれを複数系列に広げただけだと分かります。

2 系列を VAR モデルに適用し、相互依存を考慮した短期予測を行います。

直感 #

気温と電力需要を 12 か月記録すると、電力需要は気温の動きに 1 か月ほど遅れて追随します。電力需要だけを見て AR モデルを作るより、「先月の気温」も説明変数に入れた方が予測は良くなるはずです。VAR はこの発想を対称にしたもので、気温の式にも電力需要の過去を入れ、2 本(系列が k 個なら k 本)の回帰式を同時に推定します。ラグ p の VAR なら各式に \(k \times p\) 個の係数と定数項が入り、fit(2) で 2 系列なら 1 式あたり 5 個のパラメータを最小二乗で求めます。予測は直近 p 期の全系列の値から 1 期先を計算し、その結果を次の入力に回して多段先へ伸ばします。

Python で 2 系列を同時に予測する #

次のコードは、周期 12 か月の正弦波 x と、x を 1 か月遅らせて 0.5 倍したものにノイズを足した y を 120 か月分作り、ラグ 2 の VAR を当てはめて 6 か月先を予測します。y が x に 1 期遅れて追随する構造を仕込んでいるので、予測の破線が観測の波を自然に延長するかが見どころです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.api import VAR

rng = np.random.default_rng(27)
dates = pd.date_range("2020-01-01", periods=120, freq="M")
x = np.sin(2 * np.pi * np.arange(len(dates)) / 12)
y = 0.5 * np.roll(x, 1) + rng.normal(0, 0.2, len(dates))
df = pd.DataFrame({"x": x + rng.normal(0, 0.1, len(dates)), "y": y}, index=dates)

model = VAR(df)
results = model.fit(2)
forecast = results.forecast(df.values[-results.k_ar:], steps=6)
forecast_index = pd.date_range(dates[-1] + pd.offsets.MonthEnd(), periods=6, freq="M")
forecast_df = pd.DataFrame(forecast, index=forecast_index, columns=df.columns)

fig, ax = plt.subplots(figsize=(6.5, 3.5))
ax.plot(df.index, df["x"], label="x 観測", color="#2563eb")
ax.plot(df.index, df["y"], label="y 観測", color="#22c55e")
ax.plot(forecast_df.index, forecast_df["x"], label="x 予測", color="#f97316", linestyle="--")
ax.plot(forecast_df.index, forecast_df["y"], label="y 予測", color="#facc15", linestyle="--")
ax.set_title("VAR モデルの予測")
ax.set_xlabel("年月")
ax.set_ylabel("値")
ax.legend()
ax.grid(alpha=0.3)

fig.tight_layout()
fig.savefig("static/images/timeseries/var_forecast.svg")

VAR モデルで 2 系列を 6 か月先まで同時予測した図

実行結果の読み方 #

青い実線 x は周期 12 か月の波を描き、緑の実線 y はその半分の振幅で 1 か月遅れて追随します。オレンジと黄色の破線は 6 か月先までの予測で、x の破線が正弦波を自然に延長し、y の破線がその動きに遅れて続いていれば VAR が 2 系列の関係を学習できています。results.summary() を表示すると、y の式の L1.x の係数が 0.5 付近、x の式の L1.y の係数は 0 付近になるはずで、依存の方向が x → y だけであることが係数から読めます。

何が起きているか(ステップで見る) #

コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。

見るポイント:φ が 1 に近いほど前の値を引きずり、波がゆっくりになる。負なら 1 期ごとに符号が反転しやすい。

使いどころと落とし穴 #

VAR が向くのは、GDP と金利、気温と電力需要のように系列どうしが互いに影響し合い、どちらを目的変数にするかを決めにくいデータです。系列数 k とラグ p を増やすと係数は \(k^2 p\) 個で増えるので、5 系列・ラグ 12 なら 300 個の係数を推定することになり、数百点のデータでは過学習します。ラグは select_order の AIC か BIC で選び、BIC の方が小さいラグを選ぶ傾向があります。VAR は各系列が定常であることを前提にしているため、トレンドや単位根がある系列は ADF 検定で確認し、差分を取ってから当てはめます。どの系列がどの系列に効いているかを統計的に確かめたいときは、次の グレンジャー因果性検定 で係数の有意性を検定します。