본문 바로가기

AI Study/Machine Learning

sklearn의 model selction module (데이터셋 분리 및 교차검증)

sklearn의 Model selection module 살펴보기

이번 시간에는 데이터를 학습 / 검증 / 테스트 용으로 분리하기 위한 메소드를 살펴본다.

그런 다음 교차 검증에 관한 4가지 방법을 순차적으로 학습한다.


  • sklearn의 model_selection module에서 제공하는 함수/클래스
    • train data/test data의 분리 (train_test_split())
    • 교차 검증 분할 및 평가(KFold, Stratified_KFold)
    • Estimator의 하이퍼 파라미터를 튜닝
In [10]:
# train/test를 분할하지 않았을 때의 문제 : 모의고사만 똑같은 거 2번 보는 셈
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

iris = load_iris()
dt_clf = DecisionTreeClassifier()
train_data = iris.data
train_label = iris.target

dt_clf.fit(train_data, train_label)

# 학습 데이터 세트로 예측
pred = dt_clf.predict(train_data)
print('예측 정확도 : ', accuracy_score(train_label, pred))
 
예측 정확도 :  1.0
 

1. train_test_split()

  • 학습/테스트 데이터 세트 분리 - train_test_split()
  • sklearn.model_selection module에서 train_test_split 로드
    • Parameter
      • 1st : feature data set
      • 2nd : label data set
      • other
        • test_size: 전체 데이터 중 test data의 크기. default는 0.25
        • shuffle : default는 True. 데이터 분리 전 미리 섞을 지 결정함.
                데이터를 분산시켜서 좀 더 효율적인 학습/테스트 데이터 세트 생성가능
        • random_state : 호출할 때마다 동일한 학습/테스트용 데이터 세트를 생서하기 위한 것
  • 반환값 : tuple 형태. 순서가 지정되어 있음.
    • 학습용 데이터의 피처 데이터 세트, 테스트용 데이터의 피처 데이터 세트
    • X_train, X_test
    • 학습용 데이터의 레이블 데이터 세트, 테스트용 데이터의 레이블 데이터 세트
    • y_train, y_test
In [11]:
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

iris_data = load_iris()
dt_clf = DecisionTreeClassifier()

X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, \
                                                   test_size=0.3, random_state=121)
 
In [12]:
# 학습 데이터를 기반으로 dt_clf 학습, 모델을 이용해 예측 정확도 측정
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
print('예측 정확도:{0:.4f}'.format(accuracy_score(y_test, pred))) # 순서 : 실제, 예측
 
예측 정확도:0.9556
 

2. 교차 검증

  • Overfitting(과적합)의 문제
    • 과적합 : 모델이 학습데이터에만 과도하게 최적화되어 실제 예측을 다른 데이터로 수행 시, 예측 성능이 과도하게 떨어지는 현상
    • 문제점을 개선하기 위한 것이 교차 검증
  • 교차 검증의 개념
    • 본 고사를 치루기 전 최대한 여러번의 모의고사를 보는 것
    • 본고사 = test data set
    • 모의 고사
      • train data를 더 쪼개서 진행
        • train(학습)
        • Verification(검증)
        • test
      • 교차 검증에서 많은 학습과 검증 세트에서 알고리즘 학습과 평가를 수행하는 것
    • ML은 데이터에 기반 -> 데이터는 이상치, 분포도, 다양한 속성값, 피처 중요도 등 여러가지 ML에 영향을 미치는 요소를 가짐
    • 데이터 편중을 막기 위해 별도의 여러 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행
  • 대부분의 ML model의 성능 평가는 교차 검증 기반으로 1차 평가 -> 최종적으로 test data set에 적용해 평가하는 precess
  • ML에 사용되는 data set를 세분화하여 train(학습)/Verification(검증)/test data set로 나눔
    • test data set외에 별도의 Verification data set를 둬서 최종 평가 이전에 다양한 평가를 수행

2.1 KFold 교차 검증

  • 가장 보편적으로 사용되는 교차 검증 기법
  • K개의 데이터 폴드 세트를 생성
  • K번만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행
  • K번의 평가를 평균내어 예측 성능을 평가
 
In [13]:
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
from sklearn.datasets import load_iris
import numpy as np

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

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

cv_accuracy=[] # 각각의 정확도를 담을 리스트 객체
print('붓꽃 데이터 세트 크기 : ', features.shape[0])
 
붓꽃 데이터 세트 크기 :  150
 
