시계열 - 선형 모형

Time Series - Linear Models

time series
ARIMA
Author

Cheonghyo Cho

시계열 분석을 정리하고자 한다. ARIMA 등 선형 모델에 대해 알아보자.

AR Model

AR(Autoregressive) 모델은 시계열 데이터의 현재 값이 이전의 여러 시점의 값들에 의존하여 결정된다고 가정하는 시계열 모델이다.

AR 모델은 시계열의 현재 값이 과거의 자신의 값들과의 선형 조합으로 표현한다.

AR(p)

\(AR(p)\):

\[Y_t = c + \phi_1 Y_{t-1} + \phi_2 Y_{t-2} + \dots + \phi_p Y_{t-p} + \epsilon_t\]

\[\Phi_p(L)Y_t = c + \epsilon_t\]

  • 자기 상관성: AR 모델은 시계열 데이터의 자기 상관성을 모델링한다. 즉, 현재의 값이 과거의 값들과 어떻게 연관되어 있는지를 분석한다.

  • 정상성(Stationarity): AR 모델을 적용하기 위해서는 시계열 데이터가 정상 시계열이어야 한다. 즉, 시계열의 평균과 분산이 시간에 따라 일정해야 하며, 공분산이 두 시점 간의 간격에만 의존해야 한다. 비정상 시계열은 차분(differencing)과 같은 방법으로 정상화할 수 있다.

  • 모델 선택: AR 모델의 차수 \(p\)는 중요한 선택 요소이다. 너무 낮은 차수는 데이터의 구조를 충분히 설명하지 못할 수 있고, 너무 높은 차수는 과적합(overfitting)을 초래할 수 있다. AIC(Akaike Information Criterion)나 BIC(Bayesian Information Criterion) 같은 정보 기준을 사용하여 최적의 차수를 결정할 수 있다.

import numpy as np
import pandas as pd
from statsmodels.tsa.ar_model import AutoReg
import matplotlib.pyplot as plt

# 임의의 시계열 데이터 생성
np.random.seed(123)
data = pd.Series(np.random.randn(100).cumsum())

# AR 모델 적합 (여기서는 차수 p=2로 설정)
model = AutoReg(data, lags=2)
model_fitted = model.fit()

# 모델 파라미터 출력
print(model_fitted.params)

# 예측
predictions = model_fitted.predict(start=len(data), end=len(data)+10)

plt.figure(figsize=(10,5))
plt.plot(data, label='Original Data')
plt.plot(np.arange(len(data), len(data)+11), predictions, label='Predictions', color='red')
plt.legend()
plt.show()
const    0.087009
y.L1     0.989062
y.L2    -0.041930
dtype: float64

AR(1)

\(X_{t} = c + {\phi}X_{t-1} + \epsilon_{t}\)

AR(1) 모형의 정상성 조건은 다음과 같음을 확인할 수 있다.

$ ||<1$

만약 이 조건이 지켜지지 않는 경우 AR(1) 회귀식으로부터, 시계열의 값이 시간에 대해 점차 증가하거나 감소하는 추세를 가지게 될 것임을 예측할 수 있다.

또한, \(\phi=1, c=0\)이면 랜덤워크, $, c $이면 drift가 있는 랜덤워크이다.

\(E[X_{t}] = \frac{c}{1-\phi}\)

\(Var[X_{t}] = \frac{\sigma^{2}}{1-\phi^{2}}\)

\(Cov[X_{t}, X_{t-k}] = \frac{\phi^{k}}{1-\phi^{2}}\sigma^{2}\)

AR(1)의 ACF는 \(\phi^k\) (단, 정상 시계열일때)

AR(1)의 PACF는 \(\phi\) (단, k>1이면 0)

AR(2)

\(X_{t} = c + {\phi_1}X_{t-1} + {\phi_2}X_{t-2}+ \epsilon_{t}\)

  • AR(2) 모형의 정상성 조건: \(-1<\phi_2<1, \phi_1+\phi_2<1, \phi_2-\phi_1<1\)

MA Model

MA(Moving Average) 모델은 시계열 분석에서 사용되는 또 다른 중요한 모델이다. 이 모델은 시계열 데이터의 현재 값이 과거의 예측 오차들의 선형 조합으로 표현될 수 있다고 가정한다. MA 모델은 시계열의 불규칙적인 변동(잡음)을 모델링하는 데 특히 유용하다.

