본문 바로가기

데이터 사이언스 공부

00. cross_val_score가 사용하는 KFold 방식

cross_val_score는 교차 검증을 간편하게 만드는 사이킷 런의 API 함수이다.

 

일반적인 KFold는 단순히 데이터셋을 나눠주고, 나눠진 데이터셋의 인덱스를 리턴하는 함수에 지나지 않는다.

 

이를 활용하여 교차검증을 수행하고, 정확도를  확인하여 리스트 형태로 리턴하는 일련의 과정까지 cross_val_score 함수는 진행한다.

 

KFold가 가지고 있는 맹점 중의 하나는, k개로 데이터셋을 나누었을 때, 만약 데이터셋의 분포가 불균형한 상태라면 제대로 된 결과가 나오지 않을 수 있다.

 

이 때 활용하는 것이 StratifiedKFold 방식이다.

 

 

StratifiedKFold는 각 Fold가 전체 데이터셋의 클래스 비율을 반영하도록 나눈다.

 

따라서 각 폴드의 데이터셋은 비슷한 분포의 클래스를 가지게 된다. 타겟값이 일정하게 들어간다는 것이다.

 

1이 1000개, 0이 49000개인 데이터셋을 생각해보자.

 

10000개씩 5개의 Fold로 나누면, KFold 방식의 경우 1이 0개인 Fold가 생길 수 있다.

 

그렇게 되면 target 값이 0인 데이터만 가지고 학습을 진행하게 되므로, 모든 데이터가 0이라고 평가하게 된다.

 

하지만 StratifiedKFold는 대략 200개씩 1인 타겟값을 각각의 Fold마다 분배하므로 교차검증이 실패할 가능성을 조금 줄여줄 수 있다.

 


 

cross_val_score는 기본적으로 KFold 방식을 사용한다.

 

하지만 이 함수는 사용자가 다른 교차 검증 방법을 지정할 수도 있다.

 

cross_val_score와 교차 검증 전략

  • 기본적으로 cross_val_score는 KFold를 사용한다.
  • KFold의 경우, cv=KFold(n_splits=5)와 같은 형태로 교차 검증 전략을 지정할 수 있다.
  • 만약 불균형 데이터셋에서 성능을 좀 더 정확하게 평가하고 싶다면, 이때는 cv=StratifiedKFold(n_splits=5)로 지정한다.

기본 KFold 사용 (기본값)

from sklearn.model_selection import cross_val_score, KFold
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier() 
kf = KFold(n_splits=5) 
scores = cross_val_score(model, X, y, cv=kf) 
print(scores)

 

기본 StratifiedKFold 사용 (기본값)

from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier()
stratified_kf = StratifiedKFold(n_splits=5)
scores = cross_val_score(model, X, y, cv=stratified_kf)
 

 

 

하지만 StratifiedKFold가 기본적으로 사용되는 경우는 분류 문제에서 cross_val_score가 stratified 방식으로 동작하도록 자동화된 라이브러리의 동작에 따라 다를 수 있다.

 

우리는 위에서 StratifiedKFold와 KFold 모두 분류 문제에서 생각해보았다.

 

하지만 회귀 문제에서도 cross_val_score는 사용할 수 있고, 이 때 scoring 파라미터에 'r2'나 'mse'를 넣어주면 활용이 가능하다.

 

 

  • StratifiedKFold분류 문제에서 사용될 때에는 자동으로 StratifiedKFold가 사용되는 경우가 많다. 이는 Scikit-learn의 분류 모델에서 데이터의 클래스 불균형을 보다 잘 반영하기 위해 설계된 동작이다.
  • 회귀 문제에서는 기본적으로 KFold가 사용된다. 회귀 문제에서는 클래스 레이블 대신 연속적인 값을 예측하기 때문에, 클래스 비율을 유지할 필요가 없기 때문이다.

 

cross_val_score에서 회귀 방식을 사용하는 예시

from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LinearRegression
from sklearn.datasets import make_regression

# 회귀 데이터 생성
X, y = make_regression(n_samples=100, n_features=2, noise=0.1)

# 회귀 모델 정의
model = LinearRegression()

# 교차 검증을 통한 음의 평균 제곱 오차 평가
scores = cross_val_score(model, X, y, cv=5, scoring='neg_mean_squared_error')

print(f"음의 MSE: {scores}")
print(f"평균 음의 MSE: {scores.mean()}")

 


 

 

분류 문제에서는 cross_val_score가 기본적으로 StratifiedKFold를 사용한다.  그렇기 때문에 클래스 불균형을 고려해야 하는 상황에서 더 적합하게 동작한다.

 

회귀 문제에서는 KFold가 기본으로 사용된다.

 

따라서, cross_val_score는 분류 문제에 대해 기본적으로 StratifiedKFold를 사용한다고 이해하면 된다.