🧪 [머신러닝 심화] 내 모델의 진짜 실력은? 데이터셋 분리와 모델 검증 완벽 가이드
머신러닝 모델을 만들 때 가장 경계해야 할 것이 무엇일까요? 바로 공부한 문제만 잘 맞히고 새로운 문제는 못 맞히는 '과적합(Overfitting)'입니다. 이를 방지하고 모델의 진짜 실력을 검증하기 위해 데이터를 어떻게 나누고 평가해야 하는지 핵심만 쏙쏙 뽑아 정리해 보겠습니다.
1. 데이터의 세 가지 왕국: Train, Validation, Test
데이터는 용도에 따라 크게 세 가지로 나뉩니다. 시험 공부 과정에 비유하면 이해가 아주 빠릅니다.
- Train 데이터셋 (훈련 데이터): 모델을 학습시킬 때 사용하는 데이터입니다. (교과서와 익힘책)
- Validation 데이터셋 (검증 데이터): 모델의 설정(하이퍼파라미터)을 바꿔가며 어떤 설정이 제일 좋은지 테스트할 때 사용합니다. (모의고사)
- Test 데이터셋 (평가 데이터): 모든 준비가 끝난 후, 마지막에 딱 한 번 모델의 최종 성능을 측정하기 위해 사용합니다. (실제 수능 시험)
⚠️ 주의사항: Test 데이터는 절대로 학습이나 설정 변경에 참여해서는 안 됩니다. 미리 답을 알고 시험을 치는 것과 같기 때문입니다.
2. 방법 1: 홀드아웃(Hold-out) 방식
데이터셋을 단순하게 일정 비율(예: 8:2)로 툭 나누는 방식입니다. scikit-learn의 train_test_split() 함수를 사용합니다.
💻 실무 코드 및 실행 결과
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
# 1. 데이터 로드
iris = load_iris()
# 2. 데이터 분할 (Train 80%, Test 20%)
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.2, stratify=iris.target, random_state=0
)
# 3. 모델 생성 및 학습
model = DecisionTreeClassifier(random_state=0)
model.fit(X_train, y_train)
# 4. 평가
pred = model.predict(X_test)
acc = accuracy_score(y_test, pred)
print(f"평가 결과 정확도: {acc:.4f}")
▶️ 실행 결과:
평가 결과 정확도: 0.9667
- 단점: 데이터 양이 적을 경우, 어떻게 나누냐에 따라 결과가 들쭉날쭉할 수 있습니다. (운 좋게 쉬운 문제만 시험지에 들어갈 수 있음)
3. 방법 2: K-겹 교차 검증 (K-Fold Cross Validation)
홀드아웃의 단점을 보완하기 위해 데이터를 K개로 쪼개고, 번갈아 가며 시험지 역할을 하게 하는 방식입니다. 모든 데이터가 한 번씩은 시험지(Validation)가 됩니다.
💻 실무 코드 및 실행 결과
from sklearn.model_selection import KFold
import numpy as np
# 5-Fold 교차 검증 객체 생성
kfold = KFold(n_splits=5)
acc_list = []
for train_idx, test_idx in kfold.split(iris.data):
# 인덱스를 이용해 데이터 분할
X_train, X_test = iris.data[train_idx], iris.data[test_idx]
y_train, y_test = iris.target[train_idx], iris.target[test_idx]
# 학습 및 예측
model.fit(X_train, y_train)
pred = model.predict(X_test)
acc_list.append(accuracy_score(y_test, pred))
print(f"5번의 개별 정확도: {acc_list}")
print(f"평균 정확도: {np.mean(acc_list):.4f}")
▶️ 실행 결과:
5번의 개별 정확도: [1.0, 0.9667, 0.8667, 0.9333, 0.7333] 평균 정확도: 0.9000
4. 방법 3: 층화 K-폴드 (Stratified K-Fold)
분류 문제에서 정답(Class)의 비율이 한쪽으로 쏠리는 것을 방지하기 위해 사용합니다. 원본 데이터의 품종 비율을 유지하면서 쪼개기 때문에 훨씬 공정한 평가가 가능합니다.
from sklearn.model_selection import StratifiedKFold
# StratifiedKFold는 split할 때 정답 데이터(y)도 함께 넣어줘야 비율을 맞춥니다.
s_kfold = StratifiedKFold(n_splits=5)
s_acc_list = []
for train_idx, test_idx in s_kfold.split(iris.data, iris.target):
X_train, X_test = iris.data[train_idx], iris.data[test_idx]
y_train, y_test = iris.target[train_idx], iris.target[test_idx]
model.fit(X_train, y_train)
s_acc_list.append(accuracy_score(y_test, model.predict(X_test)))
print(f"층화 K-폴드 평균 정확도: {np.mean(s_acc_list):.4f}")
▶️ 실행 결과:
층화 K-폴드 평균 정확도: 0.9600 (비율이 일정하므로 일반 K-Fold보다 더 안정적인 결과가 나옵니다.)
5. 가장 편한 도구: cross_val_score()
위의 복잡한 for문을 한 줄로 끝내주는 함수입니다. 내부적으로 Stratified K-Fold(분류일 때)를 사용하여 교차 검증을 수행합니다.
from sklearn.model_selection import cross_val_score
# 모델, 데이터, 정답, 폴드 수(cv)만 지정하면 끝!
scores = cross_val_score(model, iris.data, iris.target, cv=5)
print(f"교차 검증 점수: {scores}")
print(f"최종 평균 정확도: {np.mean(scores):.4f}")
▶️ 실행 결과:
교차 검증 점수: [0.96666667 0.96666667 0.9 0.96666667 1. ] 최종 평균 정확도: 0.9600
📝 [실습 TODO] 나만의 모델 검증 연습
오늘 배운 내용을 바탕으로 다음 문제를 해결해 보세요!
- TODO 1 (데이터 분할): train_test_split을 사용하여 Train과 Test 세트를 7:3 비율로 나누고, random_state=42를 적용하세요.
- TODO 2 (K-Fold): 일반 KFold를 사용하여 3-Fold 교차 검증을 수행하고 각 폴드의 정확도를 출력하세요.
- TODO 3 (함수 활용): cross_val_score 함수를 사용하여 cv=10 (10-Fold)으로 교차 검증을 수행한 뒤 평균 정확도를 구하세요. 이때 모델은 DecisionTreeClassifier(max_depth=2)를 사용하세요.
- TODO 4 (이유 생각하기): 왜 단순한 Hold-out 방식보다 K-Fold 교차 검증이 모델의 성능을 평가하는 데 더 신뢰할 수 있는지 블로그 댓글로 남기듯 한 문장으로 정리해 보세요.
💡 [정답 확인 예시]
# TODO 3 예시 코드
from sklearn.model_selection import cross_val_score
dt_model = DecisionTreeClassifier(max_depth=2, random_state=0)
scores = cross_val_score(dt_model, iris.data, iris.target, cv=10)
print(f"10-Fold 평균 정확도: {np.mean(scores):.4f}")
▶️ 예상 결과: 10-Fold 평균 정확도: 0.9333 (설정에 따라 다를 수 있습니다.)
'두두 IT > 파이썬' 카테고리의 다른 글
| [머신러닝 1] 머신러닝(ML)개요 (0) | 2026.05.12 |
|---|---|
| [머신러닝 3-2] 데이터셋 분할 & 교차 검증 (0) | 2026.05.12 |
| [머신런닝 2] 머신러닝 분석 - Iris_분석 (0) | 2026.05.12 |
| [PYTHON] NumPy 데이터 다루기 (0) | 2026.05.08 |
| [PYTHON] 파이썬 데이터 분석 기초 Numpy (0) | 2026.05.08 |