Data Analysis & ML/시계열분석

[시계열분석] 정상성 변환 방법론

YSY^ 2021. 6. 27. 17:57

비정상성(Non-stationary)의 정상성(Stationary) 변환

  • 목적: 정상성 확보를 통해 안정성이 높아지고 예측력 향상
  • 장점: 절약성 원칙(Principle of Parsimony)(파라미터를 적게 써도됨)에 따라 적은 모수만으로 모델링 가능하기에 과적합 확률이 줄어듬
  • 방법: 제곱, 루트, 로그, 차분 등
  • 비정상 데이터는 범위가 무제한, 하지만 정상성데이터는 범위가 제한되기 때문에 예측이 더 쉬워지지만 무조건 정상성이 필요한 것은 아님.
  • 정상성 변환을 하면 모델이 단조로워지기 때문에 과적합이 일어날 확률이 낮아짐

  • Trend: a/c/e/f/i
  • Seasonality: d/h/i
  • Cycle: g
  • Non-constant Variance: i
  • 정상성 만족 : b

1) 로그변환

  • 시간흐름에 비례하여 값이 커지는 경우(분산 증가)
  • 비정상 확률 과정으로 표준편차가 자료의 크기에 비례하여 증가하거나 지수함수적으로 증가하는 경우
  • 로그 변환한 확률 과정의 분산은 일정하기에 추세 제거로 기댓값이 0이 되면 정상 과정으로 모형화 가능

2) 차분(Difference):특정 시점 또는 시점들의 데이터가 발산할 경우 시점간 차분(변화량)으로 정상성 변환 가능

  • 계절성(Seasonality,St): 특정한 달/요일에 따라 기대값이 달라지는 것, 변수 더미화를 통해 추정 가능
    • 계절성 제거: 1) 계절성 추정(f(t)) 후 계절성 제거를 통한 정상성 확보
      • 확률과정의 계절변수 더미화를 통해 기댓값 함수를 알아내는 것
      • 확률과정(Yt)이 추정이 가능한 결정론적 계절성함수(f(t))와 정상확률과정(Yst)의 합
    • 계절성 제거: 2) 차분 적용 후 계절성 제거를 통한 정상성 확보
  • 추세(Trend, TtTt): 시계열이 시간에 따라 증가, 감소 또는 일정 수준을 유지하는 경우
    • 추세 제거: 1) 추세 추정(f(t)) 후 추세 제거를 통한 정상성 확보
      • 확률과정의 결정론적 기댓값 함수를 알아내는 것
      • 확률과정(Yt)이 추정이 가능한 결정론적 추세함수(f(t))와 정상확률과정(Yst)의 합
    • 추세 제거: 2) 차분 적용후 추세 제거를 통한 정상성 확보

3) Box-Cox 변환: 정규분포가 아닌 자료를 정규분포로 변환하기 위해 사용

  • 거듭곱변환(power transformation) : 제곱근과 세제곱근을 사용
  • 모수(parameter)λ를 가지며, 보통 여러가지λ값을 시도하여 가장 정규성을 높여주는 값을 사용
  • 박스-칵스(Box-Cox) 변환에서 로그는 항상 자연 로그(즉, 밑이 e).
  • λ=0이면, 자연 로그를 사용, λ≠0이면, 어떤 단순한 눈금에 따라 거듭곱 변환(power transformation)을 사용

 

대기중 CO2 농도 추세 제거

추세가 있는 데이터

# 방법(1) : 잔차로 추세와 계절성이 제거 된 것을 추정
plt.plot(raw.time, result.resid)
plt.show()

display(stationarity_adf_test(result.resid, []))
display(stationarity_kpss_test(result.resid, []))

sm.graphics.tsa.plot_acf(result.resid, lags=100, use_vlines=True)
plt.tight_layout()
plt.show()

 

  • adf(추세에 민감한 통계량) : 비정상(추세가 남아있음)
  • kpss(계절성에 민감한 통계량) : 정상
  • acf그래프는 아직 계절성이 남아있다고 볼 수 있음
# 방법(2) : 차분1회
plt.plot(raw.time[1:], raw.value.diff(1).dropna())
plt.show()

display(stationarity_adf_test(raw.value.diff(1).dropna(), []))
display(stationarity_kpss_test(raw.value.diff(1).dropna(), []))

