pythonML

[pythonML] K-fold / stratifiedKFold - 교차검증

독립성이 강한 ISFP 2022. 3. 2. 03:43
728x90
반응형

# 교차검증은 언제 사용하는가?

1) 데이터셋이 부족할 때 

2) 데이터 클래스가 불균형 할 때

3) 하나의 학습/ 검증 데이터로 이루어진 모델은 학습데이터에만 과적합되었을 가능성이 높음 

하지만 여러차례 나누는 교차검증 방식을 통해 전체 데이터 전 범위를 학습하고, 검증 데이터로 성능을 평가함으로써보다 일반화된 모델을 생성할 수 있음. 

 

 

# 과적합 : 모델이 학습데이터에만 과도하게 최적화되어, 실제 예측을 다른 데이터로 하게 되면 예측 성능이 과도하게 떨어지는 것을 의미함

 

# 교차검증(cross validation) - 과적합 방지!

1. k폴드 교차 검증(K-fold cross vaildation): k개의 데이터 폴드 세트를 만들어서 k번만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행하는 방법이다.

 

-전체 데이터 셋을 K등분 부분집합으로 나누고, k-1개 부분집합은 훈련데이터셋, 1개 부분집합은 데이터 셋으로 할당한다.

=> k번 횟수만큼 교차검증을 반복한 후 이들의 평균을 낸다.

K-fold cross vaildation

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
import numpy as np

iris=load_iris()
features = iris.data
label =iris.target
dt_clf= DecisionTreeClassifier(random_state=156)

kfold =KFold(n_splits=5) #5개의 폴드 세트로 분리하는 KFold객체
cv_accuracy=[] #폴드 세트별 정확도를 담을 리스트 객체
print("붓꽃 데이터 세트 크기:", features.shape[0]) #features.shape => (150, 4)

붓꽃 데이터 세트 크기: 150개

 

n_iter=0
                            #kfold에 split을 호출해 전체 붓꽃 데이터를 5개의 폴드 데이터셋으로 분리
    #KFold 객체의 split()를 호출하면 폴드 별 학습용/검증용 데이터의 row 인덱스를 반환
    
for train_index, test_index in kfold.split(features): #features를 train과 test로 분리
    X_train, X_test =features[train_index], features[test_index]
    y_train, y_test =label[train_index], label[test_index]
    
    #학습 , 예측
    dt_clf.fit(X_train,y_train) #학습용 피처 데이터와 레이블 데이터를 학습
    pred=dt_clf.predict(X_test) #테스트용 피처 데이터에 예측
    n_iter+=1 #첫번째 예측했으니까 +1
    
    #반복 시마다 정확도 측정
    accuracy= np.round(accuracy_score(y_test,pred),4) #정확도
    train_size = X_train.shape[0]
    test_size= X_test.shape[0]
    print('교차 검증 정확도: {1}, 학습 데이터 크기: {2}, 검증 데이터 크기: {3}'
          .format(n_iter,accuracy,train_size,test_size))
    print('검증 세트 인덱스: {1}'.format(n_iter, test_index))
    cv_accuracy.append(accuracy) #빈 리스트에 정확도 넣었음
    
#개별 iteration별 정확도를 합하여 평균 정확도 계산
print("평균 검증 정확도:",np.mean(cv_accuracy))
#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.9667, 학습 데이터 크기: 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.8667, 학습 데이터 크기: 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.9333, 학습 데이터 크기: 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.7333, 학습 데이터 크기: 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

 

 

2. 계층화 K겹 교차검증 (stratified K-fold cross vaildation) : 불균형한 분포도(한쪽으로 치우치는 분포)를 가진 레이블 데이터 집합을 위한 K폴드 방식

 

-전체 데이터 셋을 K등분 부분집합으로 나누고, k-1개 부분집합은 훈련데이터셋, 1개 부분집합은 데이터 셋으로 할당한다.

-특히, 클래스 각각에 대해서 K등분으로 나누어, 훈련/테스트 데이터 셋에서 클래스 비율이 유지되도록 한다. (한 개의 클래스로 몰리지 않도록)

=> k번 횟수만큼 교차검증을 반복한 후 이들의 평균을 낸다.

 

stratified  K-fold cross vaildation

dt_clf=DecisionTreeClassifier(random_state=156)
skfold=StratifiedKFold(n_splits=3)
n_iter=0                     
cv_accuracy=[]
    
for train_index, test_index in skfold.split(features,label): #features를 train과 test로 분리
    X_train, X_test =features[train_index], features[test_index]
    y_train, y_test =label[train_index], label[test_index]
    
    #학습 , 예측
    dt_clf.fit(X_train,y_train) #학습용 피처 데이터와 레이블 데이터를 학습
    pred=dt_clf.predict(X_test) #테스트용 피처 데이터에 예측
    n_iter+=1 #첫번째 예측했으니까 +1
    
    #반복 시마다 정확도 측정
    accuracy= np.round(accuracy_score(y_test,pred),4) #정확도
    train_size = X_train.shape[0]
    test_size= X_test.shape[0]
    print('교차 검증 정확도: {1}, 학습 데이터 크기: {2}, 검증 데이터 크기: {3}'
          .format(n_iter,accuracy,train_size,test_size))
    print('검증 세트 인덱스: {1}'.format(n_iter, test_index))
    cv_accuracy.append(accuracy) #빈 리스트에 정확도 넣었음
    
#개별 iteration별 정확도를 합하여 평균 정확도 계산

print('\n## 교차 검증별 정확도:',np.round(cv_accuracy,4))
print("평균 검증 정확도:",np.mean(cv_accuracy))
교차 검증 정확도: 0.98, 학습 데이터 크기: 100, 검증 데이터 크기: 50
검증 세트 인덱스: [  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  50
51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115]
교차 검증 정확도: 0.94, 학습 데이터 크기: 100, 검증 데이터 크기: 50
검증 세트 인덱스: [ 17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  67
  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132]
교차 검증 정확도: 0.98, 학습 데이터 크기: 100, 검증 데이터 크기: 50
검증 세트 인덱스: [ 34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  83  84 85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 133 134 135
 136 137 138 139 140 141 142 143 144 145 146 147 148 149]

## 교차 검증별 정확도: [0.98 0.94 0.98]
평균 검증 정확도: 0.9666666666666667
728x90
반응형