In [14]:
# 전체 붓꽃 데이터를 5개의 폴드 데이터 세트로 분리
# 1/5는 검증 테스트 데이터 세트, 4/5는 학습용 데이터 세트
# 학습용/검증용 데이터 추출은 반환된 인덱스를 기반으로 개발코드에서 직접 수행

n_iter = 0

# KFold 객체의 split()를 호출하면 폴드 별 학습용, 검증용 테스트의 로우 인덱스를 array로 반환
for train_index, test_index in kfold.split(features): # KFold는 매개변수로 feature data set가 들어감.
    # kfold.split()으로 반환된 인덱스를 이용해 학습용, 검증용 테스트 데이터 추출
    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
    
    # 반복 시마다 정확도 측정
    accuracy = np.round(accuracy_score(y_test, pred), 4) # np.round(a,4) : a를 소수점 4째자리까지 출력
    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))
 
#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.2 Stratified K Fold

  • 불균형한(imbalanced) 분포도를 가진 label(결정 클래스) data set을 위한 K Fold 방식
    • 불균형한 분포도를 가진 label data set : 특정 레이블 값이 더 많거나 적어서 분포가 치우친 상태
      • ex) 대출 사기 데이터 예측. 정상 대출(0) 대비 사기(1) 건수는 0.001% 정도
      • 1 label이 너무 적음. KFold에서는 이 1 label이 한 data set에 몰려버릴 수 있음.
      • 원본 데이터와 유사한 대출 사기 label 값의 분포를 학습/테스트 세트에도 유지해야함
  • Stratified KFold는 원본 데이터의 label 분포를 먼저 고려함. 해당 분포와 동일하게 학습/검증 데이터 세트를 분해함.
  • 일반적으로 분류(Classification)에서의 교차 검증은 KFold가 아니라 StratifiedKFold로 분할되어야 함.
  • 회귀(Regression)에서는 Stratified KFold가 지원되지 않음 -> 회귀의 결정값은 이산값 형태의 label이 아니라 연속된 숫자값이므로 분포를 결정할 필요가 없음
In [15]:
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
iris_df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
iris_df['label'] = iris.target 
iris_df['label'].value_counts()
Out[15]:
2    50
1    50
0    50
Name: label, dtype: int64
In [16]:
# KFold의 이슈 현상을 직접 확인. 
# 3개의 폴드를 KFold로 생성, 각 교차 검증 때마다 생성되는 학습/검증 label data 값의 분포도를 확인
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
import numpy as np

kfold = KFold(n_splits=3)
n_iter = 0
for train_index, test_index in kfold.split(iris_df):
    n_iter += 1
    label_train = iris_df['label'].iloc[train_index]
    label_test = iris_df['label'].iloc[test_index]
    print('## 교차 검증 : {0}'.format(n_iter))
    print()
    print('학습 레이블 데이터 분포:\n', label_train.value_counts())
    print()
    print('검증 레이블 데이터 분포:\n', label_test.value_counts())
    print()
    print()
    
# 각 교차 검증마다 label이 편중되어, 학습하지 못하는 label이 생김. 
# 교차 검증 1의 경우, label 1과 2는 학습했으나, 0은 학습하지 못했음. 근데 검증은 label 0으로 해야하므로 크게 성능저하 나타남.
 
## 교차 검증 : 1

학습 레이블 데이터 분포:
 2    50
1    50
Name: label, dtype: int64

검증 레이블 데이터 분포:
 0    50
Name: label, dtype: int64


## 교차 검증 : 2

학습 레이블 데이터 분포:
 2    50
0    50
Name: label, dtype: int64

검증 레이블 데이터 분포:
 1    50
Name: label, dtype: int64


## 교차 검증 : 3

학습 레이블 데이터 분포:
 1    50
0    50
Name: label, dtype: int64

검증 레이블 데이터 분포:
 2    50
Name: label, dtype: int64


 

KFold와 StrtifiedKFold 코드의 차이는?

  • KFold는 for train_index, test_index in KFold.split(): 에서 매개변수에 feature data set만 들어가면 됨
  • Stratified KFold는 레이블 데이터 분포도에 다라 학습/검증 데이터를 나누기 때문에 skf.split() 매개변수 자리에 feature data set + label data set도 포함!
In [17]:
# Stratified KFold로 학습/검증 레이블 데이터 분포를 살펴보면, 균일하게 분포된 것을 확인할 수 있음. 
# 학습 레이블과 검증 레이블 데이터 값의 분포도가 동일하게 할당되었음.

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=3)
n_iter = 0

