train_test_split()로 테스트데이터와 학습데이터를 분리하여서 학습하고 예측하면 '과적합(Overiftting)'에 취약해 질 수 있다.
과적합이란 학습 데이터에만 최적화 되어서 학습이 되어 있어서 실제 예측을 할 때에 성능이 떨어지는 것을 말한다.
만약 모의고사 문제집 1개만으로 공부를 한다면 해당 모의고사 문제집에만 최적화 되어 실제 시험을 볼 때 문제유형이 다르다면 모의고사에서는 좋은 성적을 거뒀을지라도 실제 시험은 망할 수 있다.
교차 검증은 과적합을 예방하기 위해서 여러 개의 학습 데이터 세트, 검증 데이터 세트에서 학습하고 검증한다. 기존에 train_test_split()로 한번의 학습 데이터를 분석 한 후 테스트 데이터로 테스트를 했다면
교차 검증에서는 학습 데이터 안에서 학습 데이터 세트, 검증 데이터 세트를 또 나누어서 여러번 테스트를 한 후 실제 테스트데이터에 적용한다.
교차 검증에는 여러가지 기법이 있는데 그 중 흔하게 쓰이는 검증 기법은 k-폴드 교차 검증 기법이다.
K-폴드 교차 검증 기법은 k개의 data fold-set 를 만들어 k번만큼 각 폴드 세트에 학습, 검증을 수행한다. 사이킷런에서는 KFold, StratifiedKFold 를 제공하는데 한번 코드로 구현해보고자 한다.
먼저 필요한 것들은 import 받는다.
우리는 사이킷런의 와인 데이터를 가지고 k-fold 교차 검증 기법을 진행해보고자 한다.
밑에서 2번째 줄을 보면 KFold에서 n_splits는 k번만큼을 몇 번으로 정할 건지 설정해준다. 여기서 우리는 5번만큼 학습, 검증을 수행할 것이기 때문에 n_splits=5라고 지정하였다.
acucuracy_list는 정확도를 저장할 리스트이다. 미리 만들어 놓았다.
from sklearn.datasets import load_wine
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
import pandas as pd
import numpy as np
wine = load_wine()
wine_features = wine.data
wine_target = wine.target
wine_dtc = DecisionTreeClassifier
kfold = KFold(n_splits=5)
accuracy_list = []
wine feature의 크기를 보면 (178, 13)이 나온다. 데이터의 갯수가 178개라는 말이다.
wine_features.shape
이제 생성한 KFold 객체를 가지고 split()을 호출하여서 와인 데이터를 5개의 폴드데이터세트로 분리한다. 전체데이터의 수는 178인데 여기서 5이 나눠진다. split()을 호출하면 학습용, 검증용 데이터로 분할하는 인덱스를 얻을 수 있다.
iter_num = 0
for train_index, test_index in kfold.split(wine_features):
x_train, x_test = wine_features[train_index], wine_features[test_index]
y_train, y_test = wine_target[train_index], wine_target[test_index]
wine_dtc.fit(x_train, y_train)
predict = wine_dtc.predict(x_test)
iter_num += 1
# 정확도 측정
accuracy = np.round(accuracy_score(y_test, predict), 4)
train_size = x_train.shape[0]
test_size = x_test.shape[0]
print('============================')
print('iter 횟수 : ', iter_num)
print('교차 검증 정확도 : ', accuracy)
print('학습 데이터 크기 : ', train_size)
print('검증 데이터 크기 : ', test_size)
print('============================')
print('iter 횟수 : ', iter_num)
print('검증 셋트 인덱스 : ', test_index)
print('============================')
accuracy_list.append(accuracy)
print('============================')
print('평균 검증 정확도', np.mean(accuracy_list))
============================
iter 횟수 : 1
교차 검증 정확도 : 0.9167
학습 데이터 크기 : 142
검증 데이터 크기 : 36
============================
iter 횟수 : 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 30 31 32 33 34 35]
============================
============================
iter 횟수 : 2
교차 검증 정확도 : 0.8333
학습 데이터 크기 : 142
검증 데이터 크기 : 36
============================
iter 횟수 : 2
검증 셋트 인덱스 : [36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69 70 71]
============================
============================
iter 횟수 : 3
교차 검증 정확도 : 0.8056
학습 데이터 크기 : 142
검증 데이터 크기 : 36
============================
iter 횟수 : 3
검증 셋트 인덱스 : [ 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107]
============================
============================
iter 횟수 : 4
교차 검증 정확도 : 0.7429
학습 데이터 크기 : 143
검증 데이터 크기 : 35
============================
iter 횟수 : 4
검증 셋트 인덱스 : [108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142]
============================
============================
iter 횟수 : 5
교차 검증 정확도 : 0.7714
학습 데이터 크기 : 143
검증 데이터 크기 : 35
============================
iter 횟수 : 5
검증 셋트 인덱스 : [143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177]
============================
============================
평균 검증 정확도 0.80557