Mímisbrunnr知恵の泉

← 時系列分析 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:定常性と自己相関 | 数理:確率過程(マルコフ連鎖・ポアソン過程)(統計)

要点(BLUF)

1. AR(pp):過去の自分で説明する

自己回帰モデル AR(pp) は、現在値を過去 pp 期の自分自身の線形結合+ホワイトノイズで表します。

yt=c+ϕ1yt1+ϕ2yt2++ϕpytp+εt,εtWN(0,σ2)y_t = c + \phi_1 y_{t-1} + \phi_2 y_{t-2} + \cdots + \phi_p y_{t-p} + \varepsilon_t,\qquad \varepsilon_t \sim \mathrm{WN}(0,\sigma^2)

ラグ演算子 LLLyt=yt1Ly_t=y_{t-1})を使うと、左辺をひとつの多項式にまとめられます。

ϕ(L)yt=c+εt,ϕ(L)=1ϕ1Lϕ2L2ϕpLp\phi(L)\,y_t = c + \varepsilon_t,\qquad \phi(L)=1-\phi_1 L-\phi_2 L^2-\cdots-\phi_p L^p

定常性条件:AR(pp) が(弱)定常になるのは、**特性方程式 ϕ(z)=0\phi(z)=0 の根がすべて単位円の外(z>1|z|>1)**にあるときです。AR(1) なら ϕ(z)=1ϕz=0z=1/ϕ\phi(z)=1-\phi z=0\Rightarrow z=1/\phi なので、z>1    ϕ<1|z|>1\iff|\phi|<1ϕ=1\phi=1 ちょうどがランダムウォーク(単位根・非定常)でした(ランダムウォークと単位根)。直観は「過去への引きずられ方 ϕ\phi が弱すぎず(1<ϕ<1-1<\phi<1)なら、ショックの影響が時間とともに減衰し平均へ戻る」。AR(1) の自己相関は ρk=ϕk\rho_k=\phi^k と幾何減衰し、PACF はラグ1で切れます(定常性と自己相関 で実証済み)。

コード①:AR(2) の係数を復元する

真の係数 ϕ1=0.5, ϕ2=0.3\phi_1=0.5,\ \phi_2=-0.3 を仕込んだ AR(2) を生成し、statsmodelsARIMA(order=(2,0,0))d=0d=0 なので純粋な AR(2))で係数を推定します。推定値が真値に一致するか、また特性根が単位円の外(定常)かを数値で見ます。

import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.arima_process import arma_generate_sample

# 真の AR(2): y_t = 0.5 y_{t-1} - 0.3 y_{t-2} + ε_t
phi1_true, phi2_true = 0.5, -0.3
np.random.seed(0)
ar_poly = np.array([1, -phi1_true, -phi2_true])   # 1 - φ1 L - φ2 L^2
ma_poly = np.array([1.0])
y = arma_generate_sample(ar_poly, ma_poly, nsample=3000, scale=1.0)

res = ARIMA(y, order=(2, 0, 0), trend="c").fit()
phi1_hat = res.params[res.param_names.index("ar.L1")]
phi2_hat = res.params[res.param_names.index("ar.L2")]
print(f"{'係数':>6}{'真値':>10}{'推定値':>10}")
print(f"{'φ1':>6}{phi1_true:>10.3f}{phi1_hat:>10.3f}")
print(f"{'φ2':>6}{phi2_true:>10.3f}{phi2_hat:>10.3f}")

# 定常性チェック:特性根が単位円の外か
roots = res.arroots
print(f"特性根の絶対値 = {np.abs(roots).round(3)}  (>1 なら定常)")

出力:

    係数        真値       推定値
    φ1     0.500     0.511
    φ2    -0.300    -0.299
特性根の絶対値 = [1.83 1.83]  (>1 なら定常)