\(MA(q)\):

\[Y_t = \mu + \epsilon_t + \theta_1 \epsilon_{t-1} + \theta_2 \epsilon_{t-2} + \dots + \theta_q \epsilon_{t-q}\]

  • 과거의 예측 오차: MA 모델은 현재의 값이 과거의 예측 오차들에 의해 영향을 받는다고 가정한다. 이는 AR 모델과 대비되는 부분으로, AR 모델은 과거의 값들에 의해 현재 값이 결정된다고 보는 것이다.
  • 잡음의 필터링: MA 모델은 시계열 데이터에서 잡음을 분리해내는 필터 역할을 할 수 있다. 이는 시계열 데이터의 중요한 구조적 정보를 추출하는 데 도움을 준다.
  • 차수의 결정: MA 모델의 차수 \(q\)는 중요한 선택 요소다. 차수가 너무 낮으면 데이터의 구조를 충분히 설명하지 못할 수 있고, 너무 높으면 모델이 과적합될 위험이 있다.

정상성을 나타내는 어떤 AR(p) 모델을 MA(\(\infty\)) 모델로 쓸 수 있으며, MA(q) 모델을 AR(\(\infty\)) process로 쓸 수 있다. 이를 가역적(invertible)이라고 한다.

  • \(|\theta|<1\)이면, 가중치의 시차(lag) 값이 증가함에 따라 증가하고, 따라서 더 멀리 떨어진 관측값일 수록 현재 오차에 미치는 영향이 커진다.
  • \(|\theta|=1\)이면, 가중치가 크기에 대해 상수이고, 멀리 떨어진 관측값과 가까운 관측값 모두 같은 영향을 미친다.
  • \(|\theta|<1\)일 때, 과정은 가역적(invertible)이다.
from statsmodels.tsa.arima.model import ARIMA

# MA 모델 적합 (여기서는 차수 q=2로 설정)
model = ARIMA(data, order=(0, 0, 2))  # ARIMA 모델에서 AR 부분을 0으로 설정하여 순수한 MA 모델을 생성
model_fitted = model.fit()

# 모델 파라미터 출력
print(model_fitted.summary())

# 예측
predictions = model_fitted.predict(start=len(data), end=len(data)+10)

plt.figure(figsize=(10,5))
plt.plot(data, label='Original Data')
plt.plot(np.arange(len(data), len(data)+11), predictions, label='Predictions', color='red')
plt.legend()
plt.show()
                               SARIMAX Results                                
==============================================================================
Dep. Variable:                      y   No. Observations:                  100
Model:                 ARIMA(0, 0, 2)   Log Likelihood                -195.819
Date:                Mon, 08 Apr 2024   AIC                            399.638
Time:                        20:48:15   BIC                            410.059
Sample:                             0   HQIC                           403.856
                                - 100                                         
Covariance Type:                  opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          1.1174      0.473      2.364      0.018       0.191       2.044
ma.L1          1.1379      0.117      9.749      0.000       0.909       1.367
ma.L2          0.5044      0.112      4.496      0.000       0.285       0.724
sigma2         2.8983      0.521      5.568      0.000       1.878       3.919
===================================================================================
Ljung-Box (L1) (Q):                  10.20   Jarque-Bera (JB):                 2.34
Prob(Q):                              0.00   Prob(JB):                         0.31
Heteroskedasticity (H):               1.08   Skew:                            -0.01
Prob(H) (two-sided):                  0.83   Kurtosis:                         2.25
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

MA(1)

\(X_{t} = c + \epsilon_{t} + \theta \epsilon_{t-1}\)

\(E[X_{t}] = c\)

\(Var[X_{t}] = (1+\theta^{2})\sigma^{2}\)

\(Cov(X_{t},X_{t-1}) = \theta\sigma^{2}\)

\(Cov(X_{t},X_{t-k}) = 0\) for k > 1

MA(1) process는 추가적인 가정이 없이도 약정상성을 만족

ARMA Model

ARMA(Autoregressive Moving Average)은 자기 회귀(AR) 모델과 이동 평균(MA) 모델을 결합한 형태다. ARMA 모델은 시계열 데이터의 자기 상관성과 불규칙적인 변동을 모두 캡처할 수 있기 때문에, 비교적 복잡한 시계열 데이터를 모델링할 때 널리 사용된다.

