본문 바로가기
  • 데이터에 가치를 더하다, 서영석입니다.
공부하는 습관을 들이자/Python_ML

[2. (2) 교차 검증]

by 꿀먹은데이터 2021. 12. 30.

과적합(Overfitting)은 모델이 학습 데이터에만 과도하게 최적화되어, 실제 예측에서 성능이 과도하게 떨어지는 것이다.

교차 검증은 본시험에 앞서 모의 시험을 여러번 치루는 것과 같다.

데이터 편중을 막기 위해서 별도의 여러 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행하는 것이다.

K fold 교차 검증

https://nonmeyet.tistory.com/entry/KFold-Cross-Validation%EA%B5%90%EC%B0%A8%EA%B2%80%EC%A6%9D-%EC%A0%95%EC%9D%98-%EB%B0%8F-%EC%84%A4%EB%AA%85

K개의 데이터 폴드 세트를 만들어서 K번만큼 각 폴트 세트에 학습과 검증 평가를 반복적으로 수행하는 방법이다.

아래 그림은 K=5인 경우이다.

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)

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

n_iter=0

#KFold 객체의 split()를 호출하면 폴드 별 학습용, 검증용 테스트의 로우 인덱스를 array로 반환 
for train_index,test_index in kfold.split(features):
    #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)
    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)

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

1차 검증 : 0~29 | 2차 검증 : 30~59 | 3차 검증 : 60~89 | 4차 검증 : 90~119 | 5차 검증 : 120~149

Stratified K 폴드

불균형한 분포도를 가진 레이블 데이터 집합을 위한 K 폴드 방식이다.

import pandas as pd

iris=load_iris()
iris_df=pd.DataFrame(data=iris.data,columns=iris.feature_names)
iris_df['label']=iris.target
iris_df['label'].value_counts()

iris_df

Kfold() 사용으로 분류

kfold=KFold(n_splits=3)
n_iter=0
print('--------------------------------------------')
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('학습 레이블 데이터 분포:\n',label_train.value_counts())
    print('검증 레이블 데이터 분포:\n',label_test.value_counts())
    print('--------------------------------------------')

위와 같이 학습 레이블과 검증 레이블이 완전 다른 값으로 추출되었다. 학습 레이블은 1,2 밖에 없으므로 0의 경우 전혀 학습하지 못하는 등의 문제가 생기므로 이를 해결하기 위해 StratifiedKFold()를 사용한다.

StratifiedKFold() 사용으로 분류

from sklearn.model_selection import StratifiedKFold
skf= StratifiedKFold(n_splits=3)
n_iter=0
print('--------------------------------------------')
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('학습 레이블 데이터 분포:\n',label_train.value_counts())
    print('검증 레이블 데이터 분포:\n',label_test.value_counts())
    print('--------------------------------------------')

 

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('\n{0}검증 세트 인덱스:{1}'.format(n_iter,test_index))
    cv_accuracy.append(accuracy)

    #교차 검증별 정확도 및 평균 정확도 계산
    print('\n교차 검증별 정확도:',np.round(cv_accuracy,4))
    print('\n평균 검증 정확도:',np.mean(cv_accuracy))
    print('-------------------------------------------------------------------------------------------')

cross_val_score() - 교차 검증을 간편하게 하는 API

KFold의 데이터 학습 및 예측하는 과정을 한꺼번에 수행해주는 API다.

 

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

#성능 지표는 정확도, 교차 검증 세트는 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))

#cross_validate() : 여러 개의 평가 지표를 반환

GridSearchCV- 교차 검증과 최적 하이퍼 파라미터 튜닝을 한 번에!

교차 검증을 기반으로 하이퍼 파라미터의 최적 값을 찾게 해준다.

grid_parameters={'max_depth':[1,2,3],'min_samples_split':[2,3]}

 

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV

#데이터를 로딩하고 학습 데이터와 테스트 데이터 분리
iris_data=load_iris()
X_train,X_test,y_train,y_test=train_test_split(iris_data.data,iris_data.target,test_size=0.2,random_state=121)

dtree=DecisionTreeClassifier()

##파라미터를 딕셔너리 형태로 설정
parameters={'max_depth':[1,2,3],'min_samples_split':[2,3]}

 

GridSearchCV() 함수 파라미터 :

estimator : classifier, regressor, pipelie이 사용

param_grid : estimator의 튜닝을 위해 파라미터명과 사용될 여러 파라미터 값을 지정

scoring : 예측 성능을 측정할 평가 방법 지정

cv : 교차 검증을 위해 분할되는 학습/테스트 세트의 개수

refit : default 값 :TRUE , 최적의 하이퍼 파라미터를 찾은 뒤 재학습

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)

#붓꽃 학습 데이터로 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']]

4번과 5번의 rank_test_score은 1이다. 예측 성능이 1위를 의미한다.

print('GridSearchCV 최적 파라미터:',grid_dtree.best_params_)
print('GridSearchCV 최고 정확도:{0:.4f}'.format(grid_dtree.best_score_))

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

#GridSearchCV의 best_estimator_는 이미 최적 학습이 됐으므로 별도 학습이 필요 없음
pred=estimator.predict(X_test)
print('테스트 데이터 세트 정확도:{0:.4f}'.format(accuracy_score(y_test,pred)))

정확도는 96.67로 최적의 학습을 하였다.

'공부하는 습관을 들이자 > Python_ML' 카테고리의 다른 글

[2-4]타이타닉 생존자 예측  (0) 2022.01.05
[#3]데이터 전처리  (0) 2022.01.01
[2. (1) 붓꽃 품종 예측하기]  (0) 2021.12.29
부스팅 알고리즘  (0) 2021.12.29