ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Machine Learning] 교차검증 - Cross Validation, RandomizedSearchCV, GridSearchCV
    Data 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_  # 최적의 하이퍼파라미터 적용

     

     

     

     

Designed by Tistory.