sm.graphics.tsa.plot_acf(raw.value.diff(1).dropna(), lags=100, use_vlines=True)
plt.tight_layout()
plt.show()

  • lags=100 이란 lags 100개의 수치를 전부 알려달라는 내용이다. lag란 데이터상 과거의 몇 번째 뒤로 간 데이터를 의미한다. 만약 lag=1이고 시간 설정을 일로 했다면, 전날 데이터와 현재 데이터를 비교하는 것이다.
  • adf(추세에 민감한 통계량) : 정상
  • kpss(계절성에 민감한 통계량) : 정상
  • acf그래프는 아직 계절성이 남아있다고 볼 수 있으며 추세는 어느정도 제거 된것을 볼 수 있음

호흡기 질환 사망자수 계절성 제거

# 계절성 제거 및 정상성 확인 -> 차분
sm.graphics.tsa.plot_acf(raw.value, lags=50, use_vlines=True)
plt.show()

plt.plot(raw.time, raw.value)
plt.title('Raw')
plt.show()
seasonal_lag = 3 #3개월 차분했을 때
plt.plot(raw.time[seasonal_lag:], raw.value.diff(seasonal_lag).dropna(), label='Lag{}'.format(seasonal_lag))
seasonal_lag = 6 # 6개월 차분했을 때
plt.plot(raw.time[seasonal_lag:], raw.value.diff(seasonal_lag).dropna(), label='Lag{}'.format(seasonal_lag))
seasonal_lag = 12 # 12개월 차분했을 때
plt.plot(raw.time[seasonal_lag:], raw.value.diff(seasonal_lag).dropna(), label='Lag{}'.format(seasonal_lag))
plt.title('Lagged')
plt.legend()
plt.show()

- 3개월 차분(파란색), 6개월 차분(주황색)은 아직 계절성이 남아있는 것을 볼수 있지만, 12개월 차분(녹색)은 계절성이 많이 없어진 것을 볼 수 있다.

#lag 6일 때 통계량 및 시각화
seasonal_lag = 6
display(stationarity_adf_test(raw.value.diff(seasonal_lag).dropna(), []))
display(stationarity_kpss_test(raw.value.diff(seasonal_lag).dropna(), []))
sm.graphics.tsa.plot_acf(raw.value.diff(seasonal_lag).dropna(), lags=50, 
                         use_vlines=True, title='ACF of Lag{}'.format(seasonal_lag))
plt.tight_layout()
plt.show()

  • adf(추세에 민감한 통계량) : 정상
  • kpss(계절성에 민감한 통계량) : 정상
  • acf그래프는 아직 계절성이 남아있음
# 12개월 차분했을 때 통계량과 시각화
seasonal_lag = 12
display(stationarity_adf_test(raw.value.diff(seasonal_lag).dropna(), []))
display(stationarity_kpss_test(raw.value.diff(seasonal_lag).dropna(), []))
sm.graphics.tsa.plot_acf(raw.value.diff(seasonal_lag).dropna(), lags=50, 
                         use_vlines=True, title='ACF of Lag{}'.format(seasonal_lag))
plt.tight_layout()
plt.show()

  • adf(추세에 민감한 통계량) : 정상
  • kpss(계절성에 민감한 통계량) : 정상
  • acf그래프에는 계절성이 보이지 않음

랜덤워크의 정상성 변환

실제값 = 이전 시점의 값 + 백색 잡음의 값

-> 따라서 랜덤워크 값을을 차분하면 백색잡음이 나옴

임의의 랜덤워크 데이터

# 차분 전 랜덤워크 정상성 테스트
display('Before a difference:')
display(stationarity_adf_test(random_walk, []))
display(stationarity_kpss_test(random_walk, []))
sm.graphics.tsa.plot_acf(random_walk, lags=100, use_vlines=True)
plt.tight_layout()
plt.show()

  • adf(추세에 민감한 통계량) : 비정상
  • kpss(계절성에 민감한 통계량) : 비정상
  • acf그래프 : 추세가 있음(비정상)
# 차분 후 랜덤워크 정상성 테스트
display('After a difference:')
display(stationarity_adf_test(pd.Series(random_walk).diff(1).dropna(), []))
display(stationarity_kpss_test(pd.Series(random_walk).diff(1).dropna(), []))
sm.graphics.tsa.plot_acf(pd.Series(random_walk).diff(1).dropna(), lags=100, use_vlines=True)
plt.tight_layout()
plt.show()

  • adf(추세에 민감한 통계량) : 정상
  • kpss(계절성에 민감한 통계량) : 정상
  • acf그래프 : 정상

 

해당 포스팅은 패스트캠퍼스의 <파이썬을 활용한 시계열 데이터 분석 A-Z 올인원 패키지> 강의를 듣고 정리한 내용입니다

728x90
반응형