상세 컨텐츠

본문 제목

[파이썬 머신러닝] 교차검증 K-Fold 와 Cross_val_score() (feat. GridSearchCV)

파이썬 머신러닝

by Kang Gyung Hun 2024. 1. 1. 15:57

본문

1.  교차검증이란

2. K-Fold

 2-1. Stratified K-Fold

3. Cross_val_score()

4. GridSearchCV

 

 

1. 교차검증이란

머신러닝을 수행할 때 흔히 데이터를 학습 데이터와 테스트 데이터로 나눈 후, 학습 데이터를 통해 모델을 학습하고 테스트 데이터로 최종 평가를 하게된다. 이 때 테스트 데이터에 대한 예측만 잘하도록(과적합) 모델이 설계 될 수 있는데, 이런 문제를 개선하기 위해  학습 데이터를 통한 교차검증을 수행하게 된다.

 

(출처: 코드스테이츠)

 

학습 데이터와 테스트 데이터를 나눈 후, 학습 데이터를 다시 학습 데이터와 검증 데이터로 나눈다. 이 때 검증 데이터는 테스트 데이터처럼 분리시켜 놓는 것이 아니라, 데이터의 모든 부분들이 검증데이터로 사용될 수 있도록 한다(우연히 데이터가 잘 나눠져서 성능이 좋거나 나쁘게 나오는 것을 방지). 

몇 번의 검증을 할지는 파라미터를 통해 전달하고 그 수만큼 학습 데이터가 나눠진다. 검증 횟수만큼 평가를 하고 최종적으로 모든 평가를 평균을 내서 교차검증의 결과를 얻는다. 

 

위에서 교차검증은 모델이 과적합 되는 것을 막기 위함이라고 설명했는데, 교차검증을 하는 이유가 꼭 과적합 때문만은 아니다. 쉽게 설명하자면 교차검증은 테스트 데이터로 최종 평가를 진행하기 전에 수행되는 1차 테스트라고 보면 된다. 1차 테스트의 결과를 통해 우리는 모델을 수정하고 최종 평가에서 더 좋은 결과를 얻도록 한다.

 

교차 검증을 수행하는 방법을 예제 코드를 통해 알아보자.

 

2. K-fold

K-fold는 가장 보편적으로 사용되는 교차검증 방법이다. 학습데이터를 k 개로 나눈후 k 번의 검증을 수행한다. 이때 학습데이터의 크기는 k-1/ k, 검증데이터의 크기는 1/k이다. 예를들어 k = 5라면 학습데이터의 크기는 전체 학습데이터의 4/5, 검증데이터는 1/5가 된다.

 

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

iris = load_iris() # sklean에 있는 붓꽃 예제 데이터 불러오기
features = iris.data # feature 데이터만 분리 
label = iris.target # target 데이터만 분리

dc_clf = DecisionTreeClassifier(random_state=156) # 의사결정나무 모델 객체 생성
kfold = KFold(n_splits=5) # K-fold 객체 생성/ n_splits 매개변수를 통해 데이터 나누는 횟수 전달
accuracy_avg = [] # 각 검증 별 평가결과 담는 빈 리스트 생성

for train_index, test_index in kfold.split(features): # split 매서드를 통해 학습/검증 데이터의 인덱스 추출
    X_train, X_test = features[train_index], features[test_index] #인덱스를 통해 학습/검증 데이터 분리
    y_train, y_test = label[train_index], label[test_index]
    
    dc_clf.fit(X_train,y_train) # 모델 학습
    pred = dc_clf.predict(X_test) # 예측
    accuracy = accuracy_score(y_test,pred) # 정확도 평가
    
    accuracy_avg.append(accuracy) # 정확도 결과를 처음 생성한 리스트에 삽입

print(np.mean(accuracy_avg)) # 리스트 안에있는 결과들의 평균 점수 출력
0.9

 

2-1. Stratified K-Fold

Stratified K-Fold의 경우 K-Fold와 방법은 같지만 레이블 데이터의 분포를 고려해서 학습/검증데이터를 나눈다. 예를들어 암 진단 데이터의 경우 실제 암인 사람들의 비율은 정상인 사람들에 비해 매우 적을 것이다. 이처럼 대부분의 이진분류 문제는(보함사기, 당뇨병 등) 레이블 데이터 분포가 불균형 데이터인 경우가 대부분임으로 보통 Stratified K-Fold가 사용된다.

 

K-Fold 와의 차이점은  Stratified K-Fold는 레이블 데이터의 분포를 고려하기 때문에 split() 의 인자로 feature 데이터 뿐만 아니라 label 데이터도 전달해줘야 한다.

import numpy as np
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold

