ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [사이킷런] 교차 검증 (KFold, Statified KFold)
    머신러닝 & 딥러닝 2021. 9. 28. 14:54

    교차 검증

    • 학습 데이터 세트 : 학습 데이터를 분할하여 학습 데이터와 검증 데이터로 나눔.
    • 테스트 데이트 세트 : 모든 학습/검증 과정이 완료된 후 최종적으로 성능을 평가하기 위함.
    • 교차 검증은 수능을 보기 전, 모의 고사를 여러차례 보는 개념이다.
    • 데이터 편증을 막기 위해 여러 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행한다.
    • 대부분의 ML 모델의 성능 평가는 교차 검증 기반으로 1차 평가를 한 뒤, 테스트 데이터 세트를 적용해 평가는 프로세스다.

     

    K-Fold 교차 검증

    • 가장 보편적인 교차 검증 기법이다.
    • K개의 데이터 폴드 세트를 만든 뒤, k번 만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행한다.
    • k=5 일 경우, 총 5개의 폴드 세트에 5번의 학습과 검증 평가 반복 수행
    • 교차 검증 최종 평가 = 평균(평가 1, 2, 3, 4, 5)
    • 일반 k 폴드
    • Stratified K 폴드 : 불균형한 분포드를 가진 레이블 데이터를 위한 방식.
      • 학습 데이터와 검증 데이터 세트가 가지는 레이블 분포도가 유사하도록 검증 데이터 추출
    • KFold 클래스를 이용한 교차 검증 방법
      1. 폴드 세트 설정
      2. for 루프에서 반복적으로 학습/검정 데이터 추출 및 학습과 예측 수행
      3. 폴드 세트별로 예측 성능을 평균화하여 최종 성능 평가

     

    K-Fold 예시

    from sklearn.datasets import load_iris 
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.metrics import accuracy_score
    from sklearn.model_selection import KFold
    import numpy as np
    
    iris = load_iris()
    features = iris.data
    label = iris.target
    dt_clf = DecisionTreeClassifier(random_state=156)
    
    # 5개의 폴드 세트로 분리하는 KFold 객체 생성
    kfold = KFold(n_splits=5)
    cv_accuracy = [] # 폴드 세트별 정확도를 담을 리스트
    print('붓꽃 데이터 세트 크기: ', features.shape[0])
    
    n_iter = 0
    
    # 전체 붓꽃 데이터를 5개의 폴드 데이터 세트로 분리. 전체 데이터는 150개 이므로, 학습용 데이터는 120개, 검증 테스트 데이터 세트는 30개로 분류.
    for train_index, test_index in kfold.split(features):
        X_train, X_test = features[train_index], features[test_index]
        y_train, y_test = label[train_index], label[test_index]
        
        # 학습, 예측
        dt_clf.fit(X_train, y_train)
        pred = dt_clf.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)
        
        print('\n## 평균 검증 정확도: ', np.mean(cv_accuracy))

     

    결과

     

     

    Stratified K 폴드

    • 불균형한 분포도를 가진 레이블(결정 클래스) 데이터 집합을 위한 K 폴드 방식이다.
    • 불균형한 분포도를 가진 레이블이란 특정 레이블 값이 유독 많거나 적어서 한쪽으로 치우진 경우를 뜻한다.
    • K폴드가 레이블 데이터 집합이 원본 데이터 집합의 레이블 분포를 학습 및 테스트 세트에 제대로 분배하지 못하는 경우 해걸한다.
    • 원본 데이터의 레이블 분포를 먼저 고려한 뒤, 이 분포와 동일하게 학습과 검증 데이터 세트를 분배한다.
    • 분류(Classification)에서 교차검증을 할 때, Stratified K폴드로 분할되어야 한다.
    • 회귀(Regression)에서는 Stratified K폴드가 지원되지 않는다.

     

     

    Stratified K폴드 예시

    from sklearn.model_selection import StratifiedKFold
    
    dt_clf = DecisionTreeClassifier(random_state=156)
    
    skfold = StratifiedKFold(n_splits = 3)
    n_iter = 0
    cv_accuracy = []
    
    # skfold.split()의 경우 반드시 레이블 데이터 세트를 입력해야 한다.
    for train_index, test_index in skfold.split(features, label):
        # 학습용, 검증용 테스트 데이터 추출
        X_train, X_test = features[train_index], features[test_index]
        y_train, y_test = label[train_index], label[test_index]
        
        # 학습, 예측
        dt_clf.fit(X_train, y_train)
        pred = dt_clf.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)
    
    print('\n## 평균 검증 정확도: ', np.mean(cv_accuracy))

     

     

    cross_val_score()

    • cross_val_score() 함수로 폴드 세트 추출, 학습/예측, 평가를 한번에 수행 가능.
    • cross_val_score()의 파라마타
      • estimator: classifier 또는 regressor
      • X: 피처 데이터 세트
      • y: 레이블 데이터 세트
      • scoring: 예측 성능 평가 지표
      • cv: 교차 검증 폴드 수

     

    cross_val_score() 예시

    from sklearn.datasets import load_iris 
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.model_selection import cross_val_score, cross_validate
    
    iris_data = load_iris()
    dt_clf = DecisionTreeClassifier(random_state=156)
    
    data = iris_data.data
    label = iris_data.target
    
    scores = cross_val_score(dt_clf, data, label, scoring='accuracy', cv=3)
    print('교차 검증별 정확도: ', np.round(scores, 4))
    print('평균 검증 정확도: ', np.round(np.mean(scores), 4))

    교차 검증별 정확도: [0.98 0.94 0.98]

    평균 검증 정확도: 0.9667

     

    GridSearchCV

    • 교차 검증과 최적 하이퍼 파라미터 튜닝을 한번에 할 수 있다.
    • 머신러닝 알고리즘을 튜닝하기 위한 파라미터가 하이퍼 파라미터.
    • 촘촘하게 파라미터를 입력하면서 테스트 하는 방식이다.
    • 데이터 세트를 cross-validation을 위한 학습/테스트 세트로 자동으로 분할 한 뒤에 하이퍼 파라미터 그리드에 기술된 모든 파라미터를 순차적으로 적용하여 최적의 파라미터를 찾는다.
    • 파라미터
      • estimator: classifier, regressor, pipeline
      • param_grid: 딕셔너리로 주어진다.
      • scoring : 예측 성능을 측정할 평가 방법
      • cv: 학습 / 테스트 세트의 개수
      • refit: 디폴트가 true, true일 때 가장 최적의 파라미터를 찾은 뒤 하이퍼 파라미터로 재학습 시킨다.

     

    GridSearchCV 예시

    from sklearn.datasets import load_iris 
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.model_selection import GridSearchCV, train_test_split
    import pandas as pd
    
    iris_data = load_iris()
    X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, test_size = 0.2, random_state=121)
    
    dtree = DecisionTreeClassifier()
    
    # 파라미터는 딕셔너리 형태로 입력
    parameters = {'max_depth': [1, 2, 3], 'min_samples_split' : [2, 3] }
    
    # param_grid의 하이퍼 파라미터를 3개의 train, test set fold로 나누어서 테스트를 수행한다.
    grid_dtree = GridSearchCV(dtree, param_grid=parameters, cv=3, refit=True)
    
    # 붓꽃 학습 데이터로 param_grid의 하이퍼 파라미터를 순차적으로 학습 및 평가
    grid_dtree.fit(X_train, y_train)
    
    scores_df = pd.DataFrame(grid_dtree.cv_results_)
    scores_df[['params', 'mean_test_score', 'rank_test_score', 'split0_test_score', 'split1_test_score', 'split2_test_score']]

     

    댓글