3.3 잔차 진단

적합값

시계열에서 각 관측값은 이전의 모든 관측치를 이용하여 예측될 수 있습니다. 이러한 것을 적합값(fitted values)이라고 부르고, 관측값 \(y_{1},\dots,y_{t-1}\)을 가지고 하는 \(y_t\)의 예측값이라는 의미에서 \(\hat{y}_{t|t-1}\)라고 씁니다. 이런 표기법을 매우 자주 사용할 것입니다. 종종 아래첨자를 생략하고 \(\hat{y}_{t|t-1}\) 대신에 \(\hat{y}_t\)로 쓰기도 할 것입니다. 적합값은 항상 한 단계 예측치를 포함합니다.

사실, 미래 관측값을 포함하여 사용할 수 있는 모든 관측값으로 예측 기법에 들어가는 매개변수를 추정했기 때문에 적합값(fitted value)은 종종 진짜 예측값은 아닙니다. 예를 들어, 평균 기법을 사용한다고 하면, 적합값(fitted value)은 다음과 같이 주어집니다. \[ \hat{y}_t = \hat{c} \] 여기에서 \(\hat{c}\)는 시간 \(t\) 이후의 관측값을 포함하여 이용할 수 있는 모든 관측값에 대해 계산한 평균값입니다. 비슷하게, 표류 기법(drift method)에서는, 사용할 수 있는 모든 관측값을 가지고 표류 매개변수(drift parameter)를 추정합니다. 이 경우에, 적합값(fitted value)은 다음과 같이 주어집니다. \[ \hat{y}_t = y_{t-1} + \hat{c} \] 여기에서 \(\hat{c} = (y_T-y_1)/(T-1)\) 입니다. 두 경우 모두, 데이터에서 추정한 매개변수가 있습니다. \(c\) 위에 “모자” 기호는 추정치라는 것을 의미합니다. \(c\)의 추정치가 \(t\) 시간 이후의 관측값을 포함할 때, 맞춘 값들은 진짜 예측치가 아닙니다. 반면에, 나이브 또는 나이브 계절성 예측에는 어떠한 매개변수도 없어서, 적합값(fitted value)이 이러한 경우에는 진짜 예측치입니다.

잔차

시계열 모델에서 “잔차(Residuals)”는 모델을 맞춘 후에 남는 것을 의미합니다. 다양한 (하지만 전부는 아닌) 시계열 모델에서, 잔차(residual)는 관측값과 대응되는 적합값(fitted value)과 관측값의 차이와 같습니다. \[ e_{t} = y_{t}-\hat{y}_{t}. \]

잔차(residual)는 어떤 모델이 데이터의 정보를 적절하게 잡아냈는지 여부를 확인할 때 유용합니다. 좋은 예측 기법은 다음과 같은 특징을 갖는 잔차(residual)를 낼 것입니다.

  1. 잔차(residual)에 상관 관계가 없습니다. 잔차 사이에 상관관계(correlation)가 있다면, 잔차에 예측값을 계산할 때 사용해야하는 정보가 남아 있는 것입니다.
  2. 잔차의 평균이 0입니다. 잔차의 평균이 0이 아니라면, 예측값이 편향(bias)될 것입니다.

이러한 특징을 만족하지 않는 예측 기법은 개선할 수 있습니다. 하지만, 이 말은 이러한 특징을 만족하는 예측 기법이 개선될 수 없다는 것을 의미하는 것이 아닙니다. 같은 데이터에 대해 이러한 특징을 모두 만족하는 서로 다른 몇 가지 예측 기법이 있을 수 있습니다. 이러한 특징을 확인하는 것은 어떤 모델이 사용할 수 있는 모든 정보를 사용했는지 여부를 확인하기 위해 중요한 것입니다만, 예측 기법을 선택하기 위한 좋은 방법은 아닙니다.

이러한 특징 중에서 하나를 만족하지 않는다면, 더 나은 예측치를 내는 기법으로 수정될 수 있습니다. 편향을 보정하는 것은 쉽습니다. 만약에 잔차의 평균이 \(m\)이면, 단순히 모든 예측치에 \(m\)을 더하여 편향 문제를 해결합니다. 상관(correlation) 문제를 고치는 것은 좀 더 어렵고, 9 장까지 이 주제를 다루지 않을 것입니다.

이러한 핵심적인 특징에 더하여, (필수적인 것은 아니지만) 다음과 같은 잔차의 두 가지 성질도 유용합니다.

  1. 잔차의 분산이 상수입니다.
  2. 잔차가 정규 분포를 따릅니다.