\(ARMA(p,q)\):

\[Y_t = c + \phi_1 Y_{t-1} + \phi_2 Y_{t-2} + \dots + \phi_p Y_{t-p} + \epsilon_t + \theta_1 \epsilon_{t-1} + \theta_2 \epsilon_{t-2} + \dots + \theta_q \epsilon_{t-q}\]

# ARMA 모델 적합 (여기서는 AR 차수 p=2, MA 차수 q=2로 설정)
model = ARIMA(data, order=(2, 0, 2))
model_fitted = model.fit()

# 모델 요약 출력
print(model_fitted.summary())

# 예측
predictions = model_fitted.predict(start=len(data), end=len(data)+10)

plt.figure(figsize=(10,5))
plt.plot(data, label='Original Data')
plt.plot(np.arange(len(data), len(data)+11), predictions, label='Predictions', color='red')
plt.legend()
plt.show()
                               SARIMAX Results                                
==============================================================================
Dep. Variable:                      y   No. Observations:                  100
Model:                 ARIMA(2, 0, 2)   Log Likelihood                -151.885
Date:                Mon, 08 Apr 2024   AIC                            315.770
Time:                        20:48:17   BIC                            331.401
Sample:                             0   HQIC                           322.096
                                - 100                                         
Covariance Type:                  opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          1.0747      1.132      0.950      0.342      -1.144       3.293
ar.L1          1.8616      0.142     13.153      0.000       1.584       2.139
ar.L2         -0.8772      0.130     -6.733      0.000      -1.133      -0.622
ma.L1         -0.9227      0.178     -5.182      0.000      -1.272      -0.574
ma.L2          0.0783      0.117      0.669      0.504      -0.151       0.308
sigma2         1.1926      0.220      5.432      0.000       0.762       1.623
===================================================================================
Ljung-Box (L1) (Q):                   0.01   Jarque-Bera (JB):                 2.17
Prob(Q):                              0.92   Prob(JB):                         0.34
Heteroskedasticity (H):               0.74   Skew:                            -0.04
Prob(H) (two-sided):                  0.40   Kurtosis:                         2.28
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

ARIMA Model

ARIMA(Autoregressive Integrated Moving Average)는 시계열 데이터의 비정상성을 처리하기 위해 고안된 모델이다. ARIMA는 ARMA 모델을 확장한 것으로, ARMA가 정상 시계열에만 적용 가능한 반면, ARIMA는 비정상 시계열 데이터에도 적용할 수 있다는 장점이 있다.

  • 비정상 시계열 데이터 적용 가능: 차분을 통해 비정상 시계열을 정상 시계열로 변환한 후, ARMA 모델을 적용한다.
  • 예측력: ARIMA 모델은 미래 값의 예측에 자주 사용되며, 금융, 경제, 사회 과학 등 다양한 분야에서 활용된다.
  • 모델 차수의 결정: AIC, BIC와 같은 정보 기준을 사용하여 최적의 \(p,d,q\) 값을 결정한다.
# ARIMA 모델 적합 (여기서는 p=1, d=1, q=1로 설정)
model = ARIMA(data, order=(1, 1, 1))
model_fitted = model.fit()

# 모델 요약 정보 출력
print(model_fitted.summary())

# 예측
predictions = model_fitted.predict(start=len(data), end=len(data)+10, typ='levels')

plt.figure(figsize=(10,5))
plt.plot(data, label='Original Data')
plt.plot(np.arange(len(data), len(data)+11), predictions, label='Predictions', color='red')
plt.legend()
plt.show()
                               SARIMAX Results                                
==============================================================================
Dep. Variable:                      y   No. Observations:                  100
Model:                 ARIMA(1, 1, 1)   Log Likelihood                -151.508
Date:                Mon, 08 Apr 2024   AIC                            309.015
Time:                        20:48:18   BIC                            316.801
Sample:                             0   HQIC                           312.165
                                - 100                                         
