Python 데이터 분석

Python 데이터분석 기초 59 - 일반화 모델을 위한 과적합 방지 방법

코딩탕탕 2022. 11. 21. 13:17

 

 

1. train/test split 방법

2. Validation = train data를 쪼개 학습과 검정을 같이한다.  교차검증(cross validation) - train/test split을 해도 과적합 발생 또는 데이터의 양이 적은 경우

3. GridSearchCV = 최적의 모델을 찾아준다.

 

출처 : https://www.incodom.kr/k-%EA%B2%B9_%EA%B5%90%EC%B0%A8_%EA%B2%80%EC%A6%9D#h_d3e91c610b516ce3921ca1acac72a30d

 

'''
일반화 모델을 위한 과적합 방지 방법
iris dataset을 사용
train/test split, KFold, GridSearchCV
'''
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

iris=load_iris()
print(iris.keys())

train_data=iris.data
train_label=iris.target
print(train_data[:3])
print(train_label[:3])

print('분류 모델')
dt_clf=DecisionTreeClassifier()
print(dt_clf)
dt_clf.fit(train_data, train_label)

dt_clf.fit(train_data, train_label)
pred=dt_clf.predict(train_data)

print('예측값 : ', pred)
print('실제값 : ', train_label)
print('예측 정확도 : ', accuracy_score(train_label, pred))
# 1.0은 뭔가 이상하다, 과적합

print('\n과적합 방지 방법1 : train/test split')
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=121)
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
print(x_train[:5])
print(iris.data[:5])
dt_clf.fit(x_train, y_train) #트레인 데이터로 학습
pred2=dt_clf.predict(x_test) #테스트 데이터로 검정

print('예측값 : ', pred2)
print('실제값 : ', y_test)
print('예측 정확도 : ', accuracy_score(y_test, pred2))
# 예측 정확도 :  0.955555555555
# 100% 가 되지 않도록 처리함, 모델의 포용성을 위해
# 100%이면 자신의 정확하게 학습한 데이터만 인식하기 때문에
# 조금 달라도 맞다고 하는 것이다.

print('"추론통계는 모든 환경에서 100%가 되어서는 안된다."라는 철학을 이해하자')

'''
https://modern-manual.tistory.com/19
train 데이터에 대해서 validation을 쓰는 것이다.
https://www.incodom.kr/k-%EA%B2%B9_%EA%B5%90%EC%B0%A8_%EA%B2%80%EC%A6%9D#:~:text=%EA%B5%90%EC%B0%A8%20%EA%B2%80%EC%A6%9D%EC%9D%B4%EB%9E%80%20%EC%89%BD%EA%B2%8C%20%EB%A7%90%ED%95%B4,%EC%96%BB%EC%9D%84%20%EC%88%98%20%EC%9E%88%EA%B8%B0%20%EB%95%8C%EB%AC%B8%EC%9D%B4%EB%8B%A4.
k-fold cross-validation(k-겹 교차 검증)
-> k는 몇 개로 접어서 1개의 validation fold 와 k-1개의traing으로 나눠서
비교해서 돌면서 해당 퍼포먼스의 전체 평균을 구해서 사용한다
'''

print('\n과적합 방지 방법2 : 교차검증(cross validation) - train/test split을 해도 과적합 발생 또는 데이터의 양이 적은 경우')
#모델 학습 도중 train data를 쪼개 validation data를 만든 후 학습시 검증을 함께 함
#K-fold 교차검증 : train data를 k개 접어 validation data로 사용

from sklearn.model_selection import KFold
import numpy as np
features = iris.data
label = iris.target
dt_clf = DecisionTreeClassifier(criterion='entropy', random_state=123)
kfold=KFold(n_splits = 5)

cv_acc = []
print('iris shape : ', features.shape)
#iris shape :  (150, 4)
# 전체 행수 : 150, 학습데이터 : 4/5 ,120개, 검증 데이터 : 1/5, 30개

n_iter = 0
for train_index, test_index, in kfold.split(features):
    # print('n_iter : ', n_iter)
    # print('train_index : ', train_index)
    # print('test_index : ', test_index)
    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
    #반복할 때마다 정확도 측정
    acc = np.round(accuracy_score(y_test, pred), 3)
    train_size = x_train.shape[0] # (행,열)
    test_size = x_test.shape[0]
    print('반복수 : {0}, 교차검증 정확도 : {1}, 학습데이터 크기 : {2}, 검증데이터 크기 : {3}'
            .format(n_iter, acc, train_size, test_size ))
    print('반복수 : {0}, 검증 데이터 인덱스 : {1}'.format(n_iter, test_index))
    cv_acc.append(acc)