이러한 두 가지 성질은 예측구간(prediction interval)을 계산하기 쉽도록 합니다(3.5 절을 참조하시길 바랍니다). 하지만, 이러한 특징을 만족하지 않는 어떤 예측 기법이 반드시 좋아질 수 없진 않습니다. 때때로 박스-칵스(Box-Cox) 변환을 적용하면 이러한 특징이 만족될 수도 있습니다만, 그렇지 않는다면 잔차(residual)의 분산이 상수이면서 정규 분포(normal distribution)를 따른다는 것을 확인하기 위해 여러분이 할 수 있는 일이 보통은 거의 없습니다. 대신에 예측 구간(prediction interval)을 얻기 위해 다른 방식이 필요합니다. 이 책의 뒷 부분에서 이것을 어떻게 다룰 수 있을 지 설명할 것입니다.

예제: 구글 주식 일별 종가 예측하기

주식 시장 가격과 지수에서는, 단순 기법(naïve method)이 종종 가장 잘 들어맞습니다. 즉, 각 예측값을 단순히 마지막 관측값과 같게 두는 것입니다(또는 \(\hat{y}_{t} = y_{t-1}\)). 따라서, 이렇게 두는 경우에 잔차는 단순히 인접한 관측값 사이의 차이와 같습니다. \[ e_{t} = y_{t} - \hat{y}_{t} = y_{t} - y_{t-1}. \]

다음의 그래프들은 구글 주식 일별 종가(나스닥 코드: GOOG)를 나타냅니다. 166일에 크게 뛰는 부분은 2013년 10월 18일에 3분기 실적이 예상보다 훨씬 좋아서 주가가 12% 뛴 것과 관련 있습니다.

autoplot(goog200) +
  xlab("날짜") + ylab("종가(미국 달러)") +
  ggtitle("구글 주식 일별 가격(2013년 12월 6일까지)")
2013년 12월 6월까지 구글 주식 일별 가격.

Figure 3.5: 2013년 12월 6월까지 구글 주식 일별 가격.

단순 기법(naïve method)으로 이 시계열을 예측하여 얻은 잔차를 그림 3.6에서 볼 수 있습니다. 양수의 큰 잔차는 166일에 예상 밖으로 가격이 뛴 결과입니다.

res <- residuals(naive(goog200))
autoplot(res) + xlab("날짜") + ylab("") +
  ggtitle("나이브 기법에서 얻은 잔차")
단순 기법을 이용한 구글 주식 예측에서 얻은 잔차

Figure 3.6: 단순 기법을 이용한 구글 주식 예측에서 얻은 잔차

gghistogram(res) + ggtitle("잔차의 히스토그램")
구글 주가에 단순 기법을 적용하여 얻은 잔차의 히스토그램. 오른쪽 꼬리는 정규 분포에 비해 너무 깁니다.

Figure 3.7: 구글 주가에 단순 기법을 적용하여 얻은 잔차의 히스토그램. 오른쪽 꼬리는 정규 분포에 비해 너무 깁니다.

ggAcf(res) + ggtitle("잔차의 ACF")
구글 주가에 단순 기법을 적용하여 얻은 잔차의 ACF. 상관관계가 없다는 것은 예측값이 좋다는 것을 의미합니다.

Figure 3.8: 구글 주가에 단순 기법을 적용하여 얻은 잔차의 ACF. 상관관계가 없다는 것은 예측값이 좋다는 것을 의미합니다.

이런 그래프는 사용할 수 있는 모든 정보를 고려한 것처럼 보이는 예측값을 단순 기법(naïve method)으로 구한 결과를 보여줍니다. 잔차(residual)의 평균은 0에 가깝고 잔차(residual)의 시계열에서 분명한 상관값이 없습니다. 잔차의 시간 그래프(time plot)는 과거 데이터에 걸쳐 잔차(residual)의 분산이 1가지 이상치를 제외하고 거의 같은 양으로 유지되고 있다는 것을 보여주고 있습니다. 따라서 잔차(residual)의 분산을 상수로 둘 수 있습니다. 이것 역시 잔차의 히스토그램(histogram)에서 확인할 수 있습니다. 히스토그램에서 이상치를 무시하더라도 오른쪽 부분의 꼬리가 너무 긴 것 같고, 이것은 잔차(residual)가 정규 분포(normal distribution)를 따르지 않을 수 있다는 것을 시사합니다. 결과적으로, 이 기법이 낸 예측값은 꽤 괜찮은 것 같습니다만, 정규 분포(normal distribution)를 가정하여 예측구간(prediction interval)을 얻은 것은 정확하지 않을 것입니다.

자기상관에 대한 포트맨토 검정

ACF 그래프를 보는 것에 더하여, \(r_k\) 값을 각각 다루는 대신 \(r_k\) 값의 전체 모음을 하나의 그룹으로 생각하여 자기 상관에 대한 더욱 형식적인 검정도 할 수 있습니다.

