4 분 소요

K-Fold CV, LOOCV, Stratified K-Fold CV


안녕하세요. 데이터 사이언티스트를 위한 정보를 공유하고 있습니다.

M1 Macbook Air를 사용하고 있으며, 블로그의 모든 글은 Mac을 기준으로 작성된 점 참고해주세요.


교차 검증(Cross Validaion)이란?

모델이 학습 데이터를 학습하고, 테스트 데이터로 모델의 성능을 검증한다고 이야기하였습니다.

그런데 학습 데이터와 테스트 데이터가 고정되어 있을 때 문제점이 있습니다.

이러한 경우에는 고정된 테스트 데이터에서만 최적의 성능을 보이도록 편향된 모델이 만들어질 수 있습니다.

이전 글에서 했던 비유를 이어서 해보자면, 특정 년도 수능만 잘보는 학생이 될 수도 있다는 것입니다.

이러한 문제점을 개선하기 위해 교차 검증(cross validaion)을 이용합니다.

테스트 데이터 외에 별도로 검증 데이터를 생성하는 건데요.

학습 데이터를 다시 학습 데이터와 검증 데이터로 나누고, 모델이 학습과 검증을 동시에 진행하는 것입니다.

이때 학습 데이터와 검증 데이터의 구성을 바꿔가면서 여러번 학습을 진행하고 성능을 평가합니다.

이렇게 여러번 반복하여 학습하고 검증된 모델은 보다 일반화된 성능을 확인할 수 있게 되고,

앞서 말씀드린 문제를 보정하게 됩니다.

이해를 돕기 위해 다시 비유를 통해 설명드리자면 검증 데이터 세트는 모의고사라고 생각하면 좋습니다.

” 학생(모델)이 문제집(학습 데이터 세트)을 학습하면서

모의고사(검증 데이터 세트)로 현재 점수(성능)를 확인하고,

점수를 올리기 위해 문제점을 개선(하이퍼 파라미터 튜닝, 전처리 점검 등)한다.

마지막으로 수능 시험(테스트 데이터 세트)에서 실력을 평가한다. “

이런 흐름으로 모델링에 대해 기억하시면 좋을 것 같습니다.


교차 검증에는 여러 종류가 있습니다.

  1. K-Fold Cross Validation
  2. LOOCV(Leave One Out Cross Validaion)
  3. Stratified K-Fold Cross Validaion

1. K-Fold Cross Validation

K-Fold Cross Validation 방식을 간단히 설명해 보겠습니다.

데이터 세트를 K개의 폴드(fold)로 나누고,

한 개의 폴드는 검증 데이터 세트, 나머지 폴드는 학습 데이터 세트로 지정하여 모델의 학습과 검증을 진행합니다.

그리고 각 폴드가 번갈아가며 한 번씩 검증 데이터 세트로 지정되어 위 과정을 총 K번 교차로 반복합니다.

이때 K번 도출된 각각의 검증 결과를 평균한 값이 최종 평가 결과로 반환되는데

이 방식이 바로 K-Fold Cross Validation이 되겠습니다.

그럼 별도의 테스트 데이터는 없느냐?

K-Fold Cross Validation의 결과로 도출된 값을 최종 평가 결과라고 말씀드려 혼동될 수 있겠는데요.

물론 교차 검증의 결과가 평가 지표로 활용되기도 합니다만,

교차 검증을 진행한 모델 역시 검증 데이터에 최적화된 모델입니다.

모델의 가장 이상적인 하이퍼 파라미터를 찾기 위해서

최종 테스트를 하기 전에 성능을 여러 번 확인하며 하이퍼 파라미터를 개선해 가는 것이 교차 검증의 의의가 되겠습니다.

하이퍼 파라미터에 대해서는 추후에 설명드리도록 하겠습니다.

자, 그렇다면 실제로 별도의 테스트 데이터는 존재해야 합니다.

모델이 출시되기 전에 최종적인 모델의 성능을 평가하기 위해서 학습 및 검증 단계에서 경험하지 못한 데이터로 평가가 이루어져야 하기 때문이죠.


K-Fold Cross validation은 학습이 여러 번 이루어지는 관계로 반복 횟수에 따라 모델의 학습 및 검증 시간이 많이 소요되긴 하지만,

앞서 말씀드린 특정 데이터에 대한 편향, 즉 과적합(overfitting) 문제를 해결하고,

데이터의 규모가 작을 때 과소적합(underfitting)을 방지하는 장점이 있기 때문에

일반화된 모델을 만들 수 있으며 보편적으로 많이 사용되는 방식입니다.


예시로 폴드를 5개로 나누었을 때의 K-Fold Cross Validation을 도식화해 보면 다음과 같습니다.

교차검증


2. LOOCV(Leave One Out Cross Validation)

