세상을 바꾸는 데이터

교차 검증 #1 - "수능"을 보기 위해 "모의고사"를 푸는 것 (KFold & Stratified KFold) 본문

ML/scikit-learn(사이킷런)

교차 검증 #1 - "수능"을 보기 위해 "모의고사"를 푸는 것 (KFold & Stratified KFold)

Industriousness 2022. 2. 3. 18:24

 

교차검증이란?

별도의 여러 세트로 구성된 학습 데이터 세트검증 데이터 세트에서 학습과 평가를 수행하는 것

용어 정리

학습 데이터 세트: 알고리즘을 학습시키는 데이터 세트
검증 데이터 세트: 학습된 모델의 성능을 1차 평가하는 데이터 세트
테스트 데이터 세트: 모든 학습/검증 과정이 완료된 후 최종적으로 성능을 평가하는 데이터 세트

교차검증을 하는 이유

알고리즘을 학습시키려면 학습 데이터와 예측 성능을 평가하기 위한 별도의 테스트 데이터가 있어야 한다.
하지만 이 방법은 과적합(Overfitting)에 취약한 단점이 있다.
과적합은 모델이 학습 데이터에만 과도하게 최적화되어, 실제 예측을 다른 데이터로 수행할 경우에는 예측 성능이 과도하게 떨어지는 것을 말한다.
고정된 데이터로만 학습하고, 이를 테스트 데이터로 평가를 하게 되면 테스트 데이터에만 과적합되는 학습 모델이 만들어진다. 결과적으로 다른 테스트 데이터가 들어올 경우 예측 성능이 저하된다.
이는 고등학생이 입시공부를 했는데 모의고사는 건너뛰고 수능 문제를 바로 푸는 것과 다름이 없다.
이러한 문제를 개선하기 위해 교차 검증을 실시한다.

데이터들이 독립적이고 동일한 분포를 가진 경우


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

K겹 교차검증

다음 그림은 5 폴드 교차검증을 수행한 것이다.
5개로 나눈 데이터 세트를 학습과 검증을 위한 테스트 세트를 변경하면서 5번 평가를 수행한 뒤, 이 5개의 평가를 평균한 결과를 가지고 예측 성능을 평가한다.
K폴드 교차검증 순서를 자세히 알아보자.

  • 1. 데이터 세트를 5등분(K등분)한다.
  • 2. 첫 번째 반복에서 처음부터 4개 등분을 학습 데이터 세트로, 마지막 5번째 등분을 검증 데이터 세트로 설정한다.
  • 2-2. 학습 데이터에서 학습을 수행하고, 검증 데이터 세트에서 평가를 수행한다.
  • 3. 두 번째 반복에서 처음부터 3개 등분, 5개 등분을 학습 데이터 세트로, 4번째 등분을 검증 데이트 세트로 설정한다.
  • 3-2. 학습 데이터에서 학습을 수행하고, 검증 데이터 세트에서 평가를 수행한다.
  • 4. 이를 5번 반복하면서 학습과 검증을 수행한다.
  • 5. 마지막으로 5개의 예측 평가를 평균을 내 K폴드 평가 결과로 반영하면 된다.

K fold 5번 수행


실습
이전에 사용했던 사이킷런 내장 데이터인 붓꽃 데이터를 이용해 K폴드 교차검증을 수행해보자.
K폴드 교차검증을 사용하기 위하여 sklearn.model_selection에서 KFOLD를 import 하자.
KFOLD에 대한 파라미터들은 다음과 같이 n_splits, shuffle, random_state가 있다.

사이킷런 KFold 사용법

 

  • n_splits는 몇 개의 데이터 세트로 나눌 것인가를 의미한다.
  • shuffle은 데이터를 나누기 전에 데이터를 고르게 섞는 것이다.
  • random_state는 수행할 때마다 동일한 데이터 세트로 분리하는 것을 의미하며, 교차검증에서는 효과적이지 않다.

(이에 대한 자세한 parameter에 대한 내용은 참고 자료에 있다)

사용 언어는 python이다.

 

from sklearn.tree import DecisionTreeClassifier #결정트리 알고리즘 이용 
from sklearn.metrics import accuracy_score # 정확도 분석에 사용 
from sklearn.model_selection import KFold # 모델 학습을 위해 K폴드 사용 
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

 


전체 붓꽃 데이터 세트 크기가 150이고, 5개의 폴드 데이터 세트이기 때문에 120개(4/5)는 학습용 데이터 세트로, 30개(1/5)는 검증용 데이터세트로 분리한다.
KFold 객체의 split( )을 호출해 교차 검증 수행 시마다 학습과 검증을 반복해 예측 정확도를 측정한다.

KFold 객체의 split( ) 이용