\(r_k\)\(k\) 뒤처짐에 대한 자기상관(autocorrelation)이라는 것을 다시 떠올려봅시다. ACF 그래프에서 각 뾰족한 막대가 필요한 제한 조건 안에 들어오는지 여부를 볼 때, 거짓 양성(false positive)으로 나올 작은 확률에 대해 암묵적으로 몇 가지 가설검증(hypothesis test)을 수행하고 있었습니다. 이러한 검정을 충분하게 수행했을 때, 적어도 하나가 거짓 양성(false positive)으로 나올 확률이 큽니다. 그래서 사실은 그렇지 않더라도 잔차에 약간의 자기상관(autocorrelation)이 남아있다고 주장할 수도 있습니다.

이러한 문제를 해결하기 위해, 처음 \(h\)개의 자기상관(autocorrelation)이 백색잡음(white noise) 과정에서 얻은 것과 의미있게 다른 지 여부를 검정합니다. 자기상관(autocorrelation) 값의 그룹에 대한 검정을 여러 가지 물품을 담고 있는 여행 가방이라는 프랑스 단어를 빌려 포트맨토(portmanteau) 검정이라고 부릅니다.

박스-피어스(Box-Pierce) 검정은 다음과 같은 통계에 기초하는 이런 종류의 검정입니다. \[ Q = T \sum_{k=1}^h r_k^2, \] 여기에서 \(h\)는 고려할 최대 시차(lagged value)이고 \(T\)는 관측값의 개수입니다. 각 \(r_k\)가 0에 가깝다면, \(Q\)는 작을 것입니다. 몇몇 \(r_k\) 값이 크다면(양수이거나 음수), \(Q\)가 클 것입니다. 비-계절성 데이터에서 \(h=10\)를 계절성 데이터에서 \(h=2m\)을 사용하길 추천합니다. 여기에서 \(m\)은 계절성의 주기(seasonal period)입니다. 하지만, \(h\)가 크면, 검정 결과가 좋지 않습니다. 그래서 이러한 값들이 \(T/5\)보다 크면, \(h=T/5\)를 사용하시길 바랍니다.

융-박스(Ljung-Box) 검정은 관련된 (그리고 더 정확한) 검정입니다. 이 검정은 다음과 같은 내용에 기초합니다. \[ Q^* = T(T+2) \sum_{k=1}^h (T-k)^{-1}r_k^2. \]

다시 한번, 큰 \(Q^*\) 값들은 자기상관(autocorrelation)값이 백색잡음(white noise) 시계열에서 온 것이 아니라는 것을 의미합니다.

얼마나 커야 큰 것일까요? 자기상관(autocorrelation)이 백색잡음(white noise) 시계열에서 왔다면, \(Q\)\(Q^*\) 모두 \((h - K)\) 자유도(degree of freedom)를 갖는 \(\chi^2\) 분포를 따를 것입니다. 여기에서 \(K\)는 모델의 매개변수 개수입니다. 모델의 잔차에서 계산하는 대신 원본 데이터에서 이것을 계산한다면, \(K=0\)으로 둡시다.

구글 주식 가격 예제에서, 단순 모델(naïve model)에서는 매개변수가 없으니, 이 경우에도 \(K=0\)로 둡니다.

# lag=h and fitdf=K
Box.test(res, lag=10, fitdf=0)
#> 
#> 	Box-Pierce test
#> 
#> data:  res
#> X-squared = 11, df = 10, p-value = 0.4

Box.test(res,lag=10, fitdf=0, type="Lj")
#> 
#> 	Box-Ljung test
#> 
#> data:  res
#> X-squared = 11, df = 10, p-value = 0.4

\(Q\)\(Q^*\) 두 경우에 대해, 결과가 의미있지 않습니다(즉, \(p\)-값들이 상대적으로 큽니다). 그래서 잔차(residual)가 백색잡음(white noise) 시계열과 다르지 않다고 결론 내릴 수 있습니다.

잔차(residual)를 확인하는 이러한 기법 모두 편리하게 사용할 수 있도록 하나의 R 함수 checkresiduals()에 들어있습니다. 이 함수로 시간 그래프(time plot), ACF 그래프, (비교 목적에서 정규 분포와 겹쳐서 그릴 수 있는) 잔차(residual)의 히스토그램(histogram) 등을 그릴 수 있고, 정확한 자유도(correct degree of freedom)로 융-박스(Ljung-Box) 검정을 할 수 있습니다.

checkresiduals(naive(goog200))

#> 
#> 	Ljung-Box test
#> 
#> data:  Residuals from Naive method
#> Q* = 11, df = 10, p-value = 0.4
#> 
#> Model df: 0.   Total lags used: 10