흔한 실수 (Common Mistakes in ML)
핵심 요약: ML 프로젝트에서 가장 흔한 8가지 실수. 대부분 데이터 처리 순서에서 발생한다 — 전처리를 먼저 하고 분할하면 누수, 정확도만 보면 불균형 함정, 베이스라인 없이 시작하면 방향 상실.
초보자를 위한 핵심 용어
섹션 제목: “초보자를 위한 핵심 용어”- Data Snooping: 테스트 데이터를 보고 모델을 수정하는 실수. 시험 답안지를 미리 보고 공부 방향을 정하는 것과 같다.
- 검증 세트 과적합(Validation Overfitting): 검증 세트 결과를 보고 반복 튜닝하여, 검증 성능만 좋고 실전에서 떨어지는 현상.
- Training-Serving Skew: 학습 환경(Python)과 배포 환경(Java)의 전처리 차이로 성능이 급락하는 문제.
- Baseline: 비교 기준이 되는 가장 단순한 모델. 이것 없이 시작하면 “개선했는지” 자체를 판단할 수 없다.
ML 프로젝트에서 반복적으로 발생하는 실수들이 있다. 이 실수들은 대부분 성능의 과대 추정, 잘못된 결론, 또는 프로덕션에서의 실패로 이어진다. 경험이 풍부한 실무자도 실수할 수 있으며, 이를 미리 인지하고 체계적으로 방지하는 것이 중요하다.
탄생 배경
섹션 제목: “탄생 배경”ML의 흔한 실수들이 체계적으로 정리된 것은, Kaggle 대회와 산업 ML 프로젝트의 실패에서 반복적으로 발견된 패턴들이 축적된 결과이다.
Kaggle 초기 대회에서의 교훈 (2010~2015):
- Kaggle 대회 초기에는 참가자들이 테스트 세트에 대해 반복적으로 제출하면서 리더보드에 과적합(Overfitting to Leaderboard)하는 현상이 빈번했다. Public Leaderboard에서 1등이었던 팀이 Private Leaderboard에서 수백 위로 추락하는 사례가 반복되면서, “검증 세트 과적합”이라는 개념이 널리 알려졌다.
- 일부 대회에서는 의도치 않은 데이터 누수(Data Leakage)가 발견되어 대회가 무효화되기도 했다. 예를 들어, 파일명에 라벨 정보가 포함되어 있거나, 시간 순서가 무시된 분할이 사용된 경우가 있었다.
산업 ML 실패 사례의 축적 (2015~현재):
- 2015년 이후 기업들의 ML 도입이 본격화되면서, 학술 환경에서는 문제가 되지 않았던 실수들이 프로덕션에서 대규모 사고로 이어졌다. Training-Serving Skew로 인한 서비스 장애, 불균형 데이터에서의 잘못된 지표 선택으로 인한 비즈니스 손실, 교차 검증 전 전처리로 인한 성능 과대 추정 등이 반복적으로 보고되었다.
- 이러한 실패 사례들이 블로그, 컨퍼런스 발표, 논문 등을 통해 공유되면서, ML 실무자들 사이에서 “흔한 실수 체크리스트”가 자연스럽게 형성되었다. 본 문서는 그 축적된 교훈을 체계적으로 정리한 것이다.
핵심 개념
섹션 제목: “핵심 개념”1. 데이터 몰래 보기 (Data Snooping)
섹션 제목: “1. 데이터 몰래 보기 (Data Snooping)”테스트 데이터로 모델을 선택하거나 튜닝하여, 성능이 과도하게 낙관적으로 추정되는 문제이다.
| 잘못된 방법 | 올바른 방법 |
|---|---|
| 테스트 세트 결과를 보고 모델 수정 | Hold-out 테스트 세트는 최종 1회만 사용 |
| 여러 모델을 테스트 세트로 비교 | 검증 세트로 비교, 테스트 세트는 최종 모델에만 |
2. 부적절한 검증 (Improper Validation)
섹션 제목: “2. 부적절한 검증 (Improper Validation)”| 실수 | 올바른 방법 |
|---|---|
| 시계열에 random split | Time-based split |
| 그룹 데이터에서 그룹을 분할하지 않음 | Group K-Fold |
| 교차 검증 전에 전처리 | 각 fold 내부에서 전처리 |
| Stratification 없이 불균형 데이터 분할 | Stratified K-Fold |
잘못된 교차 검증 — 전체 데이터에서 전처리 후 교차 검증을 수행하면 검증 오차가 과소 추정된다:
올바른 교차 검증 — 각 fold 내부에서 전처리를 수행해야 한다:
여기서 전처리의 fit은 (학습 fold)에서만 수행하고, (검증 fold)에는 transform만 적용한다.
3. 클래스 불균형 무시
섹션 제목: “3. 클래스 불균형 무시”정확도(accuracy)만 보고 “모델이 잘 작동한다”고 판단하는 실수.
Before: “Accuracy 98%로 우수한 모델!”
After: “소수 클래스 Recall 0%… 모델이 다수 클래스만 예측”
→ 불균형 데이터에서는 F1, AUROC, AUPRC를 사용해야 한다.
4. 잘못된 지표 선택
섹션 제목: “4. 잘못된 지표 선택”비즈니스 목표와 최적화 지표의 불일치.
| 상황 | 잘못된 지표 | 적절한 지표 |
|---|---|---|
| 스팸 필터 | Recall (정상 메일 차단 위험) | Precision 우선 |
| 질병 선별 검사 | Precision (환자 누락 위험) | Recall 우선 |
| 추천 시스템 | Accuracy | nDCG, MAP |
| 회귀 (이상치 있음) | MSE | MAE 또는 Huber |
5. 검증 세트 과적합 (Overfitting to Validation Set)
섹션 제목: “5. 검증 세트 과적합 (Overfitting to Validation Set)”반복적인 하이퍼파라미터 튜닝으로 validation set에 과적합되는 문제. 번의 튜닝 시도를 하면, 검증 세트에서의 최적 성능은 실제보다 낙관적으로 추정된다:
- : 하이퍼파라미터 조합의 시도 횟수
- : 검증 세트 크기
- : 검증 세트에서 가장 좋았던 성능
이 부등식(union bound + Hoeffding)은 시도 횟수 이 증가할수록 과적합 위험이 으로 커짐을 보여준다.
해결:
- Nested cross-validation
- 별도의 최종 test set 유지
- 튜닝 횟수를 제한하고 기록
6. Baseline 미설정
섹션 제목: “6. Baseline 미설정”복잡한 모델부터 시작하면 개선 여부를 판단할 수 없다.
규칙: 항상 가장 간단한 모델로 baseline을 설정한 후, 복잡성을 늘려라.
7. 분할 후 특성 공학
섹션 제목: “7. 분할 후 특성 공학”| 실수 | 결과 |
|---|---|
| 전체 데이터에서 target encoding | 데이터 누수 |
| 전체 데이터에서 feature selection | 테스트 정보 유입 |
| 전체 데이터에서 스케일링 fit | 미미하지만 원칙적 누수 |
올바른 순서: 분할 → 학습 데이터로만 전처리 fit → 테스트에 transform
8. Training-Serving Skew
섹션 제목: “8. Training-Serving Skew”학습 시와 배포 시의 데이터 전처리 불일치. 누수 탐지를 위해 학습 세트와 테스트 세트의 특성 분포 차이를 정량적으로 측정할 수 있다. PSI (Population Stability Index)는 두 분포 간의 안정성을 측정한다:
- : 구간(bin)의 수
- : 실제(서빙) 데이터에서 번째 구간의 비율
- : 학습 데이터에서 번째 구간의 비율
- : 안정, : 주의, : 분포 변화 심각
원인: 학습은 Python/pandas, 서빙은 Java/C++ 등 다른 환경에서 전처리
해결: 전처리 파이프라인을 모델과 함께 직렬화 (sklearn Pipeline, ONNX 등)
상세 내용
섹션 제목: “상세 내용”실수 방지 체크리스트
섹션 제목: “실수 방지 체크리스트”Before/After 비교
섹션 제목: “Before/After 비교”| 실수 | Before (잘못된 방법) | After (올바른 방법) |
|---|---|---|
| 전처리 순서 | scale(전체) → split → train | split → scale.fit(train) → transform |
| 시계열 분할 | random_split(data) | data[:cutoff], data[cutoff:] |
| SMOTE 시점 | SMOTE(전체) → cross_val | for fold: SMOTE(train_fold) |
| 성능 평가 | accuracy = 99% → 배포 | AUPRC, F1 확인 → 오류 분석 → 배포 |
| Baseline | 바로 딥러닝 시작 | 로지스틱 회귀 → XGBoost → 딥러닝 |
언제 사용하는가
섹션 제목: “언제 사용하는가”이 체크리스트는 모든 ML 프로젝트에서 참고해야 한다. 특히:
- 새로운 프로젝트를 시작할 때
- 모델 성능이 비현실적으로 높을 때
- 프로덕션 배포 전 최종 검증 시
- 코드 리뷰 시
- 팀에 새로운 멤버가 합류할 때
실전 사례
섹션 제목: “실전 사례””8가지 실수를 모두 한 스타트업”
섹션 제목: “”8가지 실수를 모두 한 스타트업””한 헬스케어 AI 스타트업이 환자 재입원 예측(Patient Readmission Prediction) 모델을 개발하면서, 이 문서에서 다루는 거의 모든 실수를 경험한 사례이다.
실수 타임라인:
| 순서 | 실수 | 구체적 상황 | 결과 |
|---|---|---|---|
| 1 | Baseline 미설정 | ”딥러닝으로 시작해야 투자자에게 보여줄 수 있다”며 바로 LSTM 모델 구축 | 개선 기준 없이 3개월 소비 |
| 2 | 데이터 몰래 보기 | 테스트 세트 결과를 보고 모델 구조를 반복 수정 | 테스트 정확도 96% 달성 (과대 추정) |
| 3 | 부적절한 검증 | 시계열 특성의 환자 데이터에 Random Split 사용 | 미래 데이터가 학습에 포함 |
| 4 | 분할 후 특성 공학 | 전체 데이터에서 Target Encoding 수행 | 심각한 데이터 누수 |
| 5 | 클래스 불균형 무시 | 재입원 비율 8%인 데이터에서 Accuracy 92%에 만족 | 실제로는 “재입원 없음”만 예측 |
| 6 | 잘못된 지표 선택 | Accuracy만 보고하며 “우수한 모델” 주장 | 재입원 환자 Recall 0% |
| 7 | 검증 세트 과적합 | 200번 이상의 하이퍼파라미터 튜닝 | 검증 성능과 실제 성능 간 큰 괴리 |
| 8 | Training-Serving Skew | Python 전처리를 Java로 재구현하면서 날짜 파싱 차이 | 프로덕션 성능 급락 |
최종 결과:
- 테스트 세트 성능: 정확도 96%, F1 0.89 (실험실 환경)
- 프로덕션 성능: 정확도 71%, F1 0.23 (실제 환경)
- 투자된 비용: $1.2M (12개월)
- 실제 가치: 배포 후 2주 만에 서비스 중단
수정 후: 외부 컨설턴트의 감사를 거쳐, 올바른 Time-based Split + Stratified K-Fold + Pipeline 기반 전처리 + 로지스틱 회귀 베이스라인부터 다시 시작했다. 2개월 만에 프로덕션에서 안정적으로 동작하는 모델(F1 0.67)을 배포했으며, 이 모델이 처음의 “96% 정확도” 모델보다 실제 환경에서 압도적으로 유용했다.
흔한 오해와 함정
섹션 제목: “흔한 오해와 함정”-
“나는 경험이 많으니 이런 실수를 하지 않는다”: 압박과 시간 제약 하에서 누구나 실수할 수 있다. 체크리스트와 자동화된 파이프라인으로 방지하라.
-
“한 번 확인했으니 됐다”: 코드 변경, 데이터 업데이트 시 새로운 누수가 발생할 수 있다. CI/CD에 검증을 통합하라.
-
“Kaggle 대회와 실무는 같다”: 대회에서는 누수 특성도 활용하지만, 실무에서는 배포 시점의 특성 사용 가능성을 반드시 확인해야 한다.
-
“검증 성능이 좋으니 배포해도 된다”: 프로덕션에서는 데이터 drift, 지연시간, 공정성 등 검증 성능 이외의 요소도 중요하다.
다른 주제와의 연결
섹션 제목: “다른 주제와의 연결”- 데이터 누수: 가장 흔한 실수의 상세 설명
- 불균형 데이터: 지표 선택의 중요성
- ML 파이프라인 설계: 올바른 파이프라인으로 실수 방지
- 실험 추적: 재현 가능한 실험
- 모델 배포: Training-Serving Skew
- 윤리적 AI: 공정성 관련 실수
- ML 시스템 설계 패턴: 프로덕션 운영의 실수