ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 교차 검증(Cross validation)
    AI 2020. 8. 21. 22:40

     

     

    만약 모델을 학습시키기 위해 데이터를 train set와 test set로 나눈 후 파라미터를 수정하면서 계속 학습을 한다면 train set가 고정된 상태에서 계속 반복되면서 모델이 과적합(overfitting) 될 수 있다.

    이를 해결하고자 하는 것이 바로 교차 검증(cross validation)이다.

     

     

    교차 검증

    • 일반화 성능 향상을 위해 훈련 세트와 테스트 세트로 한 번 나누는 것보다 더 안정적이고 뛰어난 평가 방법

    • 데이터 편중을 막기 위함

    • 별도의 여러 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행

    • 연산 비용이 늘어나는 단점이 있음 (k배 더 느림)

     

     

    from sklearn.model_selection import cross_val_score

     

    • Parameter and Return
    cross_val_score(estimator, X, y=None, *, groups=None, scoring=None, cv=None, n_jobs=None, verbose=0, fit_params=None, pre_dispatch='2*n_jobs', error_score=nan)
    
    
    '''
    Parameter
    
    - estimator : 평가하려는 모델
    - X : 훈련 데이터
    - y : 타깃 레이블
    - cv : 교차 검증 분할 수(k)
    
    Return
    
    - 교차 검증 결과 정확도 점수의 배열
    '''

     

     

    Iris 데이터로 사용해보기

     

    from sklearn.model_selection import cross_val_score
    from sklearn.datasets import load_iris
    from sklearn.linear_model import LogisticRegression
    from sklearn.tree import DecisionTreeClassifier
    
    # iris 데이터 불러오기
    iris = load_iris()
    
    # model
    model_lr = LogisticRegression()
    model_dt = DecisionTreeClassifier(random_state=42)
    
    scores = cross_val_score(model_lr, iris.data, iris.target)
    print("교차 검증 점수: ", scores)
    
    scores = cross_val_score(model_dt, iris.data, iris.target)
    print("교차 검증 점수: ", scores)
    교차 검증 점수:  [0.96666667 1.         0.93333333 0.96666667 1.        ]
    교차 검증 점수:  [0.96666667 0.96666667 0.9        0.93333333 1.        ]

     

    # 폴드의 수 조절하기(cv)
    scores = cross_val_score(model_dt, iris.data, iris.target, cv=3)
    print("교차 검증 점수: ", scores)
    교차 검증 점수:  [0.98 0.94 0.96]

     

    # 보통 교차 검증의 정확도를 간단하게 나타내기 위해 평균을 사용한다.
    print("교차 검증 점수: ", scores.mean())
    교차 검증 점수:  0.96

     

     

    그런데

    • 데이터셋을 나열 순서대로 k개의 폴드를 나누는 것은 항상 좋지는 않다.

     

    iris = load_iris()
    
    print("Iris 레이블:\n{}".format(iris.target))
    Iris 레이블:
      [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
       0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
       1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
       2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
       2 2]

     

    • 결과에서 볼 수 있듯이 1/3은 클래스 0, 1/3은 클래스 1, 1/3은 클래스 2이다.
    • 이 데이터에 3-겹 교차 검증을 적용한다면 첫 번째 폴드는 클래스 0만 가지고 있으므로 정확도는 0이 된다.
    • 두 번째, 세 번째도 같은 방법으로 정확도는 0이 된다.

     

    K-fold

    from sklearn.model_selection import KFold
    
    kfold = KFold(n_splits=3)
    scores = cross_val_score(model_dt, iris.data, iris.target, cv=kfold)
    print("교차 검증 점수: ", scores)
    교차 검증 점수:  [0. 0. 0.]

     

    • 해결 방법으로는 shuffle=True 를 사용하거나 StratifiedKFold 를 사용하면 된다.

     

    # 데이터를 분할하기 전에 섞어주면 결과가 향상된다.
    kfold = KFold(n_splits=3, shuffle=True, random_state=0)
    scores = cross_val_score(model_dt, iris.data, iris.target, cv=kfold)
    print("교차 검증 점수: ", scores)
    교차 검증 점수:  [0.96 0.96 0.96]

     

    계층별 k-fold 교차 검증

    from sklearn.model_selection import StratifiedKFold
    
    kfold = StratifiedKFold(n_splits=3)
    scores = cross_val_score(model_dt, iris.data, iris.target, cv=kfold)
    print("교차 검증 점수: ", scores)
    교차 검증 점수:  [0.98 0.94 0.96]

     

    • StratifiedKFold는 데이터가 편향되어 있는 경우에 주로 사용된다.

     

     

    참고로

    • 회귀에서는 k-fold 교차 검증을 사용하고,
    • 분류에서는 계층별 k-fold 교차 검증을 주로 사용한다.

     

    또한

     

    • cross_val_score 함수에는 KFold의 매개변수를 제어할 수가 없으므로, 따로 KFold 객체를 만들고 매개변수를 조정한 다음에 cross_val_score의 cv 매개변수에 넣어야 한다.



     

    이외에도 다양한 교차 검증 방법들이 있다.

     

    임의 분할 교차 검증 (shuffle-split cross-validation)

    • 반복 횟수를 훈련 세트나 테스트 세트의 크기와 독립적으로 조절해야 할 때 유용
    from sklearn.model_selection import ShuffleSplit

     

    그룹별 교차 검증 (groups cross-validation)

    • 데이터 안에 매우 연관된 그룹이 있을 때
    from sklearn.model_selection import GroupKFold

     

    반복 교차 검증

    데이터셋의 크기가 크지 않을 경우 안정된 검증 점수를 얻기 위해 교차 검증을 반복하여 여러 번 수행

    • RepeatedKFold : 회귀에 사용
    • RepeatedStratifiedKFold : 분류에 사용
    from sklearn.model_selection import RepeatedStratifiedKFold

     

    등등...




     

     


    Reference

     

     

     

     

     

    댓글

© 2019 All rights reserved.