Home R로 하는 기초적 통계 모델 평가
Post
Cancel

R로 하는 기초적 통계 모델 평가

데이터 분석의 꽃은 통계 모델이다. 원하는 인사이트가 나오는 통계 모델을 짠 하고 만들어 냈을 때, 혹은 운좋게 모델 만드는 함수 하나를 돌려봤는데 꽤 적절한 결과를 뱉어주면 얼마나 흥분되고 신나면서 그간 힘들었던 일들이 싹 잊혀지는 지는 경험해 본 사람들만 알 수 있다.

하지만 여기에는 맹점이 있다. 이전의 데이터를 처리하고 어떤 모델을 써야 할 지 고민하는 데에 지쳐있고 매몰되어 있던 나머지, 결과가 어케 나오면 웬지 다 좋아 보일 수도 있다는 것이다. 주변에 확인해 줄 사람이 없으면 더 그렇다.  게다가 ‘여긴 어디 나는 누구’ 상태에 빠지면 모델 돌려놓고 p-value하나 확인하는 것도 잊어버릴 수도 있다. 그 와중에 모델 검증을 위해 이것저것 테스트해 볼 여력따위 남아있지 않은 것이다.

또한 어느 정도 분석 및 통계 모델링이 손에 익은 사람들이라면, 슬슬 선호하는 모델들이 생기기 마련이다. 혹은 데이터 마이닝에 막 진입한 사람들이라면, 웬지 복잡한 알고리즘을 실제 사례에 적용해 보고 싶은 마음이 샘솟는다.   혹은 이것저것 함수 한 두 개만 때려넣어도 기본적 모델들이 돌아간다는 것에 신기해 하면서 이것저것 돌려보고 모델링했다고 내놓는 경우가 있다(가장 끔찍한 경우다).  이러면서 통계 모델링의 비극이 발생한다.

그래서 우선 통계 모델을 체크할 때에는 모델링한 사람의 생각을 한 번 점검해 볼 필요가 있다.

  1. 내가 선호하는 모델이 가장 정확하다고 생각하는 것은 아닌가.
  2. 정확한 모델을  찾아야 한다는 강박에 빠져 있는 것은 아닌가.
  3. 모든 모델이 다 비슷한 수준이라고 생각하는 것은 아닌가.
  4. 복잡한 모형을 선호하는 것은 아닌가.

마음의 준비가 되었다면, 간단히 대부분의 모델에 적용해서 데이터에 대한 설명력 정도를 비교파악해 볼 수 있다.

이 때 가장 기본적으로, 하지만 가장 중요하게 살펴봐야 하는 항목에는 다음 내용들이 있다.

  • 이분산성:  예측 모델의 잔차 산포에 패턴이 발생하는 지 파악
  • 잔차의 정규성: 기본적으로 잔차가 정규분포를 따르지 않는다면 모델의 설명력이 약해짐
  • 적합도: 데이터의 수에 따른 적합도 변화
  • 데이터의 자기상관성: 수집 및 형태에 따라 시간적 상관관계 발생 여부 파악

이 중 이분산성이나 비정규성은 잔차를 통해서 파악할 수 있다. 특히 굳이 수치를 구하지 않더라도 그래프를 통해서 빠르고 쉽게 비교 파악할 수 있다.  이런 용도의 함수로,  다른 언어로 John Nelder가 개발한 함수를 R로 간단히 변형해 본다.

mcheck <- function(obj,..) { rs <- obj$resid fv <- obj$fitted windows(7,4) par(mfrow=c(1,2)) plot(fv, rs, xlab = “Fitted Values”, ylab = “Residuals”, pch = 16, col = “red”) abline(h=0, lty=2) qqnorm(rs, xlab = “Normal Scores”, ylab = “Ordered Residuals”, main = “”, pch = 16) qqline(rs, lty = 2, col = “blue”) par(mfrow=c(1,1)) invisible(NULL) }

이를 사용하여 임의로 난수를 발생하고, 이를 간단한 모델에 fitting시켜서 잔차를 살펴보자.

x <- 0:30 eu <- 20 * (runif(31)-0.5) yu <- 10 + x + eu mu <- lm(yu~x) mcheck(mu)

결과는 다음 그림과 같다.

c1

잔차가 규칙성 없이 퍼져 있으나,  QQ그래프에서 오차가 S자 형태를 그림으로써 예측값이 매우 크거나 작은 부분에서는 상대적으로 좀 더 고민해 봐야 할 부분이 있다고 볼 수 있다.

이와 더불어 적합도 및 데이터의 영향도를 살펴보면서 모델의 overfitting(sample data에 모델이 너무 딱 맞아 떨어져서 다른 데이터에 대해서는 안 맞게 되는 경우) 정도를 파악해 보아야 한다. 이런 경우는  전반적인 잔차가 오히려 작게 나오기 때문에 위의 잔차 분석으로는 파악하기 힘들다. 이 경우 대부분의 모델 함수에 들어있는 fitted 혹은 fitness 관련 수치로 파악해 볼 수도 있고,  stats 패키지의 influence() 함수를 사용할 수도 있다.

예를 들어 위의 mu에 대해 lm.influence(mu)를 확인해 보면,

$hat 1 2 3 4 5 6 7 8 9 10 11 12 13 0.12298387 0.11129032 0.10040323 0.09032258 0.08104839 0.07258065 0.06491935 0.05806452 0.05201613 0.04677419 0.04233871 0.03870968 0.03588710 (이하 생략)

$coefficients (Intercept) x 1 0.7666613007 -3.770465e-02 2 -1.3595198253 6.563199e-02 3 0.7243566147 -3.424231e-02

(이하 생략)

$sigma 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 6.210889 5.958364 6.198496 6.307722 6.283025 6.116059 6.267392 6.275218 6.254236 6.306797 6.260839 6.116691 6.307585 6.194379 6.279123

(이하 생략)

$wt.res

1 2 3 4 5 6 7 8 9 10 11 5.46717485 -10.33235067 5.87650766 0.35601826 -2.85116234 7.87166844 3.66178614 3.30428095 -4.23866550 -0.66663684 -3.99174640

(이하 생략)

결과가 나올 것이다. 여기서 $hat은 orthogonal projector matrix로, y값에 대한 영향값이다.  $coefficient는 해당 행의 점을 제외한 상태의 회귀모형에 대한 절편과 기울기의 계수값이다.  (값이 다른 데이터와 많이 차이날 수록 영향력이 큰 것이라고 볼 수 있음) $sigma는 해당 행의 점을 제외한 상태의 회귀모형에서 나온 잔차의 표준오차고, $wt.res는 가중치가 부여된 잔차 벡터다.  물론 이는 가장 흔한(…) lm의 경우고, 다른 모델의 경우에는 또 다르게 사용될 수 있으니 help(influence)를 확인해 보자.

모델링은 나름 재미있고 신기한 분야지만, 괜히 잘못 만들어서 사용하면 시간낭비 자원낭비에 두고두고 독이 될 수 있으니, 꼭 필요한 경우에만 최대한 단순하게 만들고, 꼼꼼히 확인해서 최대한 좋은 인사이트를 많이 뽑아내고 많은 사람들이 유용하게 사용할 수 있도록 하는 게 중요하다고 생각한다. 이를 위해서는 귀찮고 별거 아닌 것 같아도, 만든 모델도 다시 보는 습관을 들이는 게 좋지 않을까.

 (Reference: [The R Book] 2nd Edition, 에이콘출판사)

    This post is licensed under CC BY 4.0 by the author.

    FACEBOOK의 ASK 버튼에 대한 단상

    COURSERA의 EDA 수업 후기