Covariance Type:                  opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
ar.L1         -0.7645      0.287     -2.661      0.008      -1.328      -0.201
ma.L1          0.8560      0.242      3.544      0.000       0.383       1.329
sigma2         1.2488      0.211      5.930      0.000       0.836       1.661
===================================================================================
Ljung-Box (L1) (Q):                   0.29   Jarque-Bera (JB):                 1.23
Prob(Q):                              0.59   Prob(JB):                         0.54
Heteroskedasticity (H):               0.77   Skew:                            -0.00
Prob(H) (two-sided):                  0.45   Kurtosis:                         2.45
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
C:\Users\master\anaconda3\envs\py38\lib\site-packages\statsmodels\tsa\statespace\representation.py:374: FutureWarning: Unknown keyword arguments: dict_keys(['typ']).Passing unknown keyword arguments will raise a TypeError beginning in version 0.15.
  warnings.warn(msg, FutureWarning)

차수 결정

ACF, PACF

ACF, PACF에 대해서는 전 포스트에서 다루었다.

  • AR 모델의 차수 결정: PACF를 살펴보아 \(p\) 이후에 급격히 떨어지는 지점을 찾는다. 이 지점이 AR 모델의 추정 차수가 될 수 있다.
  • MA 모델의 차수 결정: ACF를 살펴보아 \(q\) 이후에 급격히 떨어지는 지점을 찾는다. 이 지점이 MA 모델의 추정 차수가 될 수 있다.
  • ARIMA 모델의 차수 결정: 차분 \(d\)를 적용한 후에도 비정상적인 패턴이 관찰되면, ACF와 PACF를 다시 살펴보아 AR 부분과 MA 부분의 차수를 결정한다.
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt

# ACF 플롯
plt.figure(figsize=(5, 6))
plot_acf(data, lags=40, ax=plt.subplot(2, 1, 1))

# PACF 플롯
plot_pacf(data, lags=40, ax=plt.subplot(2, 1, 2))

plt.tight_layout()
plt.show()

diff = data.diff(1).dropna()

# ACF 플롯
plt.figure(figsize=(5, 6))
plot_acf(diff, lags=40, ax=plt.subplot(2, 1, 1))

# PACF 플롯
plot_pacf(diff, lags=40, ax=plt.subplot(2, 1, 2))

plt.tight_layout()
plt.show()

AIC, BIC

AIC (Akaike Information Criterion)와 BIC (Bayesian Information Criterion)는 시계열 모델 선택에서 모델의 적합도와 복잡성 사이의 균형을 평가하는 데 널리 사용된다. 자세한 설명은 생략한다.

from statsmodels.tsa.arima.model import ARIMA

# 모델 적합
model = ARIMA(data, order=(1, 1, 1))
model_fitted = model.fit()

# AIC와 BIC 출력
print(f"AIC: {model_fitted.aic}")
print(f"BIC: {model_fitted.bic}")

# 모델 적합
model = ARIMA(data, order=(3, 1, 1))
model_fitted = model.fit()

# AIC와 BIC 출력
print(f"AIC: {model_fitted.aic}")
print(f"BIC: {model_fitted.bic}")
AIC: 309.0152096770903
BIC: 316.80056922749407
AIC: 310.78416238617626
BIC: 323.7597616368492

Auto ARIMA

auto_arima 함수는 주어진 시계열 데이터에 대해 최적의 ARIMA 모델을 자동으로 찾는다!

import pmdarima as pm

# auto_arima 실행
model = pm.auto_arima(data, start_p=2, start_q=2,
                      test='adf',       # ADF 검정을 사용하여 차분 결정
                      max_p=5, max_q=5, # 최대 p와 q 값
                      m=1,              # 계절성 주기, 여기서는 비계절성 시계열이므로 1
                      d=None,           # 차분 차수, None이면 자동 결정
                      seasonal=False,   # 계절성 모델 사용 여부
                      start_P=1, 
                      D=None, 
                      trace=True,       # 검색 과정의 정보를 출력
                      error_action='ignore',  
                      suppress_warnings=True, 
                      stepwise=True)    # 단계별 검색 사용

# 요약 정보 출력
print(model.summary())
Performing stepwise search to minimize aic
 ARIMA(2,1,2)(0,0,0)[0] intercept   : AIC=inf, Time=0.37 sec
 ARIMA(0,1,0)(0,0,0)[0] intercept   : AIC=308.858, Time=0.02 sec
 ARIMA(1,1,0)(0,0,0)[0] intercept   : AIC=310.834, Time=0.02 sec
 ARIMA(0,1,1)(0,0,0)[0] intercept   : AIC=310.833, Time=0.03 sec
 ARIMA(0,1,0)(0,0,0)[0]             : AIC=306.972, Time=0.00 sec
 ARIMA(1,1,1)(0,0,0)[0] intercept   : AIC=312.834, Time=0.05 sec

