훈련/검증/테스트 분할 & 교차검증
Train / Validation / Test Split · k-Fold Cross-Validation | 모델의 실력을 "공정하게" 재는 법
시험 문제를 미리 알려주고 시험을 보면 100점을 받아도 실력을 증명하지 못합니다. 모델도 똑같습니다.
학습에 쓴 데이터로 성능을 평가하면, 모델이 데이터를 그냥 외워버렸을 뿐인지 진짜
패턴을 배운 것인지 구분할 수 없습니다. 이 문제를 막기 위해 데이터를 용도별로 나눕니다.
1. 세 부분으로 나누기 — Train / Validation / Test
Train 60%
Validation 20%
Test 20%
| 세트 | 역할 |
| 훈련(Train) | 모델의 가중치·파라미터를 실제로 학습시키는 데이터 |
| 검증(Validation) | 학습에는 쓰지 않고, 하이퍼파라미터 튜닝·모델 선택에 사용 (예: "층을 몇 개로 할까?") |
| 테스트(Test) | 모든 결정이 끝난 뒤 딱 한 번만 사용하는, 최종 성능을 보고하기 위한 데이터 |
테스트셋을 훈련 중에 들여다보면? "테스트에서 성능이 좋게 나올 때까지" 모델을 계속 고치게
되고, 이는 결국 테스트셋에 간접적으로 과적합시키는 것과 같습니다. 실전 배포 후 성능이
크게 떨어지는 흔한 원인입니다. 테스트셋은 금고에 넣어두고 마지막에 한 번만 꺼내 써야 합니다.
2. 데이터가 적을 때의 문제 — 그리고 k-겹 교차검증
데이터를 딱 한 번만 나누면(홀드아웃), 하필 운 좋게(또는 나쁘게) 쉬운 샘플들이 검증셋에 몰릴 수도
있습니다. 데이터가 많지 않을 때는 이 우연이 결과를 크게 흔듭니다. k-겹 교차검증(k-fold
cross-validation)은 학습+검증용 데이터를 k개의 폴드로 나눈 뒤, 매번 폴드 하나를
바꿔가며 검증셋으로 사용하고 나머지 k-1개로 학습합니다. 이를 k번 반복해
k개의 성능 점수를 평균내면, 우연에 덜 흔들리는 안정적인 추정치를 얻습니다.
3. 직접 폴드를 나눠 보기
빗금 친 부분은 맨 처음 떼어 둔 테스트셋(교차검증에도 절대 포함되지 않음)입니다. 아래 막대는
나머지 데이터를 k개 폴드로 나눈 모습이며, 주황색이
이번 회차의 검증 폴드입니다. "다음 폴드"를 눌러 한 바퀴 돌려보세요.
테스트셋 (전체의 20%, 교차검증 끝까지 사용 안 함)
…
4. 흔한 실수 — 데이터 유출(Data Leakage)
스케일링·인코딩을 분할 전에 전체 데이터로 하면? 정규화에 쓰인 평균·표준편차 계산에
테스트 데이터의 정보가 몰래 섞여 들어갑니다(데이터 유출). 반드시 훈련 데이터로만 통계를 계산한
뒤, 그 통계를 검증·테스트 데이터에도 똑같이 적용해야 합니다.
시계열 데이터는 무작위로 섞어 나누면 안 됩니다. 미래 데이터가 훈련셋에 들어가면 "미래를
보고 과거를 맞히는" 반칙이 됩니다. 시간 순서대로 자르는 시계열 분할(time-series split)을
사용해야 합니다.
핵심 정리
- 같은 데이터로 학습·평가하면 암기와 학습을 구분할 수 없다
- Train은 학습, Validation은 튜닝, Test는 마지막에 딱 한 번만
- k-겹 교차검증은 폴드를 바꿔가며 k번 평가해 평균 — 우연에 덜 흔들리는 추정
- 스케일링 등 전처리 통계는 훈련 데이터로만 계산해 데이터 유출을 막는다