My Data Story
시계열 데이터 분석 절차(6/6) - 분석 종료 위한 잔차 진단 본문
◈ '시계열 데이터 분석 절차' 목차 ◈
1. 시계열 데이터 분석 절차(1/6) - 시계열 데이터 패턴 추출
2. 시계열 데이터 분석 절차(2/6) - 시계열 데이터 분리
3. 시계열 데이터 분석 절차(3/6) - 시계열 데이터 전처리(1)
4. 시계열 데이터 분석 절차(4/6) - 시계열 데이터 전처리(2)
5. 시계열 데이터 분석 절차(5/6) - 시계열 레퍼런스 모델 구현 및 성능 확인
6. 시계열 데이터 분석 절차(6/6) - 분석 종료 위한 잔차 진단
레퍼런스 모델로 예측한 결과와 실제 결과 사이의 차이인 '잔차에 대한 분석'을 통해 추가적인 분석 방향에 대해 고민해야 한다.
1. 백색 소음
실제값과 예측값 차를 잔차라고 한다.
잔차를 살펴보았을 때 잔차에 아무런 패턴이 남아 있지 않다면 f(x)가 y를 잘 적합시켰다고 볼 수 있다.
레퍼런스 모델 생성 후 잔차 진단을 통해 추가적으로 어떤 방향으로 모델을 개선해나갈 수 있을 지에 대해 생각해볼 수 있다.
아무런 패턴이 남아 있지 않는 잔차를 '백색 소음(White Noise)'라고 한다.
백색 소음은 다음 2가지 속성을 만족해야 하며 하나라도 만족하지 못하면 모델이 개선의 여지가 있음을 의미한다.
- 잔차들은 정규 분포이고, (unbiased) 평균이 0과 일정한 분산을 가져야 함
- 잔차들이 시간의 흐름에 따라 상관성이 없어야 함
- 자기상관함수 (Autocorrelation Fundtion(ACF))를 통해 Autocorrelation=0 인지 확인
. 공분산(Covariance)
. 자기상관함수(Autocorrelation Function)
. 편자기상관함수(Partial Autocorrelation Function) : s와 k 사이의 시점들의 영향력(상관성)을 제거한 자기상관함수
. 자기상관 테스트 예시
2. 정상성 테스트
실제 데이터에서 추세나 계절성이 없는 것을 정상성 데이터라 한다.
2.1 시각화
잔차에 대해 시각화는 seaborn 패키지의 lmplot 통해서 확인 가능하다.
import seaborn as sns
sns.set(palette='muted', color_codes=True, font_scale=2)
#Residual Plotting
#Stationality(Trend) Analysis
Resid_tr_reg1['RowNum'] = Resid_tr_reg1.reset_index().index
sns.lmplot(data=Resid_tr_reg1, x='RowNum', y='Error',
fit_reg=True, line_kws={'color':'red'}, size=5.2, aspect=2, ci=99, sharey=True)
잔차에 대해 시각화하여 확인한 결과 잔차에 약간의 추세가 존재해보인다.
백색 소음과 거리가 멀어 보이며 정상성을 띄지 않는 것으로 판단된다.
2.2 통계량
정상성 테스트를 위해 Augmented Dickey-Fuller(ADF) test 를 진행한다.
- 가설확인
- 대중주장(귀무가설, Null Hypothesis) : 시계열 데이터는 단위근(Unit Root)이 있다. 비정상 상태이다. 시간 의존 구조이다.
- 나의주장(대립가설, Alternativa Hypothesis) : 시계열 데이터는 단위근이 없다. 정상 상태이다. 시간 의존 구조가 아니다. - 의사결정
- p-value >= 내 기준 (ex.0.05)
. 시계열 데이터가 대중 주장과 유사하기 때문에 대중 주장 참 & 나의 주장 거짓
. 시계열 데이터는 단위근이 있다. 비정상 상태이다. 시간 의존 구조이다.
- p-value < 내 기준 (ex.0.05)
. 시계열 데이터가 대중주장을 벗어나기 때문에 대중주장 거짓 & 나의 주장 참
. 시계열 데이터는 단위근이 없다. 정상 상태이다. 시간 의존 구조가 아니다.
import statsmodels.api as sm
#Checking Stationary
#Null Hypothesis: The Time-series is non-stationalry
sm.tsa.stattools.adfuller(Resid_tr_reg1['Error'])
#(실행결과) (Test Statics, p-value, Used Lag, Used Obervations,
# {p-value=1% statstics, p-value=5% statstics, p-value=10% statstics},
# Maximum information Criteria) 내용 출력
Stationarity = pd.Series(sm.tsa.stattools.adfuller(Resid_tr_reg1['Error'])[:4],
index=['Test Statics', 'p-value', 'Used Lag', 'Used Observation'])
for key, value in sm.tsa.stattools.adfuller(Resid_tr_reg1['Error'])[4] :
Stationarity['Critical Value(%s)'%key] = value
Stationarity['Maximum information Criteria'] = sm.tsa.stattools.adfuller(Resid_tr_reg1['Error'])[5]
Stationarity = pd.DataFrame(Stationarity, columns=['Stationarity'])
이 외에도 정상성 테스트를 위해 ADF-GLS test, Phillips-Perron test, Kwiatkowski Phillips Schmidt Shin test 등이 존재한다.
3. 정규분포 테스트
3.1 시각화
seaborn 패키지의 distplot()을 통해 잔차에 대해 히스토그램을 구현하고 정규분포를 띄는 지 확인할 수 있다.
import seaborn as sns
#Normal Distribution Analysis
#잔차에 대해 히스토그램 시각화 후 정규곡선에 가까운지 확인
sns.distplot(Resid_tr_reg1['Error'], norm_hist=True, fit=stats.norm)
#norm_hist : 잔차의 히스토그램에 대한 정규곡선 표현
#fit : 평균이0이고 등분산인 정규곡선 검정색으로 표현
잔차에 대한 히스토그램 시각화한 결과 정규분포를 띄는 것처럼 보인다.
3.2 통계량
정규분포 테스트를 위해 주로 Shapiro-Wilk test, Jarque-Bera test, Pearson's chi-squared test, D'Agostino's K-squared test 등을 많이 활용한다.
- 가설확인
- 대중주장(귀무가설, Null Hypothesis) : 데이터는 정규 분포 형태이다.
- 나의주장(대립가설, Alternativa Hypothesis) : 데이터는 정규 분포 형태가 아니다. - 의사결정
- p-value >= 내 기준 (ex.0.05)
. 데이터가 대중 주장과 유사하기 때문에 대중 주장 참 & 나의 주장 거짓
. 데이터가 정규 분포 형태이다.
- p-value < 내 기준 (ex.0.05)
. 데이터가 대중주장을 벗어나기 때문에 대중주장 거짓 & 나의 주장 참
. 데이터가 정규 분포 형태가 아니다.
import statsmodels.api as sm
import scipy as stats
#Checking of Normality
#Null Hypothesis: The residuals are normally distributed
stats.shapiro(Resid_tr_reg1['Error'])
#(실행결과) (Test statistics, p-value)
Normality = pd.DataFrame(stats.shapiro(Resid_tr_reg1['Error'],
index=['Normality'],
columns=['Test statistics', 'p-value']).T
4. 자기상관 테스트
4.1 시각화
자기상관 테스트를 위해 t시점과 t+@ 시점의 잔차간의 상관관계를 파악해야 한다.
아래 코드는 (t시점, t+1시점) 간의 상관관계, (t시점, t+5시점) 간의 상관관계, (t시점, t+10시점) 간의 상관관계, (t시점, t+50시점) 간의 상관관계에 대해 각각 시각화하는 코드이다.
import matplotlib.pyplot as plt
#Lag Analysis
figure, axes = plt.subplot(1, 4, figsize=(30,5))
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=1, ax=axes[0])
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=5, ax=axes[1])
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=10, ax=axes[2])
pd.plotting.lag_plot(Resid_tr_reg1['Error'], lag=50, ax=axes[3])
위 내용에 대해 하나의 그래프로 자기상관성을 확인할 수 있는 방법이 있다.
statsmodels 내에 있는 plot_acf()를 통해 자기상관성을 확인할 수 있다.
이때 lags 옵션은 t시점과 (t+'lags') 시점까지의 자기상관성을 나타내겠다는 의미이고, use_vlines 옵션은 자기상관성 여/부를 판단하는 유의 수준에 대한 구역을 표시하겠다는 의미이다.
plot_pacf() 는 편자기상관성을 표현한다.
#Autocorrelation Analysis
figure, axes = plt.subplot(2, 1, figsize=(12,5))
figure = sm.graphics.tsa.plot_acf(Resid_tr_reg1['Error'], lags=100, use_vlines=True, ax=axes[0])
figure = sm.graphics.tsa.plot_pacf(Resid_tr_reg1['Error'], lags=100, use_vlines=True, ax=axes[1])
4.2 통계량
자기상관 테스트를 위해 Durbin-Watson statistic 을 많이 활용한다.
- 가설확인
- 대중주장(귀무가설, Null Hypothesis) : 시계열 데이터의 Autocorrelation은 0이다. (존재하지 않는다.)
- 나의주장(대립가설, Alternativa Hypothesis) : 시계열 데이터의 Autocorrelation은 0이 아니다. (존재한다.) - 의사결정
검정 통계량 범위 [0,4] 에 따라 의사결정
- 2 근방
. 데이터가 대중 주장과 유사하기 때문에 대중 주장 참 & 나의 주장 거짓
. 시계열 데이터의 Autocorrelation은 존재하지 않는다.
- 0 또는 4 근방
. 데이터가 대중주장을 벗어나기 때문에 대중주장 거짓 & 나의 주장 참
. 시계열 데이터의 Autocorrelation은 존재한다.
0 : 양(Positive)의 Autocorrelation 존재
4 : 음(Negative)의 Autocorrelation 존재
# Checking for Autocorrelation
# Null Hypothesis: Autocorrelation is absent
sm.stats.diagnostic.acorr_ljungbox(Resid_tr_reg1['Error'], lags=[1,5,10,50])
#(실행결과) (Test statistics, p-value, ...)
Autocorrelation = pd.concat([pd.DataFrame(sm.stats.diagnostic.accor_ljunbox(Resid_tr_reg1['Error'], lags=[1,5,10,50])[0], columns=['Test Statistics']),
pd.DataFrame(sm.stats.diagnostic.accor_ljunbox(Resid_tr_reg1['Error'], lags=[1,5,10,50])[1], columns=['p-value'])].
axis=1).T
Autocorrelation.columns=[''Autocorr(lag1)', 'Autocorr(lag5)', 'Autocorr(lag10)', 'Autocorr(lag50)']
5. 등분산 테스트
5.1 시각화
잔차의 정상성 확인 시 잔차에 대한 시각화할 때 등분산 여부에 대해 함께 확인할 수 있다.
5.2 통계량
등분산 테스트를 위해 Goldfeld-Quandt test, Breusch-Pagan test, Bartlett's test 등을 많이 활용한다.
- 가설확인
- 대중주장(귀무가설, Null Hypothesis) : 시계열 데이터의 Homoscendasticity 상태이다. (등분산이다.)
- 나의주장(대립가설, Alternativa Hypothesis) : 시계열 데이터의 Homoscendasticity 상태가 아니다. (등분산이 아니다.) - 의사결정
- p-value >= 내 기준 (ex.0.05)
. 데이터가 대중 주장과 유사하기 때문에 대중 주장 참 & 나의 주장 거짓
. 데이터가 등분산이다.
- p-value < 내 기준 (ex.0.05)
. 데이터가 대중주장을 벗어나기 때문에 대중주장 거짓 & 나의 주장 참
. 데이터가 등분산이 아니다.
#Checking Heteroscedasticity
#Null Hypothesis: Error terms are homoscedastic
sm.stats.diagnostic.het_goldfeldquandt(Resid_tr_reg1['Error'], x_train.values, alternative='two-sided')
#(실행결과) (Test statistics, p-value, 통계량 방향(alternative))
Heteroscedasticity = pd.DataFrame([sm.stats.diagnostic.het_goldfeldquandt(Resid_tr_reg1['Error'], X_train.values, alternative='two-sided')],
index=['Heteroscedasticity'], columns=['Test Statistics', 'p-value', 'Alternative']).T
'Time Series Analysis > 1. 시계열 분석 절차' 카테고리의 다른 글
시계열 데이터 분석 절차(5/6) - 시계열 레퍼런스 모델 구현 및 성능 확인 (0) | 2021.11.14 |
---|---|
시계열 데이터 분석 절차(4/6) - 시계열 데이터 전처리(2) (0) | 2021.11.14 |
시계열 데이터 분석 절차(3/6) - 시계열 데이터 전처리(1) (0) | 2021.11.14 |
시계열 데이터 분석 절차(2/6) - 시계열 데이터 분리 (0) | 2021.11.14 |
시계열 데이터 분석 절차(1/6) - 시계열 데이터 패턴 추출 (0) | 2021.11.09 |