ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [분석/통계] 교차검증
    Study/Statistics 2019. 5. 29. 14:22
    훈련 데이터와 테스트 데이터를 나누는 행위를 여러번 해서 데이터의 불균형을 없에 일반화 성능을 검증하고 높이는 방법

     

    모델을 만든 후 잘 만든 모델인지 확인하기 위해 데이터셋을 훈련/테스트로 나눠 모델을 평가하곤 하는데

    이 때 한 번만 나누게 되면 일반화가 안 될 가능성이 있음

     

    예를 들어 훈련 80%, 테스트 20% 이렇게 한번만 나누어 훈련데이터에는 데이터가 1만 들어가는데, 테스트 데이터에는 5~9까지의 데이터가 들어가게 되는 경우 올바를 분석을 할 수 없게 됨

     

    이를 극복하여 일반화 성능을 높이는 방안으로 교차검증이 있음

     

    교차검증은 훈련/테스트를 여러번 반복해서 나누고, 여러번 학습하여 데이터의 불균형을 없에 일반화 성능을 높이는 샘플링 방법

    일반화 성능을 측정함

    K-Fold

    가장 많이 사용하는 교차 검증 방법

     

    몇 번 반복할지 몰라서 K!

    데이터를 k개수만큼 나눠서 Fold!

     

    알고리즘 - 5-Fold 교차검증을 하는 경우

    5-겹 교차 검증에서의 데이터 분할

    1. k개수만큼 데이터를 나눔

    2. 첫 번째 모델은 폴드1을 사용해 정확도 평가 => 분할2~5 = 학습, 분할1 = 테스트 데이터로 사용

    3. 두 번째 모델은 폴드2을 사용해 정확도 평가 => 분할1,3~5 = 학습, 분할2 = 테스트 데이터로 사용

    4. 3~5번째 모델도 동일하게 정확도 측정

     

    장점

    일반화가 잘됨

    모델이 훈련 데이터에 얼마나 민감한지 알 수 있음

    훈련/테스트를 한번만 나눴을 때보다 데이터를 효과적으로 사용하여 더 정확한 모델을 만듬

     

    단점

    연산비용이 늘어남

     

    목적

    데이터셋에 학습된 알고리즘이 얼마나 잘 일반화될지 평가

     

    분류의 경우 계층별 K-Fold 교차검증 사용

    why? 000000000000001111111111111111111222222222222222222이렇게 데이터가 순서대로 있는 경우 그냥 자르면 하나는 0만 하나는1만 하나는2만 들어가기 때문에 

     

    python에서 구현 방법

    skit-learn사용

    # iris데이터를 이용하여 logisticRegression
    
    from sklearn.model_selection import cross_val_score
    from sklearn.datasets import load_iris
    from sklearn.linear_model import LogisticRegression
    
    iris = load_iris()
    logreg = LogisticRegression()
    
    scores = cross_val_score(logreg, iris.data, iris.target,cv=5)
    ## cross_val_score(모델, 훈련데이터, 테스트데이터, cv=폴드하고싶은 횟수)
    
    print("교차 검증 점수:", scores) #5개각각 점수 알고 싶을 때
    
    print("교차 검증 평균 점수: {:.2f}".format(scores.mean())) # 평균 점수
    
    
    # 교차검증 상세옵션 - 데이터를 섞어 샘플 순서를 뒤죽박죽 분류의경우 등,,,
    
    kfold = KFold(n_splits=3, shuffle=True, random_state=0)
    ## kFold(n_splits=폴드하고싶은 횟수, shuffle=섞을지 말지, random_state=값을 넣어주면 똑같이 섞어줌, 안넣으면 실행할 때마다 폴드가 바뀌어 매번 결과가 달라짐)
    
    print("교차 검증 점수:\n",
        cross_val_score(logreg, iris.data, iris.target, cv=kfold))

     

    LOOCV(Leave-one-out-cross-validation)

    폴드 하나에 샘플 하나만 들어있는 k-fold

    각 반복에서 하나의 데이터 포인트를 선택해 테스트 세트로 사용

     

    단점

    큰 데이터셋에서는 시간이 매우 오래걸림

     

    이용할 때?

    작은 데이터셋에서 더 좋은 결과를 만들기도 함

     

    python에서 구현 방법

    skit-learn사용

    from sklearn.model_selection import LeaveOneOut
    loo = LeaveOneOut()
    scores = cross_val_score(logreg, iris.data, iris.target, cv=loo)
    print("교차 검증 분할 횟수: ", len(scores))
    print("평균 정확도: {:.2f}".format(scores.mean()))

     

    임의 분할 교차 검증

    train_size만큼 훈련 세트를 만들고, test_size만큼(훈련 세트와 중첩되지 않은)의 포인트로 테스트 세트를 만들도록 분할

    분할은 n_splits횟수만큼 반복

     

    예) 샘플이 10개인 데이터셋을 5개 포인트의 훈련세트로, 2개 포인트의 테스트 세트로, 4번 반복하여 나눔

    python에서 구현 방법

    skit-learn사용

    from sklearn.model_selection import ShuffleSplit
    
    shuffle_split = ShuffleSplit(test_size=.5, train_size=.5, n_splits=10)
    # ShuffleSplit(test_size=테스트세트 비율, train_size=훈련세트 비율, n_splits=반복횟수)
    
    scores = cross_val_score(logreg, iris.data, iris.target, cv=shuffle_split)
    
    print("교차 검증 점수:\n", scores)

     

    그룹별 교차 검증

    데이터 안에 매우 연관된 그룹이 있을 때 사용

     

    얼굴인식을 할 때 테스트 데이터에는 훈련 데이터에는 없는 새로운 사람의 얼굴이 들어가야하는 경우 사용

     

    그룹별로 돌아가면서 훈련/테스트 데이터가됨!

     

    python에서 구현 방법

    skit-learn사용

    from sklearn.model_selection import GroupKFold
    # 인위적 데이터셋 생성
    X, y = make_blobs(n_samples=12, random_state=0)
    
    # 처음 세 개의 샘플은 같은 그룹에 속하고
    # 다음은 네 개의 샘플이 같습니다.
    groups = [0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3]  # 어느그룹에 속하는지 알려줘야함
    
    scores = cross_val_score(logreg, X, y, groups, cv=GroupKFold(n_splits=3))
    #  groups, cv=GroupKFold(n_splits=3)) # 어느그룹에 속하는지 알려주고, cv=그룹폴드쓴다고알려주고(3개그룹이라고)
    
    print("교차 검증 점수:\n", scores)

     

    댓글

Designed by Tistory.