print('평균 검정 정확도 : ', np.mean(cv_acc))


print('\n과적합 방지 방법2-1 : 교차검증(cross validation) - 불균형한 분포(편향, 왜곡)을 가진 경우')
#불균형이란 특정 레이블 값이 특이하게 많거나 적은 경우
from sklearn.model_selection import StratifiedKFold
skfold = StratifiedKFold(n_splits=5)

cv_acc = []
n_iter = 0
for train_index, test_index, in skfold.split(features, label):
    # print('n_iter : ', n_iter)
    # print('train_index : ', train_index)
    # print('test_index : ', test_index)
    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
    #반복할 때마다 정확도 측정
    acc = np.round(accuracy_score(y_test, pred), 3)
    train_size = x_train.shape[0] # (행,열)
    test_size = x_test.shape[0]
    print('반복수 : {0}, 교차검증 정확도 : {1}, 학습데이터 크기 : {2}, 검증데이터 크기 : {3}'
            .format(n_iter, acc, train_size, test_size ))
    print('반복수 : {0}, 검증 데이터 인덱스 : {1}'.format(n_iter, test_index))
    cv_acc.append(acc)

print('평균 검정 정확도 : ', np.mean(cv_acc))


print('\n과적합 방지 방법3 : cross_val_score 함수로 간단하게 쓸 수 있다')
from sklearn.model_selection import cross_val_score
data=iris.data
label = iris.target

score=cross_val_score(dt_clf, data, label, scoring='accuracy', cv=5)
print('교차 검증별 정확도 : ', np.round(score, 3))
print('평균 검정 정확도 : ', np.round(np.mean(score), 3))


print('\n과적합 방지 방법4 : GridSearchCV - 모델 생성시 최적의 parameter 찾기')
from sklearn.model_selection import GridSearchCV
# max_depth = 트리의 최대 깊이 , min_samples_split = 노드 분할을 위한 최소 표본수 제어값
para={'max_depth' : [1,2,3], 'min_samples_split':[2,3]}

grid_dtree = GridSearchCV(dt_clf, param_grid=para, cv=3, refit=True)
grid_dtree.fit(x_train, y_train) 
# GridSearchCV를 사용하여, 자동으로 복수의 내부 모형을 생성한 후, 최적의 파라미터를 찾음 

import pandas as pd
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']
pd.set_option('display.max_columns', 500)
print(scores_df)
print('GridSearchCV 최적 파라미터 :', grid_dtree.best_params_)
print('GridSearchCV 최고 정확도 {0:4f}'.format(grid_dtree.best_score_))
# best 파라미터값을 제공한다. 최고 정확도도 제공.

# df_clf = DecisionTreeClassifier(max_depth = 2, min_samples_split = 2)

best_df_clf = grid_dtree.best_estimator_
print(best_df_clf)
pred = best_df_clf.predict(x_test)
print(pred)
print('best_df_clf acc :', accuracy_score(y_test, pred))





<console>
dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]]
[0 0 0]
분류 모델
DecisionTreeClassifier()
예측값 :  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]
실제값 :  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]
예측 정확도 :  1.0

과적합 방지 방법1 : train/test split
(105, 4) (45, 4) (105,) (45,)
[[6.3 2.8 5.1 1.5]
 [6.8 3.2 5.9 2.3]
 [4.8 3.4 1.9 0.2]
 [6.3 2.5 4.9 1.5]
 [5.  3.5 1.3 0.3]]
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]]
예측값 :  [1 2 1 0 0 1 1 1 1 2 2 1 1 0 0 2 1 0 2 0 2 2 1 1 1 1 0 0 2 2 1 2 0 0 1 2 0
 0 0 2 2 2 2 0 1]
실제값 :  [1 2 1 0 0 1 1 1 1 2 1 1 1 0 0 2 1 0 2 0 2 2 1 1 1 1 0 0 2 2 1 2 0 0 1 2 0
 0 0 2 2 2 2 0 2]
예측 정확도 :  0.9555555555555556
"추론통계는 모든 환경에서 100%가 되어서는 안된다."라는 철학을 이해하자