for train_index, test_index in skf.split(iris_df, iris_df['label']):
    n_iter +=1
    label_train = iris_df['label'].iloc[train_index]
    label_test = iris_df['label'].iloc[test_index]
    print('## 교차 검증 : {0}'.format(n_iter))
    print()
    print('학습 레이블 데이터 분포:\n', label_train.value_counts())
    print()
    print('검증 레이블 데이터 분포:\n', label_test.value_counts())
    print()
    print()
 
## 교차 검증 : 1

학습 레이블 데이터 분포:
 2    34
1    33
0    33
Name: label, dtype: int64

검증 레이블 데이터 분포:
 1    17
0    17
2    16
Name: label, dtype: int64


## 교차 검증 : 2

학습 레이블 데이터 분포:
 1    34
2    33
0    33
Name: label, dtype: int64

검증 레이블 데이터 분포:
 2    17
0    17
1    16
Name: label, dtype: int64


## 교차 검증 : 3

학습 레이블 데이터 분포:
 0    34
2    33
1    33
Name: label, dtype: int64

검증 레이블 데이터 분포:
 2    17
1    17
0    16
Name: label, dtype: int64


 
In [18]:
# Stratified KFold를 통한 iris classification 학습 및 평가
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
import numpy as np
from sklearn.datasets import load_iris

iris = load_iris()
features = iris.data
label = iris.target

dt_clf = DecisionTreeClassifier(random_state=156)
skfold = StratifiedKFold(n_splits = 3)
n_iter = 0
cv_accuracy=[]



# StratifiedKFold의 split() 호출 시 반드시 레이블 데이터 세트도 추가 입력 필요
for train_index, test_index in skfold.split(features, label):
    # split()으로 반환된 인덱스를 이용해 학습/검증용 테스트 데이터 추출
    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
    accuracy = np.round(accuracy_score(y_test, pred), 4)
    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)
    
# 교차 검증별 정확도 및 평균 정확도 
print('\n## 교차 검증별 정확도 : ', np.round(cv_accuracy, 4))
print('## 평균 검증 정확도 : ', np.mean(cv_accuracy))
 
#1 교차 검증 정확도 : 0.98, 학습 데이터 크기 : 100, 검증 데이터 크기 : 50
#1  검증 세트 인덱스 : [  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]

#2 교차 검증 정확도 : 0.94, 학습 데이터 크기 : 100, 검증 데이터 크기 : 50
#2  검증 세트 인덱스 : [ 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]

#3 교차 검증 정확도 : 0.98, 학습 데이터 크기 : 100, 검증 데이터 크기 : 50
#3  검증 세트 인덱스 : [ 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
 

2.3 편리한 교차 검증, cross_val_score()

  • KFold의 방식
      1. 폴드 세트를 설정
      1. for loop에서 반복으로 학습/테스트 데이터의 인덱스 추출
      1. 반복적으로 학습/예측을 수행한 후 예측 성능 반환
    • -> 이 과정을 한꺼번에 해주는 것이 cross_val_score()
  • cross_val_score() API는 내부에서 Estimator를 학습(fit) / 예측(predict) / 평가(evaluation) 시켜주므로 간단히 교차 검증을 할 수 있음
  • cross_val_score()는 cv로 지정된 횟수만큼 평가, scoring 파라미터로 지정된 평가 지표로 평과결괏값을 배열로 반환 -> 평균한 값을 평가 수치로 사용
  • cross_val_score(estimator, X, y=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch='2*n_jobs')
    • 주요 파라미터 : estimator, X, y, scoring, cv
      • estimator : 사이킷런의 분류 AL Class인 Classifier / Regression을 의미
        • estimator에 classifier가 입력되면 -> Stratified KFold 방식으로 학습/테스트 세트 분할
        • 회귀의 경우에는 Stratified KFold 지원 X -> KFold 방식으로 분할
      • X : feature data set
      • y : label data set
      • scoring : 예측 성능 평가 지표
      • cv : 교차 검증 폴드 수
    • 반환값 : scoring parameter로 지저오딘 성능 지표 측정값을 배열 형태로 반환
In [19]:
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score, cross_validate
from sklearn.datasets import load_iris

iris_data = load_iris()
dt_clf = DecisionTreeClassifier(random_state=156)

data = iris_data.data
label = iris_data.target

