-
[Machine Learning] 교차검증 - Cross Validation, RandomizedSearchCV, GridSearchCVData Science/Machine Learning & Deep Learning 2021. 2. 21. 18:43
데이터를 훈련 데이터(train), 검증 데이터(val), 테스트 데이터(test)로 나누어 학습을 진행하는 방법은 Hold-out Validation(Hold-out 검증)이라고 합니다. 이 방법에는 단점이 있는데 데이터의 사이즈가 충분히 크지 않을 경우 학습이 충분히 이루어지지 못할 수 있다는 것입니다. 이와 함께 검증 데이터도 충분하지 않아서 예측 성능 또한 제대로 확인할 수 없게 됩니다. 이처럼 데이터가 충분하지 않은 상황에서도 훈련과 검증에 대한 문제를 해결할 수 있는 방법이 교차검증(Crosss Validation)입니다.
교차검증을 위해서 데이터를 k개로 나누게 되는데 k 등분한 데이터 중 k-1개의 데이터를 학습에 이용하고 나머지 데이터로 검증하는 과정을 k번 반복하게 됩니다. 이를 k-fold cross-validation(CV)이라고 합니다. default인 k=5로 예를 들어보면, 5-fold cross validation이라고 하며, 데이터를 5개로 나누어 4개의 데이터(4/5)를 학습에 이용하고 나머지 1개의 데이터(1/5)로 검증을 하는 과정을 총 5번 진행하게 됩니다.
hold-out 검증 방법이 아닌 교차검증 방법을 사용할 것이므로
train데이터를 train과 val로 나누지 않고 훈련 데이터와 테스트 데이터의 특성과 타겟을 분리하겠습니다.
# 훈련/테스트 데이터를 특성과 타겟으로 분리 target = '' features = train.drop(columns=[target]).columns X_train = train[features] y_train = train[target] X_test = test[features]
ordinal encoder와 simple imputer를 사용하는 랜덤포레스트모델을 만들어 3-fold cross validation을 적용해보겠습니다.
from sklearn.pipeline import make_pipeline from category_encoders import OrdinalEncoder from sklearn.impute import SimpleImputer from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score pipe = make_pipeline( OrdinalEncoder(), SimpleImputer(), RandomForestClassifier(random_state=2) ) k = 3 scores = cross_val_score(pipe, X_train, y_train, cv=k, scoring='f1') scores
위에서 만든 모델은 하이퍼파라미터를 조정하지 않은 모델입니다.
하이퍼파라미터는 모델 훈련 중에 학습이 되지 않는 파라미터로, 직접 지정해주어야 합니다.
scikit-learn의 RandomSearchCV는 최적의 하이퍼파라미터를 찾을 수 있는 툴입니다.
RandomizedSearchCV는 검증하고 싶은 하이퍼파라미터의 범위를 지정해주면 그 조합들을 검증해 최적의 하이퍼파라미터를 찾아줍니다.
최적의 하이퍼파라미터는 과소적합과 과적합 사이 학습이 최적화된 지점으로 이상적인 모델이 될 수 있도록 하는 지점입니다.
# RandomizedSearchCV from sklearn.pipeline import make_pipeline from category_encoders import OrdinalEncoder from sklearn.impute import SimpleImputer from sklearn.ensemble import RandomForestClassifier from scipy.stats import randint, uniform from sklearn.model_selection import RandomizedSearchCV np.seterr(divide='ignore', invalid='ignore') # warning 제거 pipe = make_pipeline( OrdinalEncoder(), SimpleImputer(), RandomForestClassifier(random_state=2) ) # 하이퍼파라미터 범위 지정 dists = { 'simpleimputer__strategy': ['mean', 'median'], 'randomforestclassifier__n_estimators': randint(5, 500), 'randomforestclassifier__max_depth': [5, 10, 15, 20, None], 'randomforestclassifier__max_features': uniform(0, 1) } clf = RandomizedSearchCV( pipe, param_distributions=dists, n_iter=50, cv=3, scoring='f1', verbose=1, n_jobs=-1 ) clf.fit(X_train, y_train)
n_iter = 50 * cv = 3 으로 150번 검증을 수행하게 됩니다. 범위를 크게 지정하면 아주 많은 시간이 소요될 수 있습니다.
다음과 같이 RandomizedSearchCV로 찾은 최적의 하이퍼파라미터의 조합은 무엇인지,
최적의 하이퍼파라미터를 적용한 모델의 성능은 어떻게 되는지를 확인해볼 수 있습니다.
print('최적 하이퍼파라미터: ', clf.best_params_) print('F1: ', clf.best_score_)
마지막으로, 만들어진 모델에서 가장 좋은 성능을 내는 하이퍼파라미터로 튜닝하여 테스트 데이터로 예측을 해보았습니다.
pipe = clf.best_estimator_ # 하이퍼파라미터 적용 y_pred = pipe.predict(X_test)
RandomizedSearchCV외에 scikit-learn에는 최적의 하이퍼파라미터를 찾아주는 GridSearchCV가 있습니다.
GridSearchCV는 범위를 지정해주는 RandomizedSearchCV에서 하이퍼파라미터의 범위를 지정해주었던 것과는 달리,
검증하고 싶은 하이퍼파라미터의 수치들을 직접 지정해주어야합니다.
from xgboost import XGBClassifier from sklearn.model_selection import GridSearchCV # max_depth 수치 지정 dists = {'max_depth':range(2,10,2)} clf = GridSearchCV( estimator = XGBClassifier(n_estimators=100, max_depth=6, learning_rate=0.2, scale_pos_weight=ratio, # imbalance 데이터이므로 비율 적용 n_jobs=-1 ), param_grid=dists, cv=3, scoring='accuracy', verbose=1, n_jobs=-1 ) clf.fit(X_train, y_train); model = clf.best_estimator_ # 최적의 하이퍼파라미터 적용
'Data Science > Machine Learning & Deep Learning' 카테고리의 다른 글
[Deep Learning] 인공신경망( Artificial Neural Networks )과 퍼셉트론( Perceptron ) (0) 2021.04.06 [Machine Learning] 모델 해석 - Feature Importance, Permutation Importance, PDP, SHAP (0) 2021.03.03 [Machine Learning] RandomForest 랜덤 포레스트 & Threshold, ROC Curve, AUC (0) 2021.02.20 [Machine Learning] Logistic Regression 로지스틱회귀 (0) 2021.02.13 [Machine Learning] Linear Regression - 다중선형회귀 (0) 2021.02.07