Best model:  ARIMA(0,1,0)(0,0,0)[0]          
Total fit time: 0.485 seconds
                               SARIMAX Results                                
==============================================================================
Dep. Variable:                      y   No. Observations:                  100
Model:               SARIMAX(0, 1, 0)   Log Likelihood                -152.486
Date:                Mon, 08 Apr 2024   AIC                            306.972
Time:                        20:49:26   BIC                            309.567
Sample:                             0   HQIC                           308.022
                                - 100                                         
Covariance Type:                  opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
sigma2         1.2746      0.219      5.831      0.000       0.846       1.703
===================================================================================
Ljung-Box (L1) (Q):                   0.02   Jarque-Bera (JB):                 1.64
Prob(Q):                              0.87   Prob(JB):                         0.44
Heteroskedasticity (H):               0.70   Skew:                             0.01
Prob(H) (two-sided):                  0.32   Kurtosis:                         2.37
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

ARIMA의 한계점

  • 비선형성: ARIMA 모델은 선형 관계를 가정한다. 많은 실제 시계열 데이터는 비선형 패턴을 보이기 때문에, 이러한 비선형 패턴을 효과적으로 모델링하지 못할 수 있다.

  • 계절성: 계절 ARIMA(Seasonal ARIMA) 모델은 계절성을 다루기 위해 개발되었지만, 계절성이 복잡하거나 비정기적인 시계열 데이터를 처리하는 데는 한계가 있다.

  • 정상성: ARIMA 모델은 시계열 데이터가 정상성을 가정한다. 비정상 시계열 데이터는 차분 등의 방법으로 정상 시계열로 변환할 수 있지만, 이 과정에서 정보가 손실될 수 있으며, 모든 비정상 시계열이 적절히 정상화되는 것은 아니다. 또한, 차분을 통해 얻어진 시계열 데이터의 해석이 원본 데이터의 해석과 다를 수 있다.

  • 모델 선택과 과적합의 위험: 적절한 ARIMA 모델을 선택하기 위해서는 \(p,d,q\)의 적절한 차수를 결정해야 한다. 모델 차수를 결정하는 과정에서 과적합(overfitting)이 발생할 수 있으며, 이는 모델의 예측 성능을 저하시킬 수 있다. AIC, BIC와 같은 기준을 사용하여 모델을 선택할 수 있지만, 이러한 기준만으로 최적의 모델을 항상 보장하지는 않는다.

  • 동적 변화에 대한 제한적 대응: ARIMA 모델은 시계열 데이터의 고정된 패턴을 기반으로 예측을 수행한다. 시계열 데이터의 구조가 시간에 따라 변하는 경우(예: 금융 시장의 급변동), ARIMA 모델은 이러한 동적 변화에 효과적으로 대응하기 어려울 수 있다.

SARIMAX

Seasonal AutoRegressive Integrated Moving Average with eXogenous regressors

SARIMAX 모델은 ARIMA 모델을 기반으로 하면서 계절성 요소와 외생 변수를 추가하여 모델의 유연성과 정확성을 높였다. SARIMAX는 다양한 시계열 데이터, 특히 계절적 패턴과 외부 영향을 받는 데이터에 적합하다.

  • AR (AutoRegressive) 부분: 과거의 종속 변수 값(지연 값)이 미래 값에 영향을 미친다고 가정

  • MA (Moving Average) 부분: 과거의 예측 오차가 미래 예측에 영향을 미친다고 가정

  • Integration (차분) 부분: 비정상성(Non-stationarity) 데이터를 정상성(Stationarity) 데이터로 변환하기 위해 사용

  • Seasonal 요소: 계절성 패턴을 모델링. 계절성 AR 및 MA 구성 요소와 계절성 차분 차수를 포함할 수 있으며, 이들은 각각 \(P, D, Q\) 및 계절 주기 \(s\)에 의해 정의됨

  • Exogenous 변수 (\(\mathbf{X}\)): 모델에 외부에서 영향을 미치는 변수(예: 경제 지표, 마케팅 캠페인, 기상 조건 등)를 포함. 이 변수들은 종속 변수에 직접적인 영향을 미칠 수 있으며, 모델의 설명력과 예측력을 향상시킴.