# 성능 지표는 정확도(accuracy), 교차 검증 세트는 3개
scores = cross_val_score(dt_clf, data, label, scoring='accuracy', cv=3)
print('교차 검증별 정확도 : ', np.round(scores,4))
print('평균 검증 정확도 : ', np.round(np.mean(scores), 4)) # 결과값이 위의 Stratified KFold 코드와 동일함
 
교차 검증별 정확도 :  [0.98 0.94 0.98]
평균 검증 정확도 :  0.9667
 

cross_validate() API

  • cross_val_score는 1가지 종류의 평가 지표를 반환
  • cross_validata는 여러 종류의 평가 지표를 반환
    • 학습 데이터에 대한 성능 평가 지표와
    • 수행시간도 함께 제공
  • https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_validate.html
  • sklearn.model_selection.cross_validate(estimator, X, y=None, , groups=None, scoring=None, cv=None, n_jobs=None, verbose=0, fit_params=None, pre_dispatch='2n_jobs', return_train_score=False, return_estimator=False, error_score=nan)

2.4 GridSearchCV - 교차 검증, 최적 하이퍼 파라미터 튜닝을 한번에 할 수 있는 API

  • 하이퍼 파라미터 : ML AL을 구성하는 주요 구성 요소, 이 값을 조정해 AL의 예측 성능을 개선할 수 있음.
  • sklearn은 GridSearchCV API를 이용해 Classifier나 Regressor와 같은 알고리즘에 사용되는 하이퍼 파라미터를 순차적으로 입력 -> 편리하게 최적 파라미터를 도출할 수 있음
    • Grid(격차) : 촘촘하게 파라미터를 입력하면서 테스트 하는 방식
    • ex) 결정 트리 AL의 여러 하이퍼 파라미터를 순차적으로 변경하면서 최고 성능을 가지는 파라미터 조합을 찾는 예
      • 파라미터의 집합을 만든다
      • 순차적으로 적용하면서 최적화를 수행한다
      • 교차 검증을 기반으로 하이퍼 파라미터의 최적값을 찾게 해준다.
  • GridSearchCV Class의 생성자로 들어가는 주요 파라미터
    • estimator : classifier, regressor, pipeline
    • param_grid : key + 리스트 값을 가지는 딕셔너리가 주어짐. estimator의 튜닝을 위해 파라미터명과 사용될 여러 파라미터 값을 지정함. key가 파라미터 이름 문자열, value는 list 형태로 된 파라미터의 범위
    • scoring : 예측 성능을 측정할 평가 방법을 지정함. 보통은 sklearn의 성능 평가 지표를 지정하는 문자열(예:정확도의 경우 'accuracy')로 지정하나, 별도의 성능 지표 함수도 지정가능
    • cv : 교차 검증을 위해 분할되는 학습/테스트 세트의 개수를 지정
    • refit : 디폴트가 True, True로 생성 시 가장 최적의 하이퍼 파라미터를 찾은 뒤 입력된 estimator 객체를 해당 하이퍼 파라미터로 재학습시킴
  • process
    1. data 로딩
    2. train_test_split으로 train/test data 분리
    3. parameter dictionary 생성
    4. 학습 데이터 세트를 GridSearchCV 객체의 fit() 메서드에 인자로 입력
    5. fit 수행 -> 학습 데이터를 CV에 기술된 폴딩 세트로 분할함 -> parameter dictionary에 기술된 하이퍼 파라미터를 순차적으로 변경하면서 학습/평가 수행 -> cv_results에 기록
In [20]:
# param_grid의 예시. 
# 아래와 같이 parameter의 집합을 만들고 이를 순차적으로 적용하면서 최적화를 수행
grid_parameters = {'max_depth' : [1,2,3],
                   'min_samples_split' : [2,3]
                  }
 
In [21]:
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV

# 데이터를 로딩하고 train/test data 분리
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, 
                                                    test_size=0.2, random_state=121)
dtree = DecisionTreeClassifier()

### parameter 들을 dictionary 형태로 설정
parameters = {'max_depth':[1,2,3], 'min_samples_split':[2,3]} # 주의 : 1개만 넣더라도 list 형태로, 즉 [1] 이렇게 입력해야 함~!
 
In [22]:
import pandas as pd

# param_grid의 하이퍼 파라미터들을 3개의 train, test set fold 로 나누어서 테스트 수행 설정.  
### refit=True 가 default 임. True이면 가장 좋은 파라미터 설정으로 재 학습 시킴.  
grid_dtree = GridSearchCV(dtree, param_grid=parameters, cv=3, refit=True)