出力の意味:推定値は ϕ^1=0.511, ϕ^2=0.299\hat\phi_1=0.511,\ \hat\phi_2=-0.299 と、仕込んだ真値 0.5, 0.30.5,\ -0.3 をほぼ正確に復元しました(誤差は推定の標準誤差の範囲)。arma_generate_sample に渡す係数は [1, -φ1, -φ2] の符号に注意——ラグ多項式 ϕ(L)=1ϕ1Lϕ2L2\phi(L)=1-\phi_1L-\phi_2L^2 の係数だからです。特性根の絶対値は 1.83>11.83>1 なので、この AR(2) は定常。シミュレーションなら真値が分かるので「ちゃんと当たっているか」を直接検証できます。

2. MA(qq):過去のショックで説明する

移動平均モデル MA(qq) は、現在値を過去 qq 期のショック(ノイズ) ε\varepsilon の線形結合で表します。

yt=μ+εt+θ1εt1++θqεtq=μ+θ(L)εt,θ(L)=1+θ1L++θqLqy_t = \mu + \varepsilon_t + \theta_1\varepsilon_{t-1} + \cdots + \theta_q\varepsilon_{t-q} = \mu + \theta(L)\varepsilon_t,\qquad \theta(L)=1+\theta_1 L+\cdots+\theta_q L^q

MA はホワイトノイズの有限個の和なので、係数が何であっても常に定常です(平均・分散・自己共分散が時間に依らない)。そして記憶は qq 期で尽きる——qq より離れた値とは共有するショックが無いので、自己共分散は qq より先で厳密に 0。これが「MA(qq) は ACF がラグ qq で切れる」の正体です。

MA(1)(yt=εt+θεt1y_t=\varepsilon_t+\theta\varepsilon_{t-1})で自己共分散を直接計算すると、

γ0=Var[yt]=(1+θ2)σ2,γ1=Cov[yt,yt1]=θσ2,γk=0 (k2)\gamma_0=\mathrm{Var}[y_t]=(1+\theta^2)\sigma^2,\quad \gamma_1=\mathrm{Cov}[y_t,y_{t-1}]=\theta\sigma^2,\quad \gamma_k=0\ (k\ge 2)

なので自己相関は次の通り。ラグ1だけ非ゼロ、ラグ2以降はゼロです。

ρ1=θ1+θ2,ρk=0 (k2)\rho_1=\frac{\theta}{1+\theta^2},\qquad \rho_k=0\ (k\ge 2)

反転可能性(invertibility):実は MA(1) では θ\theta1/θ1/\theta同じ ACF を与えます(ρ1=θ/(1+θ2)\rho_1=\theta/(1+\theta^2)1/θ1/\theta を入れても同値)。つまり ACF だけでは θ\theta が一意に決まりません。そこで**θ(z)=0\theta(z)=0 の根が単位円の外(MA(1) なら θ<1|\theta|<1という反転可能性**を課し、θ<1|\theta|<1 の側を採用します。反転可能なら MA を εt=θ(L)1yt\varepsilon_t=\theta(L)^{-1}y_t と AR(\infty) に書き直せ(過去の観測値からショックを復元でき)、推定・予測が安定します。statsmodels は既定で反転可能な解を返します。

コード②:MA(1) の θ を復元し、ACF がラグ1で切れることを確認

真の θ=0.6\theta=0.6 を仕込んだ MA(1) を生成し、ARIMA(order=(0,0,1))θ\theta を推定します。あわせて ACF を計算し、理論値 ρ1=θ/(1+θ2)\rho_1=\theta/(1+\theta^2) と一致すること・ラグ2以降がほぼ 0(=切れる)ことを確かめます。

import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.arima_process import arma_generate_sample
from statsmodels.tsa.stattools import acf

# 真の MA(1): y_t = ε_t + 0.6 ε_{t-1}
theta_true = 0.6
np.random.seed(1)
ar_poly = np.array([1.0])
ma_poly = np.array([1, theta_true])
y = arma_generate_sample(ar_poly, ma_poly, nsample=3000, scale=1.0)

res = ARIMA(y, order=(0, 0, 1), trend="c").fit()
theta_hat = res.params[res.param_names.index("ma.L1")]
print(f"θ 真値={theta_true:.3f}  推定値={theta_hat:.3f}")

# 理論 ACF: ρ1 = θ/(1+θ^2), ρk=0 (k>=2)
rho1_theory = theta_true / (1 + theta_true**2)
a = acf(y, nlags=5, fft=True)
print(f"理論 ρ1 = θ/(1+θ^2) = {rho1_theory:.3f}")
print(f"{'lag':>4}{'ACF推定':>10}")
for k in range(6):
    print(f"{k:>4}{a[k]:>10.3f}")

出力:

θ 真値=0.600  推定値=0.588
理論 ρ1 = θ/(1+θ^2) = 0.441
 lag     ACF推定
   0     1.000
   1     0.432
   2    -0.009
   3    -0.001
   4     0.008
   5     0.008

出力の意味:推定 θ^=0.588\hat\theta=0.588 は真値 0.60.6 を復元。ACF はラグ1で 0.4320.432——理論 ρ1=0.441\rho_1=0.441 とほぼ一致し、ラグ2以降はすべてほぼ 00.009,0.001,-0.009,\,-0.001,\dots)。これが MA(1) の指紋「ACF がラグ1でストンと切れる」です。AR(1) の ACF が 0.70,0.48,0.70,0.48,\dots と尾を引いた(定常性と自己相関)のと対照的に、MA は記憶が有限なので ACF がぱつんと切れます。

