과적합 : 모델이 학습 데이터에만 과도하게 최적화되어, 실제 예측을 다른 데이터로 수행할 경우에는 예측 성능이 과도하게 떨어지는것을 말한다.
이번 블로그는 과적합을 방지할 수 있는 교차검증 에 대해 얘기하려합니다.
교차검증 : 데이터 편중을 막기 위해서 별도의 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행하는 것입니다.
1. KFold
from sklearn.model_selection import KFold from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score import numpy as np iris = load_iris() features = iris.data label = iris.target dtc = 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] # 학습 및 예측 dtc.fit(X_train, y_train) pred = dtc.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) # 개별 iteration별 정확도를 합하여 평균 정확도 계산 print('\n## 평균 검증 정확도:', np.mean(cv_accuracy))
이런 경우를 해결할 수 있는것이 StratifiedKFold입니다
StratifiedKFold : 불균형한 분포도를 가진 레이블 데이터 집합을 위한 KFold 방식입니다.
kfold = KFold(n_splits=3)
n_iter = 0
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())
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())
그럼 KFold와 StratifiedKFold는 언제 써야 할까요?
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score, cross_validate
from sklearn.datasets import load_iris
iris = load_iris()
dtc = DecisionTreeClassifier(random_state=156)
data = iris.data
label = iris.target
# 성능 지표는 정확도(accuracy), 교차 검증 세트는 3개
scores = cross_val_score(dtc, data, label, scoring='accuracy', cv=3)
print('교차 검증별 정확도:', np.round(scores,4))
print('평균 검증 정확도:', np.round(np.mean(scores)))
먼저 *하이퍼 파라미터란?
: 최적의 훈련 모델을 구현하기 위해 모델에 설정하는 변수
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
# 데이터를 로딩하고 학습 데이터와 테스트 데이터 분리
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.2, random_state=121
)
dtc = DecisionTreeClassifier()
params = {
'max_depth': [1,2,3],
'min_samples_split' : [2,3]
}
import pandas as pd
# param_grid의 하이퍼 파라미터를 3개의 train, test set fold로 나누어 테스트 수행 설정
### refit=True가 default임. True이면 가장 좋은 파라미터 설정으로 재학습시킴
grid_dtc = GridSearchCV(dtc, params, cv=3)
# 붓꽃 학습 데이터로 param_grid의 하이퍼 파라미터를 순차적으로 학습/평가
grid_dtc.fit(X_train, y_train)
# GridSearchCV 결과를 추출해 DataFrame으로 변환
scores_df = pd.DataFrame(grid_dtc.cv_results_)
scores_df[['params', 'mean_test_score','rank_test_score',
'split0_test_score', 'split1_test_score', 'split2_test_score']]
감사합니다~