Search

교차검증

K-겹 교차 검증(K-Fold Cross - Validation)

다양한 유형의 교차 검증 방법이 있지만, 가장 일반적인 방법은 k - 겹 교차 검증이다.
교차검증의 개수 k는 일반적으로 5 또는 10으로 설정한다.

사이킷런 KFold

from sklearn.model_selection import KFold from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score import numpy as np # iris 데이터셋 로드 iris = load_iris() X, y = iris.data, iris.target # KFold 분할기 인스턴스 생성 (5-겹 교차 검증) kf = KFold(n_splits=5, shuffle=True, random_state=42) # 정확도 점수를 저장할 리스트 accuracy_scores = [] # KFold로 데이터를 분할 for train_index, test_index in kf.split(X): # 분할된 훈련 및 테스트 데이터 생성 X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] # 모델 생성 및 훈련 model = RandomForestClassifier(random_state=42) model.fit(X_train, y_train) # 예측 및 정확도 계산 predictions = model.predict(X_test) accuracy = accuracy_score(y_test, predictions) # 정확도 점수를 리스트에 추가 accuracy_scores.append(accuracy) # 각 폴드에서의 정확도 출력 print("각 폴드에서의 정확도:", accuracy_scores) # 평균 정확도 계산 및 출력 print("평균 정확도:", np.mean(accuracy_scores))
Python
복사
각 폴드에서의 정확도: [1.0, 0.9666666666666667, 0.9333333333333333, 0.9333333333333333, 0.9666666666666667] 평균 정확도: 0.9600000000000002

사이킷런 cross_val_score

cv 에 할당한 개수만큼 교차검증을 수행하고, 성능을 평가해 cv에 할당한 개수만큼의 점수를 반환한다.
매개변수
from sklearn.moedel_selection import cross_val_score # 모델 초기화 model = RandomForestClassifier() # 회귀 문제 scores = cross_val_score(model, X, y, scoring='neg_mean_squared_error',cv=10) # 교차검증 10개 모델_rmse_scores = np.sqrt(-scores) print('평균 점수:', 모델_rmse_scores.mean())
Python
복사
※ 참고 ※
scoring 매개변수에서는 값이 클수록 좋은 결과라고 판단한다. 하지만 예를 들어 MSE 지표같은 경우에는 값이 작을수록 좋은 것이기 때문에 그대로 사용하면 잘못된 결과를 가져올 것이다. 따라서 이럴때는 neg_mean_squared_error 를 사용해서 scoring 매개변수의 정의에 맞게 사용한 다음 추후 실제 점수값을 확인할 때만 다시 ‘-’ 를 붙여주면 된다.
cross_val_predict() 함수는 cross_val_score() 과 마찬가지로 k겹 교차 검증을 수행하지만 평가 점수를 반환하는 것이 아니라 각 테스트 폴드에서 얻은 예측값을 반환한다.
적절한 임곗값 정하기
from sklearn.model_selection import cross_val_predict # 훈련 세트에 있는 모든 샘플의 점수를 구하기 y_scores = cross_val_predict(estimator, X_train, y_train, cv=k, method='decision_function')
Python
복사
cv 값을 따로 지정해주지 않거나(default=5) 정수값으로 지정해줄 경우, estimator가 분류기이고 이진분류 또는 다중분류일 경우 알아서 StratifiedKFold 교차검증으로 진행한다. 하지만 그 외에는 KFold 교차검증으로 진행한다.
# precision_recall_curve() 로 모든 임곗값에 대해 정밀도와 재현율 계산하기 from sklearn.metrics import precision_recall_curve precisions, recalls, thresholds = precision_recall_curve(y_train, y_scores)
Python
복사
precision_recall_curve() 는 이진분류에서만 사용 가능하다.
The last precision and recall values are 1. and 0. respectively and do not have a corresponding threshold. This ensures that the graph starts on the y axis.
# 임곗값의 함수로 정밀도와 재현율 그리기 def plot_precision_recall_vs_threshold(precisions,recalls,thresholds): plt.plot(thresholds,precisions[:-1], 'b--', label='정밀도') plt.plot(thresholds,precisions[:-1], 'g-', label='재현율') plt.xlabel('임곗값') plt.legend('best') plt.grid(True) plot_precision_recall_vs_threshold(precisions, recalss, thresholds) plt.show()
Python
복사
# 재현율에 대한 정밀도 곡선을 그리기 -> 트레이드 오프 선택하기 # plot_precision_recall_curve() : 이진분류만 가능 from sklearn.metrics import plot_precision_recall_curve plot_precision_recall_curve(모델, X_train, y_train, response_method='auto')
Python
복사
재현율 정밀도 곡선을 통해 그래프가 급격히 하강하는 직전을 트레이드오프로 선택하는 것이 좋다.
하지만 목표에 따라 트레이드오프를 선택하는 기준은 달라지는데, 예를 들어 정밀도 90% 를 달성하고 싶다고 하면 아래와 같이 임곗값을 설정해주고
# np.argmax() 는 최댓값의 첫 번째 인덱스를 반환해준다. threshold_90_precision = thresholds[np.argmax(precisions >= 0.9)] # 정밀도 0.9 이상이 되는 최댓값(1=True)의 가장 첫번째 인덱스
Python
복사
훈련세트의 예측값은 다음과 같이 계산하게된다.
y_train_pred_90 = (y_scores >= threshold_90_precision)
Python
복사
해당 임곗값에서의 정밀도와 재현율을 확인해보면
precision_score(y_train, y_train_pred_90) # 임의의 임곗값에서의 정밀도 recall_score(y_train, y_train_pred_90) # 임의의 임곗값에서의 재현율
Python
복사
가끔, 교차 검증 과정을 더 많이 제어해야 할 필요가 있다. 이때는 교차 검증 기능을 직접 구현하는 것이 나은데, 사이킷런의 cross_val_score와 같은 작업을 수행하고 동일한 결과를 출력해준다.
StratifiedKFold 는 클래스별 비율이 유지되도록 폴드를 만들기 위해 계층적 샘플링을 해준다.
from sklearn.model_selection import StratifiedKFold from sklearn.base import clone # 모델을 복제하기 위해서 사용하는 메소드 skfolds = StratifiedKFold(n_splits=3, random_state=0, shuffle=True) for train_index, test_index in skfolds.split(X_train,y_train): clone_model = clone(임의의model) X_train_folds = X_train[train_index] y_train_folds = y_train[train_index] X_test_folds = X_test[test_index] y_test_folds = y_test[test_index] clone_model.fit(X_train_folds, y_train_folds) y_pred = clone_model.predict(X_test_folds) n_correct = sum(y_pred == y_test_folds) print(n_correct / len(y_pred)) # 각 폴드에서의 예측 정확도를 출력
Python
복사
매 반복마다 분류기 객체를 복제해서 훈련 폴드로 훈련시키고 테스트 폴드로 예측을 만든다. 올바른 예측 수를 세어 정확한 예측 비율을 출력한다.