데이터 누수 (Data Leakage)
핵심 요약: 데이터 누수는 모델이 시험 답을 미리 본 것과 같다. 학습 시 성능은 환상적이지만, 실전에서는 완전히 망한다. “성능이 너무 좋으면 일단 누수를 의심하라.”
초보자를 위한 핵심 용어
섹션 제목: “초보자를 위한 핵심 용어”- 데이터 누수(Data Leakage): 학습 과정에서 실제 예측 시점에는 알 수 없는 정보가 유입되는 현상. 시험 전에 답안지를 본 것과 같다.
- Train-Test Contamination: 테스트 데이터의 정보가 학습에 섞여 들어가는 유형. 전체 데이터에 스케일링을 먼저 적용하면 발생한다.
- Target Leakage: 예측 시점에 사용할 수 없는 미래 정보가 특성에 포함된 유형. “퇴원일”로 사망 예측하는 것이 대표적.
- Pipeline: 전처리와 모델을 하나로 묶어 누수를 자동 방지하는 도구. sklearn의 Pipeline이 대표적.
숫자로 보는 누수 vs 정상
섹션 제목: “숫자로 보는 누수 vs 정상”상황: 고객 이탈 예측 모델을 만든다고 하자.
| 단계 | 누수 있음 (잘못된 방법) | 누수 없음 (올바른 방법) |
|---|---|---|
| 1단계 | 전체 데이터 스케일링 | 데이터를 먼저 분할 |
| 2단계 | 스케일링된 데이터 분할 | 학습 데이터에만 스케일링 fit |
| 3단계 | 학습/평가 | 테스트에는 transform만 적용 |
| 검증 정확도 | 96% | 82% |
| 실전 정확도 | 73% (급락!) | 81% (안정) |
누수가 있으면 검증 성능과 실전 성능의 괴리가 23%p나 발생한다. 올바른 방법은 검증과 실전이 거의 일치한다.
데이터 누수(Data Leakage)는 학습 과정에서 실제 예측 시점에는 사용할 수 없는 정보가 유입되는 현상이다. 데이터 누수가 있는 모델은 검증 시 뛰어난 성능을 보이지만, 실제 배포 후 성능이 급락한다. ML에서 가장 흔하면서도 발견하기 어려운 문제 중 하나이며, “too good to be true” 성능은 거의 항상 데이터 누수를 의심해야 한다.
탄생 배경
섹션 제목: “탄생 배경”데이터 누수라는 개념이 ML 커뮤니티에서 체계적으로 인식되기 시작한 것은 Kaggle 초기 대회들에서 반복적으로 발생한 누수 사건 덕분이다. 2011년 Heritage Health Prize 대회에서는 참가자들이 환자 ID를 통해 미래 시점의 정보를 간접적으로 유추할 수 있었고, 여러 대회에서 타겟과 직접 연결된 특성이 데이터에 포함되어 비현실적인 AUC 0.99 이상의 점수가 나오는 사례가 빈발했다.
이런 경험들이 축적되면서, Kaggle 커뮤니티는 “성능이 너무 좋으면 일단 누수를 의심하라”는 실무적 지혜를 형성했다. 이후 학계에서도 Kaufman et al. (2012)의 “Leakage in Data Mining” 논문이 데이터 누수를 공식적으로 분류하고 체계화했으며, 이는 오늘날 모든 ML 교육과정에서 다루는 필수 주제가 되었다.
핵심 개념
섹션 제목: “핵심 개념”1. 데이터 누수 유형
섹션 제목: “1. 데이터 누수 유형”Train-Test Contamination (학습-테스트 오염)
섹션 제목: “Train-Test Contamination (학습-테스트 오염)”테스트 데이터의 정보가 학습 과정에 유입되는 경우이다.
대표적 사례:
- 전체 데이터에 스케일링을 적용한 후 학습/테스트 분할
- 교차 검증 바깥에서 전처리 (target encoding, SMOTE 등)
- 동일 원본의 증강 데이터가 학습/테스트 세트에 분산
Target Leakage (타겟 누수)
섹션 제목: “Target Leakage (타겟 누수)”예측 시점에 사용할 수 없는 정보가 특성에 포함되는 경우이다.
예시:
- 환자 퇴원일로 입원 중 사망 예측 (퇴원 = 생존 의미)
- 주문 배송완료 여부로 주문 취소 예측
- 고객의 해지 사유로 해지 예측
Temporal Leakage (시간적 누수)
섹션 제목: “Temporal Leakage (시간적 누수)”시계열 데이터에서 미래 데이터가 학습에 사용되는 경우이다.
원인: random split을 사용하면 미래 데이터가 학습 세트에 포함 해결: 반드시 time-based split 사용
Feature Leakage (특성 누수)
섹션 제목: “Feature Leakage (특성 누수)”타겟의 다른 표현이 특성으로 포함되는 경우이다.
예시: 타겟이 “매출”인데 “수익”이 특성에 포함 (매출 = 수익 + 비용)
2. 누수 탐지 (Detection)
섹션 제목: “2. 누수 탐지 (Detection)”| 신호 | 설명 |
|---|---|
| 비정상적으로 높은 성능 | ”too good to be true” — 현실적이지 않은 AUC > 0.99 |
| 의심스러운 특성 중요도 | 한 특성이 압도적 중요도 → 타겟과 직접 관련 가능성 |
| 학습-테스트 성능 괴리 없음 | 과적합이 전혀 없다면 누수 의심 |
| 배포 후 성능 급락 | 개발 환경에서만 좋은 성능 |
Adversarial Validation:
학습/테스트 데이터를 구분하는 이진 분류기를 학습한다. AUC가 0.5보다 유의하게 높으면 두 데이터의 분포가 다르다는 신호이며, 누수 또는 분포 차이를 의미한다.
- : 학습/테스트 분포가 유사하다 (누수 없음)
- : 분포 차이가 존재한다 (누수 의심)
분포 차이 정량화 — PSI (Population Stability Index):
두 분포 간 차이를 정량적으로 측정하는 지표이다. 각 구간(bin)별 비율 차이를 합산한다.
여기서 는 기준 분포(reference)에서 구간 의 비율, 는 현재 분포에서 구간 의 비율이다.
| PSI 범위 | 해석 |
|---|---|
| < 0.1 | 유의한 변화 없음 |
| 0.1 – 0.25 | 주의 필요 |
| > 0.25 | 유의한 분포 변화 (누수 또는 드리프트 의심) |
KL 발산 (Kullback-Leibler Divergence):
학습 데이터와 서빙 데이터 간 분포 불일치를 측정하는 또 다른 방법이다.
이면 두 분포가 동일하며, 값이 클수록 분포 차이가 크다. KL 발산은 비대칭이므로 임에 유의한다.
3. 누수 예방 (Prevention)
섹션 제목: “3. 누수 예방 (Prevention)”
파이프라인 사용:
# 잘못된 방법scaler.fit(X) # 전체 데이터에 fitX_scaled = scaler.transform(X)X_train, X_test = split(X_scaled)
# 올바른 방법X_train, X_test = split(X)scaler.fit(X_train) # 학습 데이터에만 fitX_train_scaled = scaler.transform(X_train)X_test_scaled = scaler.transform(X_test)
# 가장 좋은 방법: Pipelinefrom sklearn.pipeline import Pipelinepipe = Pipeline([ ('scaler', StandardScaler()), ('model', LogisticRegression())])pipe.fit(X_train, y_train) # 내부적으로 올바르게 처리교차 검증에서의 올바른 전처리 수식:
잘못된 방법 — 전체 데이터에 전처리를 적용한 후 교차 검증을 수행하면 누수가 발생한다:
올바른 방법 — 각 fold 내부에서 학습 데이터에만 fit한 전처리를 적용한다:
여기서 는 에만 fit된 변환이며, 는 번째 fold의 검증 데이터, 는 fold 수이다.
상세 내용
섹션 제목: “상세 내용”데이터 누수 체크리스트
섹션 제목: “데이터 누수 체크리스트”| 점검 항목 | 확인 방법 |
|---|---|
| 전처리가 학습 데이터에만 fit되었는가? | 코드 리뷰 |
| 시간 순서가 유지되었는가? | 학습/테스트의 시간 범위 확인 |
| 각 특성이 예측 시점에 사용 가능한가? | 도메인 전문가와 논의 |
| 동일 엔티티가 학습/테스트에 분산되지 않았는가? | Group split 확인 |
| Target encoding/SMOTE가 fold 내부에서 적용되었는가? | 파이프라인 검토 |
| 성능이 현실적인 수준인가? | 도메인 기대치 비교 |
시간 기반 분할의 중요성
섹션 제목: “시간 기반 분할의 중요성”Kaggle에서의 교훈
섹션 제목: “Kaggle에서의 교훈”Kaggle 대회에서 leakage 특성에 의존하여 높은 순위를 달성하는 경우가 있다. 그러나 이런 모델은 실제 환경에서는 작동하지 않는다. 대회 목적과 실제 배포 목적을 구분해야 한다.
언제 사용하는가
섹션 제목: “언제 사용하는가”데이터 누수 검사는 모든 ML 프로젝트에서 수행해야 한다. 특히:
| 상황 | 누수 위험 |
|---|---|
| 시계열 데이터 | 매우 높음 (temporal leakage) |
| 그룹 데이터 (환자, 사용자) | 높음 (그룹 내 정보 공유) |
| 외부 데이터 결합 | 높음 (시점 불일치) |
| 복잡한 전처리 파이프라인 | 중간 |
| 성능이 비현실적으로 높을 때 | 누수 확인 필수 |
실전 사례
섹션 제목: “실전 사례”주가 예측 모델: 백테스트 수익률 300%의 환상
섹션 제목: “주가 예측 모델: 백테스트 수익률 300%의 환상”한 핀테크 스타트업이 딥러닝 기반 주가 예측 모델을 개발했다. 백테스트(backtesting) 결과 연간 수익률 300%라는 경이적인 성과를 보였고, 투자자들에게 자신 있게 프레젠테이션했다. 그러나 실제 트레이딩에 배포한 후 첫 달부터 손실이 발생했다. 문제의 원인은 다중 데이터 누수였다:
- Temporal leakage: 학습/테스트 분할에 random split을 사용하여, 2023년 12월 데이터로 학습한 모델이 2023년 6월 주가를 “예측”하고 있었다
- Feature leakage: 특성 중 하나인 “거래량 이동평균”이 미래 5일치 거래량을 포함한 윈도우로 계산되어 있었다
- Look-ahead bias: 기업 실적 발표 데이터가 발표일이 아닌 분기 마지막 날 기준으로 조인되어, 아직 발표되지 않은 실적 정보가 특성에 포함되어 있었다
이 사례는 시계열 데이터에서 반드시 시간 기반 분할(time-based split)을 사용해야 하며, 모든 특성이 예측 시점에 실제로 사용 가능한 정보인지 꼼꼼히 검증해야 한다는 교훈을 남겼다.
흔한 오해와 함정
섹션 제목: “흔한 오해와 함정”-
“스케일링은 누수가 아니다”: 전체 데이터의 평균/분산을 사용하면 테스트 데이터의 정보가 학습에 유입된다. 영향이 작을 수 있지만, 원칙적으로는 누수이다.
-
“교차 검증이면 누수가 없다”: 교차 검증 바깥에서 전처리를 하면 여전히 누수이다. 모든 전처리는 각 fold 내부에서 수행해야 한다.
-
“특성 중요도가 높으면 좋은 특성”: 특성 중요도가 비정상적으로 높으면 누수 특성일 가능성을 먼저 의심해야 한다.
-
“데이터 누수는 큰 영향이 없다”: 사소해 보이는 누수도 모델의 실제 배포 성능을 크게 과대 추정하게 만들어, 잘못된 비즈니스 의사결정으로 이어질 수 있다.
-
이미지 증강 시 누수: 같은 원본 이미지의 증강 결과가 학습과 검증 세트에 동시에 포함되면, 모델이 증강 패턴을 학습하여 성능이 과대 추정된다.