RyanNerd
라덕'Story
RyanNerd
  • 분류 전체보기 (72) N
    • Study Note (37) N
      • Python (3)
      • R (1)
      • Airflow (7)
      • 통계 (22) N
      • 머신러닝 (4) N
    • 빅데이터분석기사 (1)
      • 필기 (1)
    • Programmers (28)
      • Python (13)
      • SQL (15)
    • Project (3)
      • Django (3)
    • Mac (2)

블로그 메뉴

  • NaverBlog
  • 홈

최근 글

전체 방문자
오늘
어제
hELLO · Designed By 정상우.
RyanNerd

라덕'Story

Study Note/머신러닝

내 모델 믿어도 될까? 교차 검증(Cross Validation) 완벽 가이드

2025. 12. 20. 20:20

머신러닝 모델을 만들고 "정확도 99%입니다!"라고 자랑했는데, 막상 새로운 환자 데이터를 넣으니 다 틀린다면? 이는 모델이 운 좋게 쉬운 시험 문제(Test Set)만 풀었거나, 학습 데이터에만 너무 익숙해진 과적합(Overfitting) 상태일 가능성이 큽니다.

이를 방지하기 위해 반드시 거쳐야 하는 과정, 교차 검증(Cross Validation)을 알아봅니다.

 

1. 홀드아웃(Holdout) vs K-폴드(K-Fold)

① 홀드아웃 (Holdout) 교차 검증

  • 개념: 데이터를 한 번만 딱 잘라서(예: 8:2) 학습용과 검증용으로 나눕니다
  • 문제점: 하필이면 검증 데이터가 너무 쉽거나 특이한 케이스만 모여 있다면? 모델의 진짜 성능을 알 수 없게 됩니다(검증 데이터에 Overfit)

② K-폴드 (K-Fold) 교차 검증

  • 개념: 데이터를 $K$개의 조각(Fold)으로 나눕니다.
    • 1번 조각으로 시험 보고, 나머지로 공부.
    • 2번 조각으로 시험 보고, 나머지로 공부.
    • ... 이렇게 $K$번 반복해서 시험을 봅니다
  • 최종 점수: $K$번의 시험 점수 평균을 냅니다.
  • 장점: 모든 데이터를 골고루 시험 문제로 써보기 때문에 평가가 훨씬 공정하고 신뢰할 수 있습니다.
  • 단점: 학습을 $K$번이나 해야 하므로 시간이 오래 걸립니다.

2. 의료 데이터의 필수품: Stratified K-Fold

의료 데이터는 대부분 불균형(Imbalanced)합니다. (예: 정상인 90명 vs 희귀병 환자 10명) 이때 그냥 랜덤으로 자르면, 어떤 조각에는 환자가 한 명도 없을 수도 있습니다.

  • Stratified K-Fold (계층적 K-폴드):
    • 원본 데이터의 정답 비율(Class Distribution)을 유지하면서 나눕니다.
    • 예: 전체가 정상:환자=9:1이라면, 모든 Fold 안에도 9:1 비율이 되도록 강제로 맞춰서 자릅니다.

      핵심: 암 환자 예측이나 이상 탐지처럼 데이터 불균형이 심한 의료 분야에서는 반드시 일반 K-Fold 대신 Stratified K-Fold를 써야 합니다.

3. [실습] Python으로 구현하는 교차 검증

sklearn의 cross_val_score를 사용하면 이 복잡한 과정을 단 한 줄로 끝낼 수 있습니다.

🏥 의료 데이터 예시: 당뇨병 예측 모델 검증

(데이터 불균형 상황을 가정하여 Stratified K-Fold를 적용합니다.)

import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold
from xgboost import XGBClassifier

# 1. 데이터 로드 (유방암 데이터: 악성 vs 양성)
data = load_breast_cancer()
X = data.data
y = data.target

# 2. 모델 준비 (XGBoost)
model = XGBClassifier(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)

# --- Case 1: 일반 K-Fold ---
# 데이터를 5등분, 섞어서(shuffle=True) 나눔 [cite: 515, 516]
kfold = KFold(n_splits=5, shuffle=True, random_state=42)

# cross_val_score: 교차 검증 점수를 배열로 반환 [cite: 530]
scores_kfold = cross_val_score(model, X, y, cv=kfold, scoring='accuracy')

print("=== 일반 K-Fold 검증 결과 ===")
print(f"각 Fold 정확도: {np.round(scores_kfold, 4)}")
print(f"평균 정확도: {np.mean(scores_kfold):.4f}")


# --- Case 2: Stratified K-Fold (의료 데이터 추천) ---
# 정답(y)의 비율을 유지하며 나눔 
stratified_kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

scores_strat = cross_val_score(model, X, y, cv=stratified_kfold, scoring='accuracy')

print("\n=== Stratified K-Fold 검증 결과 ===")
print(f"각 Fold 정확도: {np.round(scores_strat, 4)}")
print(f"평균 정확도: {np.mean(scores_strat):.4f}")

'Study Note > 머신러닝' 카테고리의 다른 글

"모든 변수가 다 중요할까?" 피처 중요도(Feature Importance)로 모델 다이어트하기  (0) 2025.12.20
머신러닝의 꽃, 앙상블과 부스팅 (XGBoost, LightGBM) 완전 정복  (1) 2025.12.19
[ML 기초] 통계가 머신러닝이 되는 순간: 나이브 베이즈와 ML 프로세스  (0) 2025.12.19
    'Study Note/머신러닝' 카테고리의 다른 글
    • "모든 변수가 다 중요할까?" 피처 중요도(Feature Importance)로 모델 다이어트하기
    • 머신러닝의 꽃, 앙상블과 부스팅 (XGBoost, LightGBM) 완전 정복
    • [ML 기초] 통계가 머신러닝이 되는 순간: 나이브 베이즈와 ML 프로세스
    RyanNerd
    RyanNerd
    라이언 덕후의 일상 스토리~

    티스토리툴바