# 붓꽃 Train 데이터로 param_grid의 하이퍼 파라미터들을 순차적으로 학습/평가 .
grid_dtree.fit(X_train, y_train)

# GridSearchCV 결과 추출하여 DataFrame으로 변환
scores_df = pd.DataFrame(grid_dtree.cv_results_)
scores_df[['params', 'mean_test_score', 'rank_test_score', \
           'split0_test_score', 'split1_test_score', 'split2_test_score']]
 
Out[22]:
  params mean_test_score rank_test_score split0_test_score split1_test_score split2_test_score
0 {'max_depth': 1, 'min_samples_split': 2} 0.700000 5 0.700 0.7 0.70
1 {'max_depth': 1, 'min_samples_split': 3} 0.700000 5 0.700 0.7 0.70
2 {'max_depth': 2, 'min_samples_split': 2} 0.958333 3 0.925 1.0 0.95
3 {'max_depth': 2, 'min_samples_split': 3} 0.958333 3 0.925 1.0 0.95
4 {'max_depth': 3, 'min_samples_split': 2} 0.975000 1 0.975 1.0 0.95
5 {'max_depth': 3, 'min_samples_split': 3} 0.975000 1 0.975 1.0 0.95
 
  • cv_results_는 gridsearchcv의 결과 세트로서 dictionary 형태로 key값과 리스트 형태의 value값을 가짐
  • cv_results_를 pandas의 dataframe으로 변환 시 해석이 용이함
  • 칼럼별 의미
    • params : 수행할 때마다 적용된 개별 하이퍼 파라미터 값
    • mean_test_score : 개별 하이퍼 파라미터별로 CV 폴딩 테스트 세트에 대해 총 수행한 평가 평균값
    • rank_test_score : 하이퍼 파라미터별로 성능이 좋은 score순위를 나타냄. 1이 가장 뛰어난 순위, 이때의 파라미터가 최적의 파라미터
    • split0_test_score, split1_test_score, split2_test_score : CV가 3인 경우, 즉 3개의 폴딩 세트에서 각각 테스트한 성능 수치
      -> mean_test_score가 이 3개 성능 수치를 평균한 것
  • GridSearchCV 객체의 fit()을 수행
    -> 최고 성능을 나타낸 하이퍼 파라미터 값은 bestparams 속성에 기록
    -> 그때의 평가 결과값은 bestscore속성에 기록됨
    -> (즉, cv_results_의 rank_test_score가 1일 때의 값임)
    -> refit은 default값이 True이므로, 최적의 하이퍼 파라미터로 알아서 학습된 모델은 bestestimator에 기록됨.
In [23]:
# best_params_와 best_score_ 속성을 이용하면 최적 하이퍼 파라미터의 값과 그때의 정확도를 알 수 있음
print('GridSearchCV 최적 파라미터:', grid_dtree.best_params_)
print('GridSearchCV 최고 정확도: {0:.4f}'.format(grid_dtree.best_score_))

# max_depth가 3, min_samples_split이 2일 때, 검증용 폴드 세트에서 평균 최고 정확도가 97.50 %로 기록됨.
 
GridSearchCV 최적 파라미터: {'max_depth': 3, 'min_samples_split': 2}
GridSearchCV 최고 정확도: 0.9750
 
In [24]:
# GridSearchCV 객체의 생성 파라미터로 refit = True가 default임
# refit = True면 GridSearchCV가 최적 성능을 나타내는 하이퍼 파라미터로 알아서 Estimator를 학습해 best_estimator_로 저장함

# 이미 학습된 best_estimator_를 이용해 앞에서 train_test_split()로 분리한 test data set에 대해 예측하고 성능을 평가해볼 수 있음

# GridSearchCV의 refit으로 이미 학습이 된 estimator 반환
estimator = grid_dtree.best_estimator_

# GridSearchCV의 best_estimator_는 이미 최적 하이퍼 파라미터로 학습이 됨
pred = estimator.predict(X_test)
print('테스트 데이터 세트 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))
 
테스트 데이터 세트 정확도: 0.9667
 
  • 일반적으로 train data를 GridSearchCV를 이용해 최적 하이퍼 파라미터 튜닝을 수행한 뒤,
  • 별도의 test data set에서 이를 평가하는 것이 일반적인 머신러닝 모델 적용 방법임.