RL Researcher

교차검증(Cross-Validation) 본문

Machine-Learning/Scikit-Learn

교차검증(Cross-Validation)

Lass_os 2021. 1. 16. 02:47

1. Cross-Validation이란?


간략히 먼저 설명하자면 본고사를 치르기 전에 모의고사를 여러번 보는 것입니다. 즉, 본고사가 테스트 데이터 세트에 대해 평가하는 거라면 모의고사는 교차검증에서 많은 학습과 검증 세트에서 알고리즘 학습과 평가를 수행하는 것입니다.

Machine Learning은 데이터에 기반합니다. 그리고 데이터는 이상치, 분포도, 다양한 속성값, 피처 중요도 등 여러가지 Machine Learning에 영향을 미치는 요소를 가지고 있습니다. 특정 Machine Learning 알고리즘에서 최적으로 동작할 수 있도록 데이터를 선별하여 학습한다면 실제 데이터 양식과는 많은 차이가 있을 것이고 결국은 성능저하로 이어질 가능성이 매우 높습니다.

교차 검증(Cross-validation)은 이러한 데이터 편증을 막기 위해서 별도의 여러 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행하는 것입니다. 그리고 각 세트에서 수행한 평가 결과에 따라 하이퍼 파라미터 튜닝 등의 모델 최적화를 좀 더 손쉽게 할 수 있습니다.

 

2. K-Fold Cross-validation


K-Fold Cross-validation은 가장 보편적으로 사용되는 교차 검증 기법입니다. 먼저 K개의 데이터 폴드 세트를 만들어서 K번만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행하는 방법입니다.

K-Fold Cross-validation

위의 그림과 같이 5번의 폴드 교차 검증을 수행합니다(즉 K가 5). 5개의 폴드된 데이터 세트를 학습과 검증을 위한 데이터 세트로 변경하면서 5번 평가를 수행한 뒤, 이 5개의 평가를 평균한 결과를 가지고 예측 성능을 평가합니다.

먼저 데이터 세트를 K등분(5등분) 합니다. 그리고 첫번째 반복에서는 처음 1개를 테스트 데이터로 사용하고 나머지 4등분을 학습데이터 세트로 평가를 수행합니다. 첫 번째 평가를 수행하고 나면 두번째 반복에서부터 K번째 까지 비슷한 학습과 평가를 수행합니다.

 

지금부터 K-Fold Cross-validation 코드를 작성해 보겠습니다.

# 모듈 임포트
import numpy as np	
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier	# 의사결정나무
from sklearn.metrics import accuracy_score	# 정확도 평가(분류 지표)
from sklearn.model_selection import KFold	

# iris 데이터 불러오기
iris = load_iris()

# 모델 객체 생성
clf = DecisionTreeClassifier(random_state = 156)

# 5개의 폴드 세트로 분리하는 KFold 객체와 플드 세트별 정확도를 담을 리스트 객체 생성
kfold = KFold(n_splits = 5)
cv_accuracy = []

print('붓꽃 데이터 세트 크기: ',iris.data.shape[0])

====================================================

<output>
붓꽃 데이터 세트 크기:  150

다음은 split()이 어떤 값을 실제로 반환하는지 확인하기 위해 검증 데이터 세트의 인덱스도 추출해 보겠습니다.

n_iter = 0

# KFold 객체의 split()을 호출하면 폴드 별 학습용, 검증용 테스트의 로우 인덱스를 array로 반환
for train_index, test_index in kfold.split(iris.data):
    # kfold.split()으로 반환된 인덱스를 이용해 학습용, 검증용 테스트 데이터 추출
    x_train,x_test = iris.data[train_index],iris.data[test_index]
    y_train,y_test = iris.target[train_index],iris.target[test_index]
    # 학습 및 예측
    clf.fit(x_train,y_train)
    y_pred = clf.predict(x_test)
    n_iter += 1
    # 반복 시마다 정확도 측정
    accuracy = accuracy_score(y_test,y_pred)
    train_size = x_train.shape[0]
    test_size = x_test.shape[0]
    print('/n#{0} 교차 검증 정확도: {1}, 학습 데이터 크기: {2}, 검증 데이터 크기: {3}'.format(n_iter,accuracy,train_size,test_size))
    print('#{0} 검증 세트 인덱스: {1}'.format(n_iter,test_index))      
    cv_accuracy.append(accuracy)

# 개별 iteration별 정확도를 합하여 평균 정확도 계산
print('\n## 평균 검증 정확도: ',np.mean(cv_accuracy))

====================================================

<output>
#1 교차 검증 정확도: 1.0, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#1 검증 세트 인덱스: [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29]

#2 교차 검증 정확도: 0.9666666666666667, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#2 검증 세트 인덱스: [30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
 54 55 56 57 58 59]

#3 교차 검증 정확도: 0.8666666666666667, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#3 검증 세트 인덱스: [60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
 84 85 86 87 88 89]

#4 교차 검증 정확도: 0.9333333333333333, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#4 검증 세트 인덱스: [ 90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107
 108 109 110 111 112 113 114 115 116 117 118 119]

#5 교차 검증 정확도: 0.7333333333333333, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#5 검증 세트 인덱스: [120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
 138 139 140 141 142 143 144 145 146 147 148 149]

## 평균 검증 정확도:  0.9

5번의 교차 검증 결과 평균 검증 정확도는 0.9입니다. 그리고 교차 검증 시마다 검증 세트의 인덱스가 달라짐을 알 수 있습니다. 첫 번째 교차 검증에서는 0번 ~ 29번까지, 두 번째는 20번 ~ 59번, 세 번째는 60번 ~ 89번, 네 번째는 90번 ~ 119번, 다섯 번째는 120번 ~ 149번으로 각각 30개의 검증 세트 인덱스를 생성했고, 이를 기반으로 검증 세트를 추출하게 됩니다.

 

불균형한(imbalanced) 분포도를 가진 레이블(결정 클래스) 데이터 집합을 위한 K폴드 방식인 Stratified K-Fold는 다음에 다루도록 하겠습니다.

Comments