SARIMA 모델링 해석
원 데이터
- ADF 정상성 테스트 -> p가 0.05보다 작으므로 정상상태임.
- 테스트는 정상으로 나오지만, 계절성과 추세가 있는 것으로 보임
- p:2? (PACF 기준 lag 2까지 유의하고 그 뒤로는 유의하지 않음)
- d:1? (ACF를 봤을때 추세가 어느정도 보이므로 추세 1차 차분)
- q:1? (ACF 기준 필요성 인지)
- P:1? (PACF 기준 lag 24 간격 유의성으로 필요성 인지)
- D:1? (계절성 차분 필요함 인지)
- Q:2? (ACF 기준 lag 24 간격 유의성으로 필요성 인지)
- m:24 (ACF/PACF 기준 lag 24 간격으로 유의한 진동 존재)
계절 차분 후 데이터
- ADF 정상성 테스트 -> p가 0.05보다 작으므로 정상상태임.
- 하지만 계절성이 반복되고 있기 때문에 추세제거가 필요해 보임
- p:1? (PACF 기준 lag 1까지 유의하고 그 뒤로는 유의하지 않음)
- d:1? (ADF가 대중가설을 기각하고 그래프 상 추세가 보이므로 일단 추세 1차 차분)
- q:3? (ACF 기준 필요성 인지)
- P:2? (PACF 기준 lag 24 간격 유의성으로 필요성 인지)
- D:1 (계절성 차분 필요)
- Q:0? (ACF 기준 계절 시차는 유의한 간격안에 들어와 있음)
- m:24 (ACF/PACF 기준 lag 24 간격으로 유의한 진동 크게 사라짐)
계절성 및 추세차분 후 데이터
- ADF 정상성 테스트 -> p가 0.05보다 작으므로 정상상태임.
- 진동이 거의 사라졌음
- p:max4 (PACF 기준 lag 4까지 유의하고 그 뒤로는 유의하지 않음, 그래프가 lag4까지 튐)
- d:1 (ADF가 대중가설을 기각하고 그래프 상 추세도 없어졌으므로 추세 1차 차분 확정)
- q:max4 (ACF 기준 lag 4까지 유의하고 그 뒤로는 유의하지 않음, 그래프가 lag4까지 튐)
- P:max2 (PACF 기준 lag 24 간격으로 2번정도 유의함)
- D:1 (계절성 차분 필요함 인지)
- Q:max1 (ACF 기준 lag 24 간격으로 1번정도 유의함)
- m:24 (lag 24 간격으로 진동 존재)
잔차검증 : SARIMA(4,1,4)(2,1,1,24)
- ADF 정상성 테스트 -> p가 0.05보다 작으므로 정상상태임.
- ACF와 PACF는 유의한 수준을 보임 -> White Noise에 가깝다고 볼 수 있음
호흡기질환 사망자수 SARIMA 모델링
추세만 반영 : SARIMA(1,0,1)(0,0,0,0) -> ARMA(1,1)
import warnings
warnings.filterwarnings('always')
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
# 데이터로딩 및 확인
data = sm.datasets.get_rdataset("deaths", "MASS")
raw = data.data
raw.value = np.log(raw.value)
raw.plot(x='time', y='value')
plt.show()
# ACF/PACF 확인
plt.figure(figsize=(10, 8))
sm.graphics.tsa.plot_acf(raw.value.values, lags=50, ax=plt.subplot(211))
plt.xlim(-1, 51)
plt.ylim(-1.1, 1.1)
plt.title("ACF")
sm.graphics.tsa.plot_pacf(raw.value.values, lags=50, ax=plt.subplot(212))
plt.xlim(-1, 51)
plt.ylim(-1.1, 1.1)
plt.title("PACF")
plt.tight_layout()
plt.show()
# ARMA(1,1) 모델링
fit = sm.tsa.SARIMAX(raw.value, trend='c', order=(1,0,1), seasonal_order=(0,0,0,0)).fit()
display(fit.summary())
# 잔차진단
fit.plot_diagnostics(figsize=(10,8))
plt.tight_layout()
plt.show()
- Skew, Kurtosis를 봤을 때 정규분포처럼 보임
- JB테스트 결과 정규분포가 아님
- Heteroskedasticity 결과 등분산성이라고 판단
- Ljung-BOX 테스트 결과 자기 상관성이 있다고 판단
- 즉, 정규분포가 아니며 등분산성이 있으며 자기상관성이 있는 모델
잔차진단
- 계절성 시차의 영향력이 보임
- 자기상관도 ACF를 봤을때 잔존하고 있는 것이 보임
계절성 모델링 추가 : SARIMA(1,0,1)(1,1,1,12)
- M : 12 -> ACF를 봤을 때 12만큼 반복됨
# SARIMA 모델링
fit = sm.tsa.SARIMAX(raw.value, trend='c', order=(1,0,1), seasonal_order=(1,1,1,12)).fit()
display(fit.summary())
# 잔차진단
fit.plot_diagnostics(figsize=(10,8))
plt.tight_layout()
plt.show()
- AIC, BIC가 훨씬(2배정도) 작아짐
- Skew, Kurtosis를 봤을 때 정규분포가 아님.
- JB테스트 결과 정규분포가 아님
- Heteroskedasticity 결과 등분산성이라고 판단
- Ljung-BOX 테스트 결과 자기 상관성이 없다고 판단
- 잔차진단 결과 훨씬 안정화 되었음
- 정규분포가 아니라고 판단되는 것은 OUTLIER 때문임. -> 실제로 정규분포에 가깝다고 보면됨
- Trend와 season 요소가 잘 적합되어 잔차가 White Noise에 가까워졌음
항공사 승객수요 SARIMA 모델링
# 라이브러리 호출
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
# 데이터 준비
data = sm.datasets.get_rdataset("AirPassengers")
raw = data.data.copy()
# 데이터 전처리
## 시간 인덱싱
if 'time' in raw.columns:
raw.index = pd.date_range(start='1/1/1949', periods=len(raw['time']), freq='M')
del raw['time']
## 정상성 확보
plt.figure(figsize=(12,8))
raw.plot(ax=plt.subplot(221), title='Y', legend=False)
np.log(raw).plot(ax=plt.subplot(222), title='log(Y)', legend=False)
raw.diff(1).plot(ax=plt.subplot(223), title='diff1(Y)', legend=False)
np.log(raw).diff(1).plot(ax=plt.subplot(224), title='diff1(log(Y))', legend=False)
plt.show()
추세 1 차분
# ARIMA 모델링 (raw)
fit = sm.tsa.SARIMAX(raw.value, trend='c', order=(1,1,1), seasonal_order=(0,0,0,0)).fit()
display(fit.summary())
# 잔차진단
fit.plot_diagnostics(figsize=(10,8))
plt.tight_layout()
plt.show()
로그를 취한 후 추세 1차분 -> 로그의 효과 체크
# ARIMA 모델링 (log(raw))
fit = sm.tsa.SARIMAX(np.log(raw.value), trend='c', order=(1,1,1), seasonal_order=(0,0,0,0)).fit()
display(fit.summary())
# 잔차진단
fit.plot_diagnostics(figsize=(10,8))
plt.tight_layout()
plt.show()
- AIC, BIC가 단순히 1회 차분했을 때보다 훨씬 작아졌음
- 통계량을 봤을때 여전히 정규분포가 아니고 자기상관성이 있음
- 하지만 잔차진단을 했을 때 분산이 일정하며, 정규분포에 가까워 졌으며, ACF도 좀더 안정화 되었음
- 즉 log를 취하면 분산을 잡아주기 때문에 지표가 더 좋음
SARIMAX(1,1,1)(1,1,1,12) 모델링
# SARIMA 모델링 (log(raw))
fit = sm.tsa.SARIMAX(np.log(raw.value), trend='c', order=(1,1,1), seasonal_order=(1,1,1,12)).fit()
display(fit.summary())
# 잔차진단
fit.plot_diagnostics(figsize=(10,8))
plt.tight_layout()
plt.show()
- AIC, BIC가 훨씬 작아짐
- 파라미터들도 더 유의해짐
- 통계량을 봤을 때, 정규분포에 가까우며, 자기상관도 없으며, 등분산도 만족함
- 잔차분석 결과도 정규분포에 거의 가까우며, ACF도 자기상관이 없는 것을 볼 수 있음
결론
- SARIMA 함수는 정상화를 해줄 필요는 없음 -> SARIMA는 비정상데이터를 그대로 반영함
- raw데이터만 넣고 log를 취할지 말지만 결정하면 됨
- 아직까지는 x를 사용하지 않았음
- Y = c + f(x) + e => Y = SARIMA + f(x) + e 로 바꾼것이며 f(x)를 사용하지 않았으니
- Y = SARIMAX + e 가 된것이며, 이것만 해도 잔차가 WH에 가까워졌음
- Y = c + f(x) + e => Y = SARIMA + f(x) + e 로 바꾼것이며 f(x)를 사용하지 않았으니
- 우리가 쓰는 것은 SARIMA임.
해당 포스팅은 패스트캠퍼스의 <파이썬을 활용한 시계열 데이터 분석 A-Z 올인원 패키지> 강의를 듣고 정리한 내용입니다
728x90
반응형
'Data Analysis & ML > 시계열분석' 카테고리의 다른 글
[시계열분석] 시계열 알고리즘 - 선형확률과정의 분석사이클 자동화 (Auto ARIMA) (0) | 2021.09.26 |
---|---|
[시계열분석] 시계열 알고리즘 - 선형확률과정의 분석사이클 (0) | 2021.09.26 |
[시계열분석] 시계열 알고리즘 - 적분 선형확률 과정(2) - SARIMA (1) | 2021.09.25 |
[시계열분석] 시계열 알고리즘 - 적분 선형확률 과정(1) - ARIMA (0) | 2021.09.11 |
[시계열분석] 시계열 알고리즘 - 일반 선형확률 과정(4) - ARMAX / SARMAX (0) | 2021.08.28 |