검증세트 활용방법 - 교차 검증
혼자 공부하는 머신러닝+딥러닝 / 박해선 저
검증세트
- 기존처럼 데이터를 triain set과 test set으로만 분할해서 활용하면, 내가 구축한 모델이 과대적합인지 과소적합인지 판단하기 어려움.
- 이 때 테스트 세트를 활용하지 않고 내 모델을 평가하기 위해 별도로 검증세트를 두는 개념임.
- 일반적으로 전체 100의 데이터 중 훈련 세트를 약 60%, 검증과 테스트 세트를 각 20%씩으로 분할해서 활용.
1. 검증세트의 개념 직접 만들어보기
import pandas as pd
import numpy as np
wine = pd.read_csv('https://bit.ly/wine_csv_data')
data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()
# 자료 불러오고 독립변수 data와 종속변수 target으로 분할.
from sklearn.model_selection import train_test_split
# train 과 test 데이터로 나누기 위한 train_test_split 함수 불러오기
train_input, test_input, train_target, test_target = train_test_split(
data, target, test_size = 0.2, random_state = 42)
# 1차적으로 train, test 셋 나눠주기, test_size는 설정 안하면 0.25 / random_state는 seed를 고정하기 위함.
sub_input, val_input, sub_target, val_target = train_test_split(
train_input, train_target, test_size = 0.2, random_state = 42)
# train 셋을 검증셋과 트레인셋으로 다시 한 번 8:2로 분할.
print(sub_input.shape, val_input.shape)
# (4157, 3) (1040, 3)
# 분할이 제대로 되었는지 shape 함수를 통해 확인
from sklearn.tree import DecisionTreeClassifier
# sklearn의 의사결정나무 분류기 불러오기
dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)
# 훈련셋을 통한 학습
print(dt.score(sub_input, sub_target))
# 0.977
print(dt.score(val_input, val_target))
# 0.864
2. 교차 검증
from sklearn.model_selection import cross_validate
# 교차검증 함수 불러오기
scores = cross_validate(dt, train_input, train_target)
print(scores)
cross_validate 함수를 불러와 scores로 인스턴스 생성.
이 함수는 cv = None 인 경우 기본적으로 5-Fold cross validation을 수행함.
이후 그 결과값으로
- 'fit_time' : 모델 훈련 소요시간
- 'score_time' : 모델 검증 소요시간
- 'test_score' : 교차검증의 최종 점수
위 세 가지 키를 가진 딕셔너리를 반환함. 지금 수준에서 내가 가장 관심있는 것은 세번째인 test_score뿐
print(np.mean(scores['test_score']))
# 0.8697
이 값은 현재 가진 테스트세트를 가지고 5종류의 검증세트를 만들어 돌려봤을 때의 평균으로, 대략적인 내 모델의 성능을 가늠할수 있음.
다만, 방금은 train_test_split 함수로 한 번 섞어서 미리 분할을 했기때문에 바로 사용해도 무관하지만
cross_validate 함수는 훈련세트를 섞어주지 않음. 때문에 훈련세트를 섞기 위한 분할기(splitter)를 별도로 지정해야 함.
cross_validate 함수는 회귀 모델일 경우 KFold 분할기를 사용하고 분류 모델일 경우 StratifiedKFold를 사용.
from sklearn.model_selection import StratifiedKFold
splitter = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 42)
scores = cross_validate(dt, train_input, train_target, cv = splitter)
print(np.mean(scores['test_score']))
# 0.8574181117533719
StratifiedKFold의 기본값은 n_splits = 5로 5-fold 검증을 수행하나 여기서는 10으로 지정하였음.