KFold 객체의 split( )은 X값으로 학습하고자 하는 데이터 세트를 넣어야 한다.
y에는 레이블 데이터 세트가 들어가야 하지만 입력을 안 해도 무방하다.

 

n_iter = 0 # KFold객체의 split( ) 호출하면 폴드 별 학습용, 검증용 테스트의 로우 인덱스를 array로 반환 
for train_index, test_index in kfold.split(features): 
	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) 
    cv_accuracy.append(accuracy) # 개별 iteration별 정확도를 합하여 평균 정확도 계산
    print('평균 검증 정확도:', np.mean(cv_accuracy)) # 평균 정확도: 0.9

 


5번 교차 검증한 결과 평균 검증 정확도는 0.9 임을 알 수 있다.

데이터들의 분포가 다른 경우


Stratified K 폴드 교차 검증
이론
Stratified K 폴드불균형한 분포도를 가진 레이블(결정 클래스) 데이터 집합을 위한 K 폴드 방식이다.
여기서 불균형한 분포도를 가진 레이블 데이터 집합은 특정 레이블 값이 특이하게 많거나 매우 적어서 값의 분포가 한쪽으로 치우치는 것을 말한다.
Stratified K 폴드는 기존의 K폴드가 레이블 데이터 집합이 원본 데이터 집합의 레이블 분포를 학습 및 테스트 세트에 제대로 분배하지 못하는 경우의 문제를 해결해준다.

train 셋과 test 셋이 레이블(class)별로 골고루 선택되어 있는 모습



실습
앞에서 실시한 KFold의 문제를 확인해보고 이를 StratifiedKFold로 개선시켜보자.
StratifiedKFold는 레이블 데이터 분포도에 따라 학습과 검증 데이터를 나누기 때문에, KFold와 다르게 split( ) 메서드에 인자로 피처 데이터 세트뿐만 아니라 레이블 데이터 세트도 반드시 입력해야 한다.

StratifiedKFold split 클래스에는 x, y값이 필수로 들어가야한다


3개의 폴드 세트로 StratifiedKFold을 시행하고, 학습 레이블과 검증 레이블의 데이터가 어떻게 분포되는지 먼저 살펴보자.

 

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

 


[Output]


출력 결과를 보면 학습 레이블과 검증 레이블 데이터의 값이 골고루 분포되어 있음(17, 17, 16)을 알 수 있다. 이렇게 분할이 되어야 레이블 값 0,1,2(붓꽃의 품종을 숫자로 나타낸 번호)를 모두 학습할 수 있고, 검증할 수 있다.
이제 StratifiedKFold 교차검증을 실시하여 정확도를 확인해보자.

 

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) 
    cv_accuracy.append(accuracy) # 교차 검증별 정확도 및 평균 정확도 계산 
    
print('교차 검증별 정확도:', np.round(cv_accuracy, 4)) # 교차 검증별 정확도: [0.98, 0.94, 0.98] 
print('평균 검증 정확도:', np.mean(cv_accuracy)) # 평균 검증 정확도: 0.9666666666666667

 


3개의 Stratified K 폴드로 교차 검증한 결과 평균 검증 정확도가 약 96.6%로 측정되었다. 이는 앞서 측정한 일반 K 폴드의 정확도인 90%보다 높다.
이처럼 Stratified K 폴드는 원본 데이터의 레이블 분포도 특성을 반영한 학습 및 검증 데이터 세트를 만들 수 있으므로 왜곡된 레이블 데이터 세트에서는 반드시 이 Stratified K 폴드를 이용해 교차 검증해야 한다.

* 분류에서 K 폴드 대신 Stratified K 폴드로 교차검증을 대부분 실시한다.
* 회귀에서는 Stratified K 폴드는 지원되지 않는다. 회귀의 결정 값은 연속된 숫자 값이므로 결정 값 별로 분포를 정하는 것이 의미가 없기 때문이다.



출처:
https://thebook.io/080228/part04/ch13/05/
https://z-images.s3.amazonaws.com/e/e6/07_cross_validation_diagram.png
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html

 

sklearn.model_selection.KFold

Examples using sklearn.model_selection.KFold: Feature agglomeration vs. univariate selection Feature agglomeration vs. univariate selection, Gradient Boosting Out-of-Bag estimates Gradient Boosting...

scikit-learn.org


https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html

 

sklearn.model_selection.StratifiedKFold

Examples using sklearn.model_selection.StratifiedKFold: Recursive feature elimination with cross-validation Recursive feature elimination with cross-validation, GMM covariances GMM covariances, Tes...

scikit-learn.org

https://i.stack.imgur.com/XJZve.png
https://github.com/chulminkw/PerfectGuide/blob/master/1%EC%9E%A5/1.3%20%EB%84%98%ED%8C%8C%EC%9D%B4.ipynb
http://www.yes24.com/Product/Goods/69752484


728x90
반응형
Comments