Data Leakage Prevention in Machine Learning Pipelines

Source: 2026-04-26-data-leakage-prevention-ml-pipeline Type: Article (Towards Data Science + Kaggle) Valid as of: 2026-04-26

핵심 Takeaway

상세 요약

데이터 누수란?

훈련 중 테스트 데이터 정보가 유출되어 모델이 과도하게 높은 성능을 보임.

실제 성능: 70%
누수로 인한 성능: 95%
→ 배포 후 70% 성능으로 떨어져 회사 손실

원인 1: 잘못된 fit_transform 사용

문제 시나리오:

  1. 전체 데이터에 StandardScaler.fit_transform() 실행
  2. 스케일러가 전체 데이터(test 포함)의 평균·분산으로 학습
  3. 그 후 train-test 분할
  4. 결과: 모델이 테스트 데이터의 통계를 간접 학습 → 훈련 성능 92%, 테스트 성능 91% (의심스러움)

올바른 방법:

  1. train-test 분할 먼저
  2. 훈련 데이터로만 scaler.fit(X_train) 실행
  3. 동일 스케일러로 X_test_scaled = scaler.transform(X_test) 변환
  4. 결과: 훈련 92%, 테스트 87% (5% 격차 = 정상)

원인 2: Train-Test 분할 순서 오류

시나리오 1 (잘못됨): 전체 데이터에서 특성 공학 → 분할

df['age_squared'] = df['age'] ** 2  # 전체 데이터 사용!
# 이후 분할

시나리오 2 (올바름): 분할 → 훈련 데이터의 통계로만 특성 공학

X_train, X_test = split
train_age_mean = X_train['age'].mean()
X_train['normalized'] = (X_train['age'] - train_age_mean) / X_train['age'].std()
X_test['normalized'] = (X_test['age'] - train_age_mean) / X_test['age'].std()  # 훈련 통계 사용

특수 케이스: 시계열 데이터

문제: 무작위 분할 시 미래 데이터가 과거 훈련에 유출

# 잘못됨
X_train, X_test = train_test_split(X_all, y_all, test_size=0.2, random_state=42)
# Train: 2023-12-20, 2023-01-05, ... (뒤섞임)
# Test: 2023-02-10, ... (뒤섞임)
→ 모델이 미래 정보로 과거 예측 강요

올바른 방법: TimeSeriesSplit

tscv = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in tscv.split(X_all):
    # Split 1: Train 2023-01-01~01-31, Test 2023-02-01~07
    # Split 2: Train 2023-01-01~02-07, Test 2023-02-08~14
    # ... (항상 Train < Test 시간 순서)

Pipeline으로 누수 자동 방지

sklearn Pipeline은:

  1. pipeline.fit(X_train, y_train) 시 모든 변환기에 fit_transform 실행 (훈련만)
  2. pipeline.predict(X_test) 시 모든 변환기에 transform 실행 (훈련 통계 사용)
  3. 결과적으로 자동으로 누수 방지

데이터 누수 검출 방법

기법 1: 훈련/테스트 성능 비교

  • 격차 < 5%: 정상
  • 격차 5~10%: 약간의 과적합 (낮은 누수 가능성)
  • 격차 > 10%: 심각한 과적합
  • 격차 ≈ 0%: 누수 확실 (모델이 테스트 알고 있다는 증거)

기법 2: 교차 검증

K-fold CV는 자동으로 각 fold에서 fit/transform 올바르게 실행

기법 3: Permutation Importance

테스트 셋에만 있는 특성이 높은 중요도 → 누수 신호

연결되는 위키 페이지