iris = load_iris() # sklearn에 있는 붓꽃 데이터 불러오기
features = iris.data # feature 데이터 분리
label = iris.target # target 데이터 분리

dt_clf = DecisionTreeClassifier(random_state=156) # 의사결정나무 객체 생성
skfold = StratifiedKFold(n_splits=5) # Stratified KFold 객체 생성
accuracy_avg =[]

for train_index, test_index in skfold.split(features, label): # KFold와 다르게 label데이터도 전달
    X_train, X_test = features[train_index], features[test_index]
    y_train, y_test = label[train_index], label[test_index]
    
    dc_clf.fit(X_train, y_train)
    pred = dc_clf.predict(X_test)
    accuracy = accuracy_score(y_test,pred)
    accuracy_avg.append(accuracy)
    
print(np.mean(accuracy_avg))
0.9600000000000002

 

 

3. Cross_val_score ()

cross_val_score () 를 통해 K-Fold를 간단하게 수행할 수 있습니다. 먼저 cross_val_score() 어떤 매개 변수가 있는지 알아 봅시다.

 

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 : 교차 검증 수 ( k )

from sklearn.model_selection import cross_val_score 
# 위 K-Fold 코드에 이어서 작성
scores = cross_val_score(dt_clf, features, label,scoring='accuracy', cv=3) # dt_clf 의사결정나무 estimator전달
                                                                           # 평가 지표는 'accuracy' (정확도)
                                                                           # cv 전달을 통해 검증 횟수 전달
print(np.mean(scores))
# scores 는 각 검증마다 평가 결과를 담은 nd.array임

이처럼 cross_val_score()를 통해 훨씬 간단한 코드로 K-Fold를 수행할 수 있습니다.

알아두어야 할 것은  

1. cross_val_score()는 분류 estimator에 대해 자동으로 stratified K-Fold를 수행한다

2. cross_validate() 를 통해 여러가지 평가 지표를 반환할 수 있다.

 

4. GridSearchCV

GridSearchCV는 파라미터 튜닝과 교차검증을 동시에 수행해주는 API이다. GridSearchCV 생성자로 들어가는 주요 파라미터에 대해 알아보자.

 

estimator : 분류 또는 회귀 모델

param_grid : 파라미터 이름과 파라미터 값들을 딕셔너리 형태로 전달

scoring : 평가 지표

cv : 교차 검증 수

refit : 디폴트가 True 임. 최적의 파라미터를 찾은 후 해당 파라미터로 estimator를 재학습 시킴.

 

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import accuracy_score

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

X_train, X_test, y_train, y_test = train_test_split(features, label, test_size=0.2, random_state=121)
# 학습데이터와 테스트 데이터 분리
dt_clf = DecisionTreeClassifier() # 의사결정나무 객체 생성
parameters = {'max_depth': [1,2,3], 'min_samples_split':[2,3]} # 파라미터 명과 값을 딕셔너리 형태로 전달

grid_tree = GridSearchCV(dt_clf, param_grid=parameters, cv=3, refit=True) # GridSearchCV 객체 생성
grid_tree.fit(X_train, y_train) # 전달한 파라미터 경우의 수 만큼 학습

 

여기서 모델은 전달받은 파라미터를 바탕으로 최적의 결과를 도출하는 파라미터를 선택 후 학습함.

 

best_tree = grid_tree.best_estimator_ # best_estimator_ 속성에 저장된 최적의 파라미터로 학습된 모델
pred = best_tree.predict(X_test) # 최적 모델로 예측
accuracy = accuracy_score(y_test, pred) # 예측 결과 평가
print('테스트 데이터 세트 정확도:', accuracy) # 평가 결과 반환
테스트 데이터 세트 정확도: 0.9666666666666667

 

GridSearchCV는 데이터가 많을 경우 연산 시간이 오래 걸린다. 위 예제에서는 파라미터 경우의 수 3 x 2 = 6마다 각각 3번의 교차 검증을 수행하기 때문에 총 18번 연산이 수행된다. 

 

GridSearchCV 의 과정에서 저장되는 속성들을 통해 각 경우의 수별 결과를 확인 할 수도 있다.

 

cv_results_ : 각 파라미터별 평균 점수, 성능 등수, 각 횟수별 단일 점수 등을 알 수 있다. cv_results_는 nd.array이기 때문에 가시성을 위해 pd.DataFrame()을 통해 데이터 프레임으로 전환한뒤 보는 것을 추천한다.

 

아래는 '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

 

best_score_ : 최고 정확도를 반환한다.

best_params_ : 최적의 파라미터 조합을 반환한다.

best_estimator_ : 최적의 파라미터로 학습한 모델 객체를 반환한다.

 

 

 

이상 교차검증의 여러 방법들에 대해 알아보았다.

관련글 더보기