프로그래밍

[R] 교차 유효성 검사를 통한 예측 모델 성능 평가

RainIron 2021. 6. 5. 00:10
반응형

1. 교차 유효성 개념

1) 교차 유효성 검사(Cross Validation, 교차 검증)

* 정의

- 주어진 데이터의 일부를 학습시켜 모델을 생성하고, 나머지 일부(비학습 데이터)는 모델을 검증하는데 사용하는 것 => 교차 타당화

- 연구 결과에 대한 타당성을 해당 연구에 사용하지 않은 표본으로 평가해보는 타당화 방법

 

2) 교차 유효성 검사의 필요성

- 과적합(Overfitting)을 방지하기 위해 교차 유효성 검사를 실시

- 과적합: 비학습 데이터 혹은 향후에 만들어질 모델에 대해 예측력이 떨어지거나 성능이 좋지 않은 상태

- 전체 데이터 -> 훈련용 데이터(약 80%) + 테스트용 데이터(약 20%)

 

2. 교차 유효성 검사 종류

1) 종류

- Cross-Validation

- LOOCV

- K-Fold Cross-Validation

 

2) Cross Validation

- 1~n개의 데이터를 랜덤(무작위)하게 n등분하여, 데이터를 Training/Validation으로 나눈 다음 교차하여 확인하는 방법

- 장점: 구현법이 간단, 결과 도출 시간이 짧음

- 단점

   * 표본의 수와 무작위 추출에 결과값이 크게 영향을 받아 결과값이 불안정해질 수 있음

   * 테스팅 횟수가 적어, 모형을 정확히 평가하기 힘든 경우가 많음

   * 대표성에 제약이 따름

 

3) LOOCV

- 데이터 n개 중 하나만을 검정(Validation) Set으로 두고, 나머지를 학습(Training) Set으로 모델에 적합시키는 방법

  => 자료가 n개인 경우, 위 과정을 n번 반복 후 결과치들의 평균을 도출하여 사용함

- 장점: 결과값이 비교적 정확함(n-1개의 데이터를 이용하여 결과값을 구하므로, 비편향에 근사하는 성질을 띠기 때문)

   * 비편향(Unbiased): 결과값이 어느 한 쪽으로 치우치지 않아 모집단을 대표할 수 있음

- 단점

  * 계산량이 많음

  * 시간이 많이 걸림

  * 각 라인별 MSE(Mean Square Error, 평균제곱오차)가 높은 상관관계를 가지기 쉬움(N번 반복되는 과정의 학습 데이터들이 유사하기 때문)

  * 분산이 큼

 

4) K-Fold Cross-Validation

- 과다한 연산량을 줄여주는 방법

- 데이터를 무작위(Random)로 섞은 후 K등분 한 것 중 하나를 검정(Validation) Set으로 사용하는 방법

- 장점

  * LOOCV보다 적은 연산량으로 빠른 시간 내에 결과값을 구할 수 있음(k-1개의 데이터를 이용하여 결과값을 구하기 때문)

  * LOOCV와 결과값에 크게 차이가 없음

- 단점: 데이터셋을 랜덤하게 섞음으로 인해 변동성(Variability)이 수반됨(k번의 연산 반복으로 이를 상쇄하므로 큰 문제 없음)

 

3. R을 이용한 교차 유효성 검사 모델 성능 평가

* Import

# ctree() 제공 패키지
install.packages('party')
library(party)

# 교차 검증 표본 추출 제공 패키지
install.packages('cvTools')
library(cvTools)

 

* R 제공 데이터 iris 사용

* cvFolds() 함수 사용하여 교차 분석 실시

cross = cvFolds(nrow(iris), K =3)

str(cross)

cross

150개가 3개의 fold로 나뉘어져 있다.

# 균등분할 데이터 셋
cross$which

#랜덤하게 선정된 행번호
cross$subsets

# 3-fold 교차검정
k = 1:3

# 분류 정확도 설정
acc = numeric() # 수치형 변수

# index
cnt = 1
for(i in k){
  data_index = cross$subsets[cross$which == i, 1]
  
  # 검정 데이터 생성
  test = iris[data_index, ] # 50개
  
  # train 생성
  formula = Species~.
  
  # 훈련 데이터 생성
  train = iris[-data_index, ] # 100개
  
  # ctree 모델(의사결정나무)
  model = ctree(formula, data = train)
  pred = predict(model, test)
  
  # 정확도 측정
  t = table(pred, test$Species)
  print(t)
  acc[cnt] = (t[1, 1]+ t[2, 2] + t[3, 3])/sum(t)
  cnt = cnt + 1
  
}

K-fold를 3번 진행하면서 나온 판단 결과 테이블

# 각 정확도
acc

# 평균 정확도
mean(acc)

반응형