\[(1 - \sum_{i=1}^{p}{\phi_i L^i})(1 - L^d)(1 - \sum_{i=1}^{P}{\Phi_i L^{i \cdot s}})^D Y_t = (1 + \sum_{j=1}^{q}{\theta_j L^j})(1 + \sum_{j=1}^{Q}{\Theta_j L^{j \cdot s}}) \epsilon_t + \mathbf{X}_t \beta\]

여기서,

  • \(L\)은 lag operator
  • \(\phi_i\), \(\Phi_i\)는 비계절 및 계절 AR 파라미터
  • \(\theta_j\), \(\Theta_j\)는 비계절 및 계절 MA 파라미터
  • \(\mathbf{X}_t\)는 시점 \(t\)에서 외생 변수
  • \(\beta\)는 외생 변수의 계수
import numpy as np
import pandas as pd
from scipy.stats import norm
import statsmodels.api as sm
import matplotlib.pyplot as plt
from datetime import datetime
data = pd.read_stata('data/wpi1.dta')
data.index = data.t
# Set the frequency
data.index.freq="QS-OCT"

data['ln_wpi'] = np.log(data['wpi'])
data['D.ln_wpi'] = data['ln_wpi'].diff()

# Graph data
fig, axes = plt.subplots(1, 2, figsize=(15,4))

# Levels
axes[0].plot(data.index._mpl_repr(), data['wpi'], '-')
axes[0].set(title='US Wholesale Price Index')

# Log difference
axes[1].plot(data.index._mpl_repr(), data['D.ln_wpi'], '-')
axes[1].hlines(0, data.index[0], data.index[-1], 'r')
axes[1].set(title='US Wholesale Price Index - difference of logs');

# Graph data
fig, axes = plt.subplots(1, 2, figsize=(15,4))

fig = sm.graphics.tsa.plot_acf(data.iloc[1:]['D.ln_wpi'], lags=40, ax=axes[0])
fig = sm.graphics.tsa.plot_pacf(data.iloc[1:]['D.ln_wpi'], lags=40, ax=axes[1])

# Fit the model
mod = sm.tsa.statespace.SARIMAX(data['ln_wpi'], trend='c', order=(1,1,(1,0,0,1)))
res = mod.fit(disp=False)
print(res.summary())
                                 SARIMAX Results                                 
=================================================================================
Dep. Variable:                    ln_wpi   No. Observations:                  124
Model:             SARIMAX(1, 1, [1, 4])   Log Likelihood                 386.033
Date:                   Fri, 12 Apr 2024   AIC                           -762.067
Time:                           15:02:29   BIC                           -748.006
Sample:                       01-01-1960   HQIC                          -756.355
                            - 10-01-1990                                         
Covariance Type:                     opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
intercept      0.0024      0.002      1.487      0.137      -0.001       0.006
ar.L1          0.7800      0.094      8.263      0.000       0.595       0.965
ma.L1         -0.3983      0.126     -3.173      0.002      -0.644      -0.152
ma.L4          0.3106      0.120      2.591      0.010       0.076       0.545
sigma2         0.0001    9.8e-06     11.111      0.000    8.97e-05       0.000
===================================================================================
Ljung-Box (L1) (Q):                   0.01   Jarque-Bera (JB):                45.05
Prob(Q):                              0.90   Prob(JB):                         0.00
Heteroskedasticity (H):               2.58   Skew:                             0.29
Prob(H) (two-sided):                  0.00   Kurtosis:                         5.91
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

ARIMA Postestimation: Example - Dynamic Forecasting

raw = pd.read_stata('data/friedman2.dta')
raw.index = raw.time
raw.index.freq = "QS-OCT"
data = raw.loc[:'1981']

# Variables
endog = data.loc['1959':, 'consump']
exog = sm.add_constant(data.loc['1959':, 'm2'])
nobs = endog.shape[0]

# Fit the model
mod = sm.tsa.statespace.SARIMAX(endog.loc[:'1978-01-01'], exog=exog.loc[:'1978-01-01'], order=(1,0,1))
fit_res = mod.fit(disp=False, maxiter=250)
print(fit_res.summary())
                               SARIMAX Results                                