3. AR と MA の指紋:ACF/PACF で見分ける

定常性と自己相関 の表を、AR/MA を主役にして再掲します。「切れる方が次数を教える」——AR は PACF、MA は ACF が次数で切れます。

モデルACFPACF
AR(pp)緩やかに減衰(尾を引く)ラグ pp で切れる
MA(qq)ラグ qq で切れる緩やかに減衰(尾を引く)

AR(2)(ϕ1=0.5,ϕ2=0.3\phi_1=0.5,\phi_2=-0.3)と MA(1)(θ=0.6\theta=0.6)の ACF/PACF を並べて、この指紋を目で確かめます。

import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib  # 日本語ラベル用
from statsmodels.tsa.arima_process import arma_generate_sample
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

np.random.seed(2)
ar2 = arma_generate_sample(np.array([1, -0.5, 0.3]), np.array([1.0]), nsample=3000)  # AR(2): φ1=0.5, φ2=-0.3
ma1 = arma_generate_sample(np.array([1.0]), np.array([1, 0.6]), nsample=3000)        # MA(1): θ=0.6

fig, ax = plt.subplots(2, 2, figsize=(11, 7))
plot_acf(ar2, lags=12, ax=ax[0, 0]);  ax[0, 0].set_title("AR(2) の ACF(緩やかに減衰)")
plot_pacf(ar2, lags=12, ax=ax[0, 1], method="ywm"); ax[0, 1].set_title("AR(2) の PACF(ラグ2で切れる)")
plot_acf(ma1, lags=12, ax=ax[1, 0]);  ax[1, 0].set_title("MA(1) の ACF(ラグ1で切れる)")
plot_pacf(ma1, lags=12, ax=ax[1, 1], method="ywm"); ax[1, 1].set_title("MA(1) の PACF(緩やかに減衰)")
plt.tight_layout(); plt.show()

グラフの意味:上段 AR(2) は、左の ACF が徐々に減衰(尾を引く)、右の PACF がラグ2まで棒が立ち、ラグ3以降は信頼帯の中=0。下段 MA(1) は逆で、左の ACF がラグ1だけ立ってラグ2以降は0、右の PACF が尾を引きます。「ACF が切れたら MA、PACF が切れたら AR、切れた位置が次数」——次数の当てずっぽうの出発点になります。両方とも尾を引いて切れないなら、次節の ARMA を疑います(ARMA・ARIMAモデル)。

4. 数式の直観

⚠️ よくある誤解

関連ノート