준비하는 대학생

[기계학습] 교차검증(Cross Validation) 본문

Programming/Machine learning

[기계학습] 교차검증(Cross Validation)

Bangii 2023. 6. 8. 18:24

교차 검증

교차 검증은 데이터를 여러 부분으로 나누고, 각 부분을 훈련과 테스트 용도로 번갈아 사용하여 모델을 평가하는 방법입니다. 이를 통해 모델의 일반화 성능을 더 정확하게 측정할 수 있습니다.

특징

  • 훈련데이터가 많지 않을 때 사용합니다.
  • 훈련 데이터 (training data)로 학습하고 테스트 데이터(test data)로 평가하는 경우, 해당 테스트 데이터에만 과적합되는 모델이 생성되어 일반화 성능이 떨어집니다.
  • 훈련 데이터 (training data)에서 검증 데이터(validation data)를 떼어내어 모형을 검증하는 과정을 여러 번 반복합니다.

K-폴드 교차 검증

K-폴드 교차 검증은 데이터셋을 K개의 부분(폴드)으로 나누는 방법입니다. 이 방법에서는 K번의 다른 실험을 수행하며, 매번 서로 다른 폴드를 테스트 데이터로 사용하고 나머지 K-1개의 폴드를 학습 데이터로 사용합니다. K번의 실험을 통해 얻은 성능 지표들을 평균내어 최종 성능을 산출합니다.

  • 장점: 모든 데이터가 한 번씩은 테스트 데이터로 사용되므로, 데이터를 효율적으로 사용할 수 있습니다.
  • 단점: K값이 크면 연산 비용이 증가합니다.

ex)3-Fold cross validation

 훈련 데이터를 3개의 동일한 크기로 분할하여 분할된 2개의 학습 데이터로 학습하고 1개의 검증 데이터로 분리하여 평가합니다. 검증데이터를 교차하여 3번동안 검증한 뒤 모델의 평가 결과들을 평균하여 종합적으로 성능을 평가합니다.

3-Fold Cross Validation

 

예시 코드

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

iris = load_iris()
scores = []
model = DecisionTreeClassifier(random_state=42)
kfold = KFold(n_splits=5)
for i, (trainData, validateData) in enumerate(kfold.split(iris.data)):
    model.fit(iris.data[trainData], iris.target[trainData])
    print(f"{i+1}번째 모델 점수 : {model.score(iris.data[validateData], iris.target[validateData])}")
    scores.append(model.score(iris.data[validateData], iris.target[validateData]))
print(sum(scores)/5)
1번째 모델 점수 : 1.0
2번째 모델 점수 : 1.0
3번째 모델 점수 : 0.8333333333333334
4번째 모델 점수 : 0.9333333333333333
5번째 모델 점수 : 0.8
0.9133333333333333

n_splits를 5개로 나눠 kfold를 생성하여 데이터를 나눠 모델을 학습시킨뒤 해당 모델의 점수를 모두 더해 산술평균하여 결과를 표현하였습니다. 

여기서 만약 n_spliots를 3으로 설정 즉 3-fold 교차검증을 실시하면 점수가 0점이 나오게 됩니다. 왜냐하면 iris 데이터는 3개의 class 로 구분되는데 이가 50개씩 순차적으로 입력되어 있습니다. 그렇다면 정답이 0,1인 데이터로 학습하고 2인 데이터로 테스트한다면 예측값은 2가 나올 수 없기 때문입니다. 이처럼 데이터가 한쪽으로 쏠려서 테스트를 하는 경우 모델의 성능이 떨어지거나 올바르지 않게 나타날 수 있습니다. 이경우 뒤에 나오는 Stratified K-폴드를 통해 개선할 수 있습니다.

Stratified K-폴드

K-폴드 교차 검증의 경우, 데이터의 클래스 비율이 불균형한 경우 각 폴드에 대해 클래스 분포가 일정하지 않을 수 있습니다. Stratified K-폴드는 각 폴드가 전체 데이터셋의 클래스 비율을 유지하도록 하여, 이러한 문제를 해결합니다.

  • Split() 메서드 사용시 K-fold 와 차이점
    • 피쳐 데이터세트와 함께 레이블 데이터 세트(y값)도 인자로 입력하여야 한다.

일반적으로 분류 문제에서의 교차검증은 K-fold가 아니라 Stratified K-fold로 분할되어야 합니다. 분류문제에서는 Stratified K-fold로 작게 포함된 데이터도 포함하여 학습할 수 있도록 하는것이 올바른 모델을 생성하는데 도움이 될 수 있습니다. 회귀에서는 Stratified K-fold지원 하지 않습니다. y의 값이 연속적이기 때문에 계층적으로 나눌 수 없기 때문에 이경우 일반 k-fold를 이용해 shuffle을 True로 설정해 순차적이지 않고 랜덤으로 교차검증을 할 수 있습니다.

예시 코드

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

iris = load_iris()
scores = []
model = DecisionTreeClassifier(random_state=42)
skfold = StratifiedKFold(n_splits=5)
for i, (trainData, validateData) in enumerate(skfold.split(iris.data,iris.target)):
    model.fit(iris.data[trainData], iris.target[trainData])
    print(f"{i+1}번째 모델 점수 : {model.score(iris.data[validateData], iris.target[validateData])}")
    scores.append(model.score(iris.data[validateData], iris.target[validateData]))
print(sum(scores)/5)
1번째 모델 점수 : 0.9666666666666667
2번째 모델 점수 : 0.9666666666666667
3번째 모델 점수 : 0.9
4번째 모델 점수 : 0.9333333333333333
5번째 모델 점수 : 1.0
0.9533333333333334

cross_val_score

cross_val_score 함수는 K-폴드 교차 검증을 쉽게 수행할 수 있도록 도와줍니다. 이 함수는 모델, 입력 데이터, 타겟 레이블과 함께 교차 검증 방법(예: KFold, StratifiedKFold)을 인자로 받아, 각 폴드에 대한 성능 점수를 반환합니다.

Cross_val_score 주요 매개변수

  • estimator : 분류 모형 또는 회귀 모형 객체 (DTC, DTR 등등)
  • X : 피쳐 데이터 세트
  • y : 레이블 데이터 세트
  • scoring : 예측 성능 평가 지표 (accuracy : 분류, r-squre: 회귀 등)
  • cv : 교차 검증 폴드 수
  • n_jobs: 사용할 CPU 코어 수 (-1인 경우 최대한 많이 사용)

예시 코드

from sklearn.model_selection import cross_val_score
model = DecisionTreeClassifier(random_state=42)
results = cross_val_score(model, iris.data, iris.target, cv=5)

print(f'교차 검증 점수: {results}')
print(f'평균 점수: {results.mean()}')
교차 검증 점수: [0.96666667 0.96666667 0.9        0.93333333 1.        ]
평균 점수: 0.9533333333333334

결론

교차 검증은 모델의 성능을 평가하는데 필수적인 기법입니다. K-폴드 교차 검증과 Stratified K-폴드는 데이터를 여러 부분으로 나누어, 훈련과 테스트에 사용함으로써 보다 일반화된 모델 성능을 측정할 수 있습니다. 그리고 cross_val_score 함수를 사용하면 이 과정을 쉽게 수행할 수 있습니다.

Comments