==============================================================================
Dep. Variable:                consump   No. Observations:                   77
Model:               SARIMAX(1, 0, 1)   Log Likelihood                -243.316
Date:                Fri, 12 Apr 2024   AIC                            496.633
Time:                        15:06:01   BIC                            508.352
Sample:                    01-01-1959   HQIC                           501.320
                         - 01-01-1978                                         
Covariance Type:                  opg                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          0.6779     18.492      0.037      0.971     -35.565      36.921
m2             1.0379      0.021     50.329      0.000       0.997       1.078
ar.L1          0.8775      0.059     14.859      0.000       0.762       0.993
ma.L1          0.2771      0.108      2.572      0.010       0.066       0.488
sigma2        31.6978      4.683      6.769      0.000      22.520      40.876
===================================================================================
Ljung-Box (L1) (Q):                   0.32   Jarque-Bera (JB):                 6.05
Prob(Q):                              0.57   Prob(JB):                         0.05
Heteroskedasticity (H):               6.09   Skew:                             0.57
Prob(H) (two-sided):                  0.00   Kurtosis:                         3.76
===================================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
# get results for the full dataset but using the estimated parameters (on a subset of the data)

mod = sm.tsa.statespace.SARIMAX(endog, exog=exog, order=(1,0,1))
res = mod.filter(fit_res.params)
# In-sample one-step-ahead predictions
predict = res.get_prediction()
predict_ci = predict.conf_int()
# Dynamic predictions
predict_dy = res.get_prediction(dynamic='1978-01-01')
predict_dy_ci = predict_dy.conf_int()
# Graph
fig, ax = plt.subplots(figsize=(9,4))
npre = 4
ax.set(title='Personal consumption', xlabel='Date', ylabel='Billions of dollars')

# Plot data points
data.loc['1977-07-01':, 'consump'].plot(ax=ax, style='o', label='Observed')

# Plot predictions
predict.predicted_mean.loc['1977-07-01':].plot(ax=ax, style='r--', label='One-step-ahead forecast')
ci = predict_ci.loc['1977-07-01':]
ax.fill_between(ci.index, ci.iloc[:,0], ci.iloc[:,1], color='r', alpha=0.1)
predict_dy.predicted_mean.loc['1977-07-01':].plot(ax=ax, style='g', label='Dynamic forecast (1978)')
ci = predict_dy_ci.loc['1977-07-01':]
ax.fill_between(ci.index, ci.iloc[:,0], ci.iloc[:,1], color='g', alpha=0.1)

legend = ax.legend(loc='lower right')

# Prediction error

# Graph
fig, ax = plt.subplots(figsize=(9,4))
npre = 4
ax.set(title='Forecast error', xlabel='Date', ylabel='Forecast - Actual')

# In-sample one-step-ahead predictions and 95% confidence intervals
predict_error = predict.predicted_mean - endog
predict_error.loc['1977-10-01':].plot(ax=ax, label='One-step-ahead forecast')
ci = predict_ci.loc['1977-10-01':].copy()
ci.iloc[:,0] -= endog.loc['1977-10-01':]
ci.iloc[:,1] -= endog.loc['1977-10-01':]
ax.fill_between(ci.index, ci.iloc[:,0], ci.iloc[:,1], alpha=0.1)

# Dynamic predictions and 95% confidence intervals
predict_dy_error = predict_dy.predicted_mean - endog
predict_dy_error.loc['1977-10-01':].plot(ax=ax, style='r', label='Dynamic forecast (1978)')
ci = predict_dy_ci.loc['1977-10-01':].copy()
ci.iloc[:,0] -= endog.loc['1977-10-01':]
ci.iloc[:,1] -= endog.loc['1977-10-01':]
ax.fill_between(ci.index, ci.iloc[:,0], ci.iloc[:,1], color='r', alpha=0.1)

legend = ax.legend(loc='lower left');
legend.get_frame().set_facecolor('w')

머신러닝, 딥러닝

머신러닝과 딥러닝 기반의 시계열 모델은 전통적인 통계 기반 모델링 방법의 한계를 극복하고, 비선형성, 복잡한 패턴 인식, 대규모 데이터 처리 등에서 뛰어난 성능을 보인다. 이러한 모델들은 다양한 분야에서 시계열 데이터의 예측, 분류, 패턴 인식 등에 활용된다.

  • Random Forest, Boosting, SVM
  • RNN, LSTM, Transformer 등