MA 모형
MA(q) 모형은 이전 시점의 오차가 현재 시점의 값에 영향을 준다고 가정하는 모형입니다. q는 영향을 주는 시점의 수를 나타냅니다. 직전 t-1 시점의 오차가 영향을 주면 MA(1) 모형, 직전 t-1과 그 이전 t-2의 오차가 영향을 주면 MA(2) 모형, 등으로 구분합니다.
$$ y_t = \mu + \epsilon_{t} - \theta_1 \epsilon_{t-1} - \cdots - \theta_q \epsilon_{t-q} $$
다음은 MA(1) 모형의 시뮬레이션입니다.
import numpy as np
n = 1000
e = np.random.normal(size=n)
sim = np.zeros(n)
for i in range(1, n):
sim[i] = 0.5 * e[i-1] + e[i]
이를 시각화하면 아래와 같습니다.
import matplotlib.pyplot as plt
plt.plot(sim)
[<matplotlib.lines.Line2D at 0x265b3b35180>]
MA 모형을 따르는 시계열을 ACF를 시각화하면 q 이후에는 0에 가깝게 뚝 떨어지는 특성이 있습니다.
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_acf(sim);
그러나 PACF를 시각화하면 점진적으로 감소하는 형태를 띕니다.
plot_pacf(sim);
MA(q) 모형을 추정해보겠습니다. SARIMAX
함수를 사용합니다. 이 함수는 order
라는 인자를 받는데, 순서대로 (p, d, q)
순입니다. p
와 d
는 다른 모형에 사용되는 차수이므로, 여기서는 0으로 설정합니다. MA(1)
모형을 추정하려면 order=(0, 0, 1)
로 설정합니다.
ma.L1
계수가 시뮬레이션에서 설정한 0.5
에 가깝게 나오는 것을 볼 수 있습니다.
from statsmodels.tsa.api import SARIMAX
ma1 = SARIMAX(sim, order=(0, 0, 1)).fit()
ma1.summary()
Dep. Variable: | y | No. Observations: | 1000 |
---|---|---|---|
Model: | SARIMAX(0, 0, 1) | Log Likelihood | -1431.729 |
Date: | Sun, 18 Jun 2023 | AIC | 2867.457 |
Time: | 18:33:02 | BIC | 2877.273 |
Sample: | 0 | HQIC | 2871.188 |
- 1000 | |||
Covariance Type: | opg |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
ma.L1 | 0.4910 | 0.026 | 18.561 | 0.000 | 0.439 | 0.543 |
sigma2 | 1.0256 | 0.047 | 21.693 | 0.000 | 0.933 | 1.118 |
Ljung-Box (L1) (Q): | 0.13 | Jarque-Bera (JB): | 0.69 |
---|---|---|---|
Prob(Q): | 0.72 | Prob(JB): | 0.71 |
Heteroskedasticity (H): | 1.03 | Skew: | -0.03 |
Prob(H) (two-sided): | 0.81 | Kurtosis: | 2.88 |
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
맥주 생산량 데이터를 이용해서 MA 모형으로 추정해보겠습니다.
import pandas as pd
df = pd.read_excel('beer.xlsx')
y = df.production
y.plot()
<Axes: >
MA(1) 모형
ma1 = SARIMAX(y, order=(0, 0, 1)).fit()
ma1.summary()
Dep. Variable: | production | No. Observations: | 218 |
---|---|---|---|
Model: | SARIMAX(0, 0, 1) | Log Likelihood | -1511.619 |
Date: | Sun, 18 Jun 2023 | AIC | 3027.239 |
Time: | 18:35:07 | BIC | 3034.008 |
Sample: | 0 | HQIC | 3029.973 |
- 218 | |||
Covariance Type: | opg |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
ma.L1 | 0.8116 | 0.074 | 10.958 | 0.000 | 0.666 | 0.957 |
sigma2 | 6.141e+04 | 1.72e+04 | 3.565 | 0.000 | 2.76e+04 | 9.52e+04 |
Ljung-Box (L1) (Q): | 56.83 | Jarque-Bera (JB): | 15.09 |
---|---|---|---|
Prob(Q): | 0.00 | Prob(JB): | 0.00 |
Heteroskedasticity (H): | 1.73 | Skew: | 0.55 |
Prob(H) (two-sided): | 0.02 | Kurtosis: | 2.32 |
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
실제값과 예측값을 비교
y.plot()
ma1.predict(0, 250).plot()
<Axes: >
MA 모형은 기본적으로 절편 0을 가정합니다. 오차가 없으면 0으로 수렴합니다. trend='c'
로 설정하면 절편(intercept)을 추정합니다.
ma1c = SARIMAX(y, order=(0, 0, 1), trend='c').fit()
ma1c.summary()
Dep. Variable: | production | No. Observations: | 218 |
---|---|---|---|
Model: | SARIMAX(0, 0, 1) | Log Likelihood | -1232.206 |
Date: | Sun, 18 Jun 2023 | AIC | 2470.412 |
Time: | 18:35:48 | BIC | 2480.566 |
Sample: | 0 | HQIC | 2474.513 |
- 218 | |||
Covariance Type: | opg |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
intercept | 415.1554 | 8.452 | 49.117 | 0.000 | 398.589 | 431.722 |
ma.L1 | 0.5227 | 0.087 | 6.019 | 0.000 | 0.353 | 0.693 |
sigma2 | 4747.1747 | 491.539 | 9.658 | 0.000 | 3783.775 | 5710.574 |
Ljung-Box (L1) (Q): | 14.90 | Jarque-Bera (JB): | 4.54 |
---|---|---|---|
Prob(Q): | 0.00 | Prob(JB): | 0.10 |
Heteroskedasticity (H): | 0.39 | Skew: | 0.35 |
Prob(H) (two-sided): | 0.00 | Kurtosis: | 2.94 |
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
y.plot()
ma1c.predict(0, 250).plot()
<Axes: >
trend='ct'
로 설정하면 절편(intercept)과 시간에 따른 표류(drift)를 추정합니다.
ma1ct = SARIMAX(y, order=(0, 0, 1), trend='ct').fit()
ma1ct.summary()
Dep. Variable: | production | No. Observations: | 218 |
---|---|---|---|
Model: | SARIMAX(0, 0, 1) | Log Likelihood | -1209.574 |
Date: | Sun, 18 Jun 2023 | AIC | 2427.148 |
Time: | 18:36:09 | BIC | 2440.686 |
Sample: | 0 | HQIC | 2432.616 |
- 218 | |||
Covariance Type: | opg |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
intercept | 338.2782 | 13.492 | 25.072 | 0.000 | 311.834 | 364.723 |
drift | 0.7086 | 0.107 | 6.603 | 0.000 | 0.498 | 0.919 |
ma.L1 | 0.4761 | 0.078 | 6.116 | 0.000 | 0.324 | 0.629 |
sigma2 | 3858.1869 | 441.422 | 8.740 | 0.000 | 2993.016 | 4723.358 |
Ljung-Box (L1) (Q): | 6.02 | Jarque-Bera (JB): | 25.60 |
---|---|---|---|
Prob(Q): | 0.01 | Prob(JB): | 0.00 |
Heteroskedasticity (H): | 0.91 | Skew: | 0.84 |
Prob(H) (two-sided): | 0.70 | Kurtosis: | 3.11 |
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
y.plot()
ma1ct.predict(0, 250).plot()
<Axes: >
MA(2) 모형
ma2 = SARIMAX(y, order=(0, 0, 2), trend='c').fit()
ma2.summary()
C:\Users\eupho\anaconda3\lib\site-packages\statsmodels\tsa\statespace\sarimax.py:978: UserWarning: Non-invertible starting MA parameters found. Using zeros as starting parameters. warn('Non-invertible starting MA parameters found.'
Dep. Variable: | production | No. Observations: | 218 |
---|---|---|---|
Model: | SARIMAX(0, 0, 2) | Log Likelihood | -1186.272 |
Date: | Sun, 18 Jun 2023 | AIC | 2380.544 |
Time: | 18:36:28 | BIC | 2394.082 |
Sample: | 0 | HQIC | 2386.012 |
- 218 | |||
Covariance Type: | opg |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
intercept | 415.0024 | 11.220 | 36.988 | 0.000 | 393.012 | 436.993 |
ma.L1 | 1.1796 | 0.046 | 25.867 | 0.000 | 1.090 | 1.269 |
ma.L2 | 0.7872 | 0.044 | 17.783 | 0.000 | 0.700 | 0.874 |
sigma2 | 3083.6395 | 347.530 | 8.873 | 0.000 | 2402.494 | 3764.785 |
Ljung-Box (L1) (Q): | 4.71 | Jarque-Bera (JB): | 3.09 |
---|---|---|---|
Prob(Q): | 0.03 | Prob(JB): | 0.21 |
Heteroskedasticity (H): | 0.79 | Skew: | -0.11 |
Prob(H) (two-sided): | 0.33 | Kurtosis: | 2.46 |
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
y.plot()
ma2.predict(0, 250).plot()
<Axes: >