🖇 정상성이 왜 중요한가?
🖇 확률적 시계열과 정상성
🖇 정상성 (Stationarity)
🖇 비정상성 (Non-Stationarity)
🖇 정상성 검정 방법
🖇 정상성 부여 방법
앞선 글에서도 언급되었지만, 시계열 분석에서 정상성(Stationarity)은 매우 중요하게 작용하는 개념이다.
시계열 데이터는 시간의 흐름에 따라 관측된 값들의 연속이며, 이 연속적인 데이터의 통계적 특성이 시간에 따라 일정하게 유지되는지 여부가 '정상성'의 여부를 판단하는 기준이 된다.
이 글에서는 정상성이 무엇인지 살펴보기에 앞서 정상성이 왜 중요한지, 정상성과 비정상성의 차이는 무엇인지, 그리고 시계열이 정상성을 갖추었는지를 어떻게 판단할 수 있는지 그 방법에 대해 다루고 있다. 한 번에 바로 이해가 쉽지 않아 최대한 예시를 들어 설명해 보았다.
시계열 데이터를 분석하는 궁극적인 목적 중 하나는 과거의 데이터를 바탕으로 미래를 예측하는 것이다.
미래의 데이터를 예측하려고 한다면 적어도 두 가지의 전제는 반드시 필요하다.
이때 중요한 가정은 과거에 나타난 통계적 특성이 앞으로도 유사하게 유지될 것이라는 점이다. 과거 시점(t-10 ~ t-1)의 시계열 특성이 미래 시점(t ~ t+10)에도 적용 가능해야 의미 있는 예측이 가능하다.
만약 시계열의 특성이 시간에 따라 변한다면 과거로부터 추정한 모델은 미래 예측에 부적합해질 수 있다. 이처럼 시간에 따른 통계적 성질의 일관성을 보장하기 위한 조건이 정상성이다.
시계열 분석은 대부분 데이터를 확률적 과정(stochastic process)의 결과물로 해석하는 관점을 취한다.
이는 관측된 시계열 데이터가 어떤 통계적 메커니즘에 따라 생성된 확률 변수들의 집합이라는 가정을 바탕으로 한다.
이러한 확률적 시계열은 매 시간마다 특정 확률분포를 따르는 랜덤 변수들이 시간의 흐름에 따라 순서대로 나타난 것으로 이해할 수 있다. 예를 들어, 매일의 주가, 기온, 환율 등은 모두 어떤 확률적 패턴을 따라 움직인다고 볼 수 있다. 따라서 우리는 전체 데이터가 어떤 구조나 경향을 가지고 있는지를 파악하고자 할 때 이 확률적 시계열을 설명할 수 있는 수학적 특성에 주목하게 된다.
하지만 실제로 관측되는 데이터가 어떤 분포를 따르는지 완벽하게 아는 경우는 드물다. 그렇기 때문에 시계열 모델링을 가능하게 하기 위한 몇 가지 전제 조건이 필요한데, 그 중 하나가 정상성(stationarity)이다.
정상성은 예측 가능성과 모델 적용 가능성을 판단하는 데 있어 매우 중요한 기준이 된다. 아래에서 하나씩 살펴보자.
정상성이란 시계열의 통계적 특성이 시간의 흐름에 따라 변하지 않고 일정한 상태를 말한다.
여기서 말하는 통계적 특성이란 대표적으로 평균, 분산, 그리고 공분산(자기상관)을 의미한다. 시계열이 정상성을 가진다면 어떤 시점을 기준으로 분석하든 전체적인 통계 구조가 동일하게 유지된다.
조금 더 이해하기 쉽게 예시와 함께 살펴보자.
💡 정상성은 시간이 지나도 통계적 성질이 변하지 않는 상태를 말한다.
예시 1: 정상 시계열
- 하루하루 온도가 약간씩 오르내리긴 해도, 평균 기온이 20도쯤으로 비슷하고 변동폭도 일정하다.
- 즉, 평균과 분산이 시간이 지나도 바뀌지 않는다.
➡ 이런 데이터는 정상성(stationary)을 가진다고 한다.예시 2: 비정상 시계열
- 온난화처럼 날이 갈수록 기온이 계속 오르고 있는 상황이다. 즉, 시간이 지날수록 평균이 점점 올라가고 있다.
➡ 이런 데이터는 비정상성(non-stationary)을 가진다고 한다. 시간에 따라 평균이 계속 변하기 때문이다.
💡 그렇다면 추세가 있으면 무조건 비정상일까?
거의 맞다고 볼 수 있다.
"추세"는 시간이 지나면서 평균이 바뀌고 있다는 뜻이기 때문이다.예를 들어
- 유튜브 채널 구독자 수가 계속 늘고 있다.
→ 추세가 있음 → 평균이 변함 → 비정상하지만
- 그 추세가 일정하게 바뀌는 패턴이라면,
- 어떤 검정(KPSS)은 “추세는 있지만 나머지는 안정적이다”라고 해서 "추세를 포함한 정상성"이라고 보기도 한다.
정리하자면, 추세가 있으면 대부분 비정상이라고 생각하면 된다.
약정상성을 갖는 시계열은 시간에 따라 평균, 분산, 공분산의 기본적인 통계적 특성이 변하지 않는다는 특징을 가진다.
이 조건은 시계열 분석에서 가장 널리 사용되는 정상성의 정의로, 아래의 세 가지를 만족해야 한다.
평균이 일정하다
: 어떤 시점 에서도 기대값 은 항상 일정한 값 를 가져야 한다.
분산이 일정하다
: 어떤 시점 에서도 시계열의 분산 이 유한하고 일정해야 한다.
공분산이 시점 ttt에 의존하지 않고 시차 에만 의존한다
:
: 두 시점 간의 거리에만 의존하고 실제 시점이 언제인지는 중요하지 않다.
이처럼 약정상성을 띠는 시계열 데이터는 어느 시점()에 관측해도 확률 과정의 성질(, )이 변하지 않는것을 말한다.
이러한 성질을 가지는 시계열은 통계 모델링, 특히 ARIMA와 같은 예측 모델에서 안정적인 성능을 발휘할 수 있다.
비정상성을 가진 시계열은 시간에 따라 평균이나 분산이 변하거나, 일정한 추세를 가지는 경우를 말한다. 이런 데이터는 분석이나 예측이 어렵고, 모델이 잘 작동하지 않기 때문에 반드시 사전에 처리가 필요하다.
이를 위해 시계열 데이터를 정상성 있는 형태로 변환하는 전처리 과정이 요구되며, 대표적인 방법으로는 차분(differencing), 로그 변환, 선형 추세 제거(detrending) 등이 있다.
💡 정상성은 시계열 분석의 기반이 되는 전제 조건으로, 데이터를 어떻게 다루고 어떤 모델을 선택할지에 대한 중요한 판단 기준이 된다.
💡 시계열 분석을 시작하기 전에 주어진 데이터가 정상성을 만족하는지 반드시 확인하고, 필요하다면 적절한 방법을 통해 이를 확보해야 한다.
시계열이 정상성을 띠는지를 확인하기 위해 대표적으로 두 가지 통계 검정이 사용된다.
Kwiatkowski-Phillips-Schmidt-Shin Test
- 귀무가설(H₀): 시계열은 정상이다.
- 대립가설(H₁): 시계열은 비정상이다.
- 해석
- p-value < 0.05 → 귀무가설 기각 → 비정상 시계열
- p-value ≥ 0.05 → 귀무가설 채택 → 정상 시계열
# kpss 불러오기
from statsmodels.tsa.stattools import kpss
# 시계열 테스트 데이터
time_series_data_test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# KPSS 검정 수행
kpss_outputs = kpss(time_series_data_test)
# 검정 결과 출력
print('KPSS test 결과 : ')
print('--'*15)
print('KPSS Statistic:', kpss_outputs[0])
print('p-value:', kpss_outputs[1])
KPSS test 결과 :
------------------------------
KPSS Statistic: 0.5941176470588235
p-value: 0.023171122994652404
KPSS 함수는 kpss_stat, p_value, lags, crit 총 네가지 값을 반환한다. 가장 직관적인 방법은 p-value를 이용해 해석하는 것이다.
Augmented Dickey-Fuller Test
- 귀무가설(H₀): 시계열은 단위근을 가진다 → 비정상 시계열
- 대립가설(H₁): 시계열은 단위근이 없다 → 정상 시계열
- 해석
- p-value < 0.05 → 귀무가설 기각 → 정상 시계열
- p-value ≥ 0.05 → 귀무가설 채택 → 비정상 시계열
# adfuller 불러오기
from statsmodels.tsa.stattools import adfuller
# 시계열 테스트 데이터
time_series_data_test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# ADF 검정 수행
adf_outputs = adfuller(time_series_data_test)
# 검정 결과 출력
print('ADF Test 결과 : ')
print('--'*15)
print('ADF Statistic:', adf_outputs[0])
print('p-value:', adf_outputs[1])
ADF함수는 adf, pvalue, usedlag, nobs, critical values 등을 반환하는데 이 역시 p-value를 활용하는 것이 가장 직관적이다.
💡 단위근과 정상성
시계열의 정상성은 종종 AR(자기회귀) 모델의 뿌리(근, root)와도 연결된다. AR 모델의 특성 방정식의 근의 절대값이 1보다 크면 정상, 절대값이 1이면 단위근(Unit Root)이 존재하며 비정상으로 간주된다. 즉, 단위근을 통해 정상성을 확인할 수 있는 것이다.
💡 KPSS 검정과 ADF 검정의 차이
- KPSS 검정은 정상성을 귀무가설, ADF는 비정상성을 귀무가설로 설정한다.
- 확정적 추세(Deterministic Trend)가 존재하는 경우, KPSS는 비정상으로 판정할 가능성이 크다. 따라서 두 검정을 함께 사용해 교차 검증하는 방식이 가장 안정적이다. 이와 관련해서 다음 글에서 다뤄 볼 예정이다.
- plot, ACF/PACF 등을 통해 시각적으로도 stationary한지 파악하는 것이 중요하다.
비정상 시계열을 분석 가능한 형태로 만들기 위해서는 정상성 확보를 위한 변환이 필요하다. 이때는 분산을 일정하게 만들거나, 평균을 일정하게 만드는 방식으로 접근한다.
① 로그 변환 (log transformation)
로그 변환은 변동성이 큰 데이터를 스케일 조정하여 분산을 안정화시킬 수 있다.
import numpy as np
import matplotlib.pyplot as plt
time_series_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
time_series_data_log = np.log(time_series_data)
# 시각화
plt.plot(time_series_data, label='Original')
plt.plot(time_series_data_log, label='Log Transformed')
plt.legend(); plt.show()
① 회귀 (regression detrending)
선형 회귀를 이용해 추세를 모델링한 후, 실제값과 예측값의 차이를 통해 평균을 제거할 수 있다.
mean_adjusted = y - ŷ 형태로 변환
② 평활 (Smoothing)
이동 평균(rolling mean), 지수 평활법 등을 통해 잡음을 줄이고 평균 수준을 일정하게 유지시킨다.
import pandas as pd
import random
df = pd.DataFrame({'orig_value': [random.uniform(0, 100) for _ in range(100)]})
df['smoothed'] = df['orig_value'].rolling(5).mean()
df.plot(title='Smoothing 적용 결과')
③ 차분 (Differencing)
연속된 관측값의 차이를 계산해 추세나 계절성의 영향을 제거한다.
많은 비정상 시계열은 정상 시계열의 누적합(Integrated Process)으로 생성된다. 이런 경우에는 차분을 통해 다시 정상성 구조를 회복할 수 있다.
많은 비정상적 시계열은 누적 과정(Integrated Process)이고 정상적 시계열이 누적되어 비정상적 시계열을 이루었기 때문에, 다시 누적된 것을 차분해줌으로써 그 이면의 정상적 과정을 우리가 볼 수 있게 되는 것이다.
즉, 누적된 과정을 원래의 정상적 과정으로 되돌리는 것이 차분의 핵심이다.
yₜ* = yₜ - yₜ₋₁df['diff'] = df['orig_value'].diff()
df.plot(title='차분 결과')
시계열 데이터 분석은 완벽한 미래 예측을 보장하지는 않는다.
어떤 예측하지 못한 외부적 변수에 의해 시계열 데이터 분석의 전제가 되는 정상성이 훼손될 여지가 있기 때문이다.
분석 전에 시계열의 정상성 여부를 판단하고, 필요하다면 차분, 로그 변환, 회귀 제거 등의 방법을 통해 정상성을 확보하는 작업이 선행되어야 한다. 그렇게 한다면 시계열 데이터 분석은 프로세스 내재적인 시간적 변화를 묘사하는데 훌륭한 성능을 보일 수 있을 것이다.
앞으로 ACF/PACF 해석, ARIMA 모델링, 예측 등 시계열의 다양한 분석 기법을 다룰 때도 이 정상성 개념이 기반이 된다는 점을 기억하자.