LOOCV는 K-Fold Cross Validation과 같은 방식을 취하는데 폴드를 데이터의 개수만큼 지정하는 방식을 의미합니다.

예를 들어 붓꽃 데이터의 데이터 샘플 수가 150개라면 각 데이터가 하나의 폴드가 되어

총 150번의 교차 검증을 진행하는 것입니다.

검증 데이터 세트로 지정된 한 개의 폴드는 단 하나의 데이터로 구성되어 있게 됩니다.

즉 단 한 개의 데이터로 학습된 모델의 성능을 검증하게 되는 것이고,

그렇기에 이로부터 나온 결과를 신뢰하긴 어렵습니다.

보통 학습 데이터의 양이 극심히 적을 때 사용되는 방식입니다.


3. Stratified K-Fold Cross Validation

Stratified K-Fold Cross Validation 방식은 각 레이블 별로 데이터 분포가 불균형할(imbalanced) 때 사용되는 방식입니다.

예를 들어 강아지 사진은 200개 있는데, 고양이 사진이 800개로 압도적으로 많은 경우를 데이터의 분포가 불균형하다고 표현합니다.

이렇게 데이터가 불균형한 경우에 일반적인 K-Fold Cross Validation이 적용되면

무작위로 데이터가 폴드에 배정되어 폴드마다 분포도가 다르게 되는데

K번 학습과 검증이 반복될 때마다 도출되는 각각의 결과의 편차가 크게 될 것입니다.

그렇게 되면 일반화된 모델을 얻는 데 방해가 되겠죠.

이를 해결하기 위해 Stratified K_Fold Cross Validation을 사용하게 되면

폴드가 나눠질 때 각 폴드에서의 데이터 분포도가 전체 데이터의 레이블 별 데이터 분포와 동일하게 적용됩니다.

위의 예시에서 전체 데이터에서 강아지 사진과 고양이 사진의 비율은 1:4인데

폴드를 나눌 때 각각의 폴드에서도 강아지 사진과 고양이 사진의 비율이 1:4로 배정되게 되는 것입니다.

이 방식은 분류에서만 적용되고 회귀에서는 사용이 불가합니다.

분류에서는 타겟값이 이산적인 레이블로 나타나는 반면,

회귀에서는 타겟값이 연속적인 숫자값으로 나타나기 때문에 데이터의 분포도가 의미가 없기 때문입니다.


cross_val_score()

그럼 교차 검증이 실제로 어떻게 쓰이는지 예시를 보겠습니다.

사실 model_selection 모듈에는 KFold()와 StratifiedKFold() 메소드가 있습니다.

교차 검증을 위한 메소드이긴 하지만 코드 작성 시 복잡해지는 경향이 있습니다.

그래서 저는 간편하게 한 줄의 코드로 교차 검증을 할 수 있게 도와주는 cross_val_score()를 사용할 것입니다.

이번에도 역시 붓꽃 데이터를 사용하겠습니다.

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris

import numpy as np

iris_data = load_iris()
# 붓꽃 데이터 가져오기
dt = DecisionTreeClassifier(random_state = 1)
# Decision Tree 분류기를 dt라는 이름으로 생성

scores = cross_val_score(dt, iris_data.data, iris_data.target, scoring = "accuracy", cv = 5)
# 5개의 폴드로 나누어 교차 검증
# 결과는 교차 검증별 accuracy로 반환

print(f"교차 검증별 정확도: {np.round(scores, 4)}")
print(f"평균 검증 정확도: {np.round(np.mean(scores), 4)}")
교차 검증별 정확도: [0.9667 0.9667 0.9    1.     1.    ]
평균 검증 정확도: 0.9667

cross_val_score()의 주요 파라미터를 살펴보겠습니다.

첫 번째 파라미터에는 estimator, 즉 분류 모델 또는 회귀 모델이 입력되고,

두 번째 파라미터에는 피처 데이터 세트, 세 번째 파라미터에는 레이블 데이터 세트가 입력되어야 합니다.

scoring: 예측 성능 평가 지표를 결정합니다.

cv: 폴드의 수를 결정합니다.

cross_val_score()를 호출하면 자체적으로 학습(fit), 예측(predict), 평가를 진행하여

각 교차 검증별 정확도가 배열의 형태로 반환됩니다.

또한 분류 모델이 입력되면 자동으로 Stratified K-Fold Cross Validation이 적용되고,

회귀 모델이 입력되면 K-Fold Cross Validation이 적용됩니다.

cross_val_score() 외에도 cross_validate()도 있는데

이는 여러 개의 성능 평가 지표를 반환할 수 있다는 장점이 있습니다.


읽어주셔서 감사합니다.

정보 공유의 목적으로 만들어진 블로그입니다.

미흡한 점은 언제든 댓글로 지적해주시면 감사하겠습니다.


업데이트:

댓글남기기