과적합 방지 방법2 : 교차검증(cross validation) - train/test split을 해도 과적합 발생 또는 데이터의 양이 적은 경우
iris shape :  (150, 4)
반복수 : 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.967, 학습데이터 크기 : 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.9, 학습데이터 크기 : 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.933, 학습데이터 크기 : 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.8, 학습데이터 크기 : 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.9199999999999999

과적합 방지 방법2-1 : 교차검증(cross validation) - 불균형한 분포(편향, 왜곡)을 가진 경우
반복수 : 1, 교차검증 정확도 : 0.967, 학습데이터 크기 : 120, 검증데이터 크기 : 30
반복수 : 1, 검증 데이터 인덱스 : [  0   1   2   3   4   5   6   7   8   9  50  51  52  53  54  55  56  57
  58  59 100 101 102 103 104 105 106 107 108 109]
반복수 : 2, 교차검증 정확도 : 0.967, 학습데이터 크기 : 120, 검증데이터 크기 : 30
반복수 : 2, 검증 데이터 인덱스 : [ 10  11  12  13  14  15  16  17  18  19  60  61  62  63  64  65  66  67
  68  69 110 111 112 113 114 115 116 117 118 119]
반복수 : 3, 교차검증 정확도 : 0.9, 학습데이터 크기 : 120, 검증데이터 크기 : 30
반복수 : 3, 검증 데이터 인덱스 : [ 20  21  22  23  24  25  26  27  28  29  70  71  72  73  74  75  76  77
  78  79 120 121 122 123 124 125 126 127 128 129]
반복수 : 4, 교차검증 정확도 : 0.933, 학습데이터 크기 : 120, 검증데이터 크기 : 30
반복수 : 4, 검증 데이터 인덱스 : [ 30  31  32  33  34  35  36  37  38  39  80  81  82  83  84  85  86  87
  88  89 130 131 132 133 134 135 136 137 138 139]
반복수 : 5, 교차검증 정확도 : 1.0, 학습데이터 크기 : 120, 검증데이터 크기 : 30
반복수 : 5, 검증 데이터 인덱스 : [ 40  41  42  43  44  45  46  47  48  49  90  91  92  93  94  95  96  97
  98  99 140 141 142 143 144 145 146 147 148 149]
평균 검정 정확도 :  0.9534

과적합 방지 방법3 : cross_val_score 함수로 간단하게 쓸 수 있다
교차 검증별 정확도 :  [0.967 0.967 0.9   0.933 1.   ]
평균 검정 정확도 :  0.953

과적합 방지 방법4 : GridSearchCV - 모델 생성시 최적의 parameter 찾기
   mean_fit_time  std_fit_time  mean_score_time  std_score_time  \
0       0.000332      0.000470         0.000000         0.00000   
1       0.000664      0.000470         0.000000         0.00000   
2       0.000499      0.000407         0.000000         0.00000   
3       0.000333      0.000471         0.000000         0.00000   
4       0.000333      0.000470         0.000332         0.00047   
5       0.000332      0.000470         0.000332         0.00047   

  param_max_depth param_min_samples_split  \
0               1                       2   
1               1                       3   
2               2                       2   
3               2                       3   
4               3                       2   
5               3                       3   

                                     params  split0_test_score  \
0  {'max_depth': 1, 'min_samples_split': 2}              0.675   
1  {'max_depth': 1, 'min_samples_split': 3}              0.675   
2  {'max_depth': 2, 'min_samples_split': 2}              0.950   
3  {'max_depth': 2, 'min_samples_split': 3}              0.950   
4  {'max_depth': 3, 'min_samples_split': 2}              0.950   
5  {'max_depth': 3, 'min_samples_split': 3}              0.950   

   split1_test_score  split2_test_score  mean_test_score  std_test_score  \
0               0.65               0.65         0.658333        0.011785   
1               0.65               0.65         0.658333        0.011785   
2               0.95               0.90         0.933333        0.023570   
3               0.95               0.90         0.933333        0.023570   
4               0.95               0.90         0.933333        0.023570   
5               0.95               0.90         0.933333        0.023570   

   rank_test_score  
0                5  
1                5  
2                1  
3                1  
4                1  
5                1  
GridSearchCV 최적 파라미터 : {'max_depth': 2, 'min_samples_split': 2}
GridSearchCV 최고 정확도 0.933333
DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=123)
[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2]
best_df_clf acc : 1.0