CertNote/ 출퇴근 학습 노트
로드맵
KOEN
CLF-C02 · FoundationalCloud Practitioner - Foundational
DVA-C02 · AssociateDeveloper - Associate
SAA-C03 · AssociateSolutions Architect - Associate
SOA-C02 · AssociateCloudOps Engineer - Associate
SAP-C02 · ProfessionalSolutions Architect - Professional
DOP-C02 · ProfessionalDevOps Engineer - Professional
SCS-C03 · SpecialtySecurity - Specialty
MLA-C01 · AssociateMachine Learning Engineer - Associate
AIF-C01 · FoundationalAI Practitioner - Foundational
DEA-C01 · AssociateData Engineer - Associate
MLS-C01 · SpecialtyMachine Learning - Specialty
  • Week 1
    • 1.ML 수명주기(ML Lifecycle): 비즈니스 문제 정의부터 A/B 테스트까지
    • 2.ML용 데이터 저장소: S3·EFS·FSx for Lustre·데이터 포맷
    • 3.데이터 수집: Kinesis·Glue·배치 vs 스트리밍
    • 4.데이터 레이블링: SageMaker Ground Truth·액티브 러닝(Active Learning)·레이블 품질
    • 5.1주차 종합 복습: ML 개요와 데이터 엔지니어링 1
  • Week 2
  • Week 3
  • Week 4
  • Week 5
    • 1.통계 기초: 분포·중심 경향·산포·변환·표본과 모집단
    • 2.상관관계 분석: 상관계수·상관과 인과의 차이·다변량 관계
    • 3.데이터 누수(Data Leakage): 원인·탐지·예방과 시계열 누수·타깃 누수
    • 4.검증 설계: 학습/검증/테스트 분할·교차 검증·시계열 분할·층화 샘플링
    • 5.5주차 종합 복습: 통계와 검증 설계
  • Week 6
  • Week 7
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← MLS-C01/Week 5/Day 3

기준: MLS-C01 시험 가이드·오류 제보

MLS-C01· AssociateWeek 5 · Day 3읽기 약 13분
핵심 정리
  • 누수(leakage)는 예측 시점에 알 수 없었을 정보가 학습에 들어오는 것이다. 검증 점수만 부풀고 실제 운영에서 무너진다.
  • 타깃 누수는 결과 정보가 피처 자체에 박혀 있어 분할을 아무리 잘해도 잡히지 않는다. 피처 생성 시점을 따져야 한다.
  • 시계열 누수는 무작위 분할·미래 윈도 집계에서 나온다. 시간 순 분할과 과거만 보는 집계(shift 후 rolling)로 막는다.
  • train-test 오염은 분할 전에 전처리를 해서 생긴다. 먼저 분할하고 학습 부분으로만 fit하며, Pipeline으로 강제한다.
  • 판별 질문은 언제나 하나다 — "예측하는 그 순간에 이 값을 정말 알 수 있었는가?" 아니면 누수다.

Day 3 - 데이터 누수(Data Leakage): 원인·탐지·예방과 시계열 누수·타깃 누수

데이터 누수란 무엇인가

검증 점수는 완벽한데 실제 운영에서 모델이 처참하게 실패한다. 범인은 거의 항상 하나 — 데이터 누수다. 누수는 모델이 학습 시점에 실제로는 가질 수 없었던 정보에 접근해 평가 점수가 인위적으로 부풀려지는 현상이다.

MLS-C01은 누수에 집착한다. "검증은 99%인데 프로덕션은 60%?" 같은 시나리오의 답은 거의 항상 누수다.

유형정의결과
타깃 누수(target leakage)타깃 정보가 직간접적으로 피처에 포함됨학습·검증이 둘 다 비현실적으로 높다
train-test 오염(contamination)전처리·분할을 통해 테스트 정보가 학습에 유입됨검증은 높은데 프로덕션이 낮다

핵심 질문은 언제나 같다. "예측을 내리는 그 시점에, 우리가 이 값을 정말 알 수 있었는가?" 아니라면 누수다.

누수는 본질적으로 시험 부정행위와 같다 — 모델이 이미 답안지를 본 것이다. 통계적으로는 검증셋의 독립성 가정을 위반한다. 검증 점수가 미지의 데이터에 대한 일반화 성능을 추정하려면, 검증셋이 학습 과정과 완전히 독립이어야 한다. 누수가 있으면 검증 점수는 일반화가 아니라 "이미 본 정보를 재현하는 능력"을 재게 되고, 그 위에서 내린 모델 선택·하이퍼파라미터 튜닝 결정이 전부 오염된다.

누수 유형 → 증상 → 탐지 → 예방 (핵심 표)

누수 유형전형적 원인증상탐지 방법예방
타깃 누수결과가 확정된 뒤 생성되는 값이 피처에 포함학습·검증·테스트 모두 높고 운영만 낮다단일 피처 중요도·상관 이상 高, 피처 생성 시점 감사각 피처의 타임스탬프 확인, 예측 시점 이후 데이터 제거
시계열 누수무작위 분할, 미래 포함 윈도 집계백테스트는 좋은데 실제 미래 예측이 나쁘다학습 구간이 검증 구간보다 미래인지 확인시간 순 분할, shift(1) 후 rolling
train-test 오염분할 전 스케일링·대치·인코딩검증 점수가 재현되지 않는다전처리 코드가 분할 전인지 확인먼저 분할 → 학습 부분만 fit → Pipeline
그룹 누수같은 사용자·환자의 행이 학습과 검증에 흩어짐개인화 성능이 과대평가그룹 ID가 양쪽 분할에 모두 있는지 확인GroupKFold / 그룹 단위 분할
중복 행 누수분할 전 중복 제거 누락같은 레코드가 학습·테스트 양쪽에 존재중복 키 카운트분할 전에 중복 제거
샘플링 누수분할 전 SMOTE 등 오버샘플링합성 샘플이 양쪽에 걸침리샘플링 시점 확인학습 부분에만 리샘플링 적용

타깃 누수: 미래·결과 정보가 섞여 든다

타깃 누수는 예측하려는 타깃에 관한 정보가 피처에 포함될 때 일어난다. 가장 은밀하고 흔하다.

시나리오누수 피처왜 누수인가
질병 진단 예측투약_여부진단이 내려진 후에야 투약한다
이탈 예측해지_사유_코드이탈이 확정된 뒤 생성된다
대출 부도 예측연체_횟수(미래 기간 포함)부도 발생 이후에 누적된다
매출 예측당월_최종_매출타깃 그 자체
이탈 예측고객센터_해지문의_수해지 의사 표명 이후 발생한 이벤트

타깃 누수의 신호:

  • 단일 피처의 상관·중요도가 비정상적으로 높다(한 변수가 정확도의 95%를 설명).
  • 피처가 타깃과 동시에 또는 그 이후에 만들어진다.
  • "예측 시점에 이 값을 정말 알 수 있는가?"의 답이 "아니오"다.
# 타깃 누수 의심 점검: 단일 피처가 타깃을 지나치게 설명하는지 확인
import pandas as pd
 
corr_with_target = (
    df.corr(numeric_only=True)["churned"]
    .abs()
    .sort_values(ascending=False)
)
print(corr_with_target.head(10))
# 어떤 피처의 상관이 0.95 이상이면 "예측 시점에 알 수 있는 값인가?"를 먼저 의심한다

⚠️ 함정: 타깃 누수는 train/validation/test를 완벽하게 나눠도 잡히지 않는다. 누수가 피처 자체에 박혀 있기 때문이다. 모든 분할이 똑같이 오염된다. 그래서 분할만으로는 부족하고, 각 피처가 언제 만들어지는지(타임스탬프)와 예측 시점과의 관계를 도메인 지식으로 따져야 한다. "검증도 높고 테스트도 높은데 운영만 낮다?" → 타깃 누수를 1순위로 의심한다.

누수 의심 신호표

관찰해석다음 행동
검증 정확도 99%+, 문제가 원래 어려움너무 좋으면 의심하라피처별 중요도부터 확인
한 피처를 빼면 성능이 폭락그 피처가 답을 담고 있다그 피처의 생성 시점 감사
학습·검증 격차가 거의 0검증이 독립적이지 않을 수 있다분할·전처리 순서 점검
검증·테스트 높음, 운영만 낮음타깃 누수피처 타임스탬프 감사
검증 높음, 테스트부터 낮음train-test 오염전처리 fit 위치 점검
백테스트 좋고 실전 미래 예측 나쁨시계열 누수분할 방식·윈도 정의 점검

시계열 누수: 미래가 과거로 새어 든다

시계열 데이터에서 가장 흔한 누수는 미래 정보로 과거를 예측하는 것이다.

원인:

  • 무작위 분할: 시계열을 섞으면 미래 데이터가 학습에, 과거가 테스트에 들어간다 → 미래로 과거를 예측
  • 미래 포함 윈도 집계: "최근 30일 평균"을 예측 시점 이후 데이터까지 포함해 계산
  • 전역 통계 사용: 전체 평균으로 정규화 → 미래 정보가 과거 행에 스며든다
  • lag/rolling 경계 오류: shift를 잘못 걸어 t+1 값이 t 시점에 들어간다
[잘못된 무작위 분할]                    [올바른 시간 순 분할]
시간축 ──────────────────────▶          시간축 ──────────────────────▶
 T T V T V T T V T V T T V T             T T T T T T T T | V V V | E E
 └─ 학습(T)과 검증(V)이 뒤섞임              학습             검증    평가
    → 모델이 t+1을 보고 t를 "예측"          └── 항상 과거 → 미래 방향 ──┘
    → 시간 역행 학습 = 누수                  (forward-chaining, 배포 상황과 동일)
import pandas as pd
 
df = df.sort_values("date")
 
# 올바른 방법: 과거만 보는 rolling (shift로 현재 행을 제외)
df["sales_ma7"] = df["sales"].shift(1).rolling(7).mean()  # t-1 ~ t-7
 
# 시계열은 시간 순 분할 (무작위 분할 금지)
cutoff = "2025-01-01"
train = df[df["date"] < cutoff]
test = df[df["date"] >= cutoff]

시계열에서 무작위 분할이 치명적인 이유는 시간적 의존성 때문이다. 일반 데이터는 행이 서로 독립이라고 가정하지만, 시계열은 인접 시점 간 상관이 강하다. 무작위로 섞으면 모델이 t+1의 패턴을 보고 t를 "예측"하게 되어, 현실에서 불가능한 시간 역행을 학습한다. 그래서 시계열 검증은 항상 "과거로 학습하고 미래로 평가(forward-chaining)" 원칙을 따라야 하며, 이것이 Day 4의 시계열 분할로 이어진다.

train-test 오염: 전처리를 통한 누수

분할을 제대로 해도 분할 전에 전체 데이터로 전처리하면 테스트 정보가 학습으로 샌다.

잘못된 방식누수 경로
전체 데이터로 스케일러 fit테스트의 평균·표준편차가 학습 스케일에 반영
전체 데이터로 대치 통계 계산테스트 분포가 대치값에 들어간다
전체 데이터로 타깃 인코딩테스트의 타깃 평균이 인코딩에 포함
분할 전 중복 제거 누락같은 레코드가 학습·테스트 양쪽에 등장
분할 전 오버샘플링(SMOTE)합성 샘플이 학습과 테스트에 걸친다
전체 데이터로 특성 선택테스트 정보를 보고 피처를 골라 선택 편향 발생

해결책은 전처리를 분할·교차검증 안쪽에 가두는 Pipeline이다.

[누수가 나는 순서]                     [Pipeline이 막는 방식]
전체 데이터                             전체 데이터
   │                                       │
   ▼ fit(scaler) ← 테스트 통계 포함          ▼ split
전체 스케일링                            학습 fold │ 검증 fold
   │                                       │         │
   ▼ split                            fit+transform  transform만
학습 │ 테스트                              │         │  (학습 fold 통계만 사용)
   └─ 이미 오염됨                          └─ 모델 학습 ▶ 평가
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
 
# Pipeline: 각 fold의 학습 부분에서만 fit이 일어나 누수를 차단한다
pipe = Pipeline([
    ("impute", SimpleImputer(strategy="median")),
    ("scale", StandardScaler()),
    ("clf", LogisticRegression()),
])
 
# 각 fold의 전처리가 학습 부분에만 fit된다
scores = cross_val_score(pipe, X, y, cv=5)

⚠️ 함정: "전체 데이터로 스케일링한 뒤 분할하면 안 되나?"는 헷갈리기 쉬운 문제다. 안 된다. StandardScaler가 전체 데이터로 fit되면 테스트 통계가 학습 스케일에 새어 검증 점수가 낙관적으로 부풀려진다. 학습 부분에만 fit, 테스트에는 transform만 적용해야 한다. 교차검증에서는 Pipeline이 이 규칙을 fold마다 자동으로 강제한다.

누수와 지표: 왜 "너무 좋은 점수"가 위험 신호인가

관찰된 지표 패턴그럴듯한 원인확인할 것
불균형 데이터인데 accuracy 99%다수 클래스만 맞히는 착시(누수가 아닐 수도)PR-AUC·recall로 다시 본다
PR-AUC·recall까지 전부 완벽누수 가능성 高단일 피처 기여도, 피처 생성 시점
ROC-AUC ≈ 1.0타깃을 그대로 담은 피처 존재 의심피처-타깃 상관 상위 목록
검증 점수 분산이 거의 0fold 간 정보 공유(중복·그룹 누수)중복 행, 그룹 ID 분포
재학습마다 점수가 크게 흔들림누수보다는 데이터 부족·분할 불안정k-fold로 평균·분산 확인

불균형 데이터에서 accuracy가 높은 것은 누수가 아니라 다수 클래스 편향일 수 있다. 두 원인을 구분하려면 소수 클래스 지표(recall, PR-AUC)를 봐야 한다. accuracy만 보고 "누수다"라고 단정하는 것도, "정상이다"라고 안심하는 것도 둘 다 틀린다.

데이터 누수 예방 체크리스트

실무에서 누수를 막는 일관된 절차:

  1. 먼저 분할: 어떤 전처리보다 train/test 분할을 먼저 한다
  2. 학습 부분만 fit: 스케일러·인코더·대치기는 학습 부분에만 fit
  3. Pipeline 사용: 교차검증 루프 안쪽에 전처리를 가둔다
  4. 시계열은 시간 순 분할: 무작위 분할 금지, lag/rolling은 과거만 참조
  5. 피처 생성 시점 감사: 각 피처가 예측 시점에 알 수 있는 값인지 확인한다
  6. 높은 검증 점수를 의심: 점수가 너무 좋으면 누수를 먼저 의심한다
  7. 그룹·중복 정리: 같은 사용자·중복 레코드는 분할 전에 처리한다

AWS 서비스 매핑표

상황AWS 서비스·기능이유
전처리 로직을 학습·추론에서 동일하게 고정SageMaker Processing Job + 저장된 전처리 스크립트노트북 즉흥 전처리를 없애 training-serving skew와 누수를 함께 줄인다
피처 정의와 값을 중앙에서 관리SageMaker Feature Store학습·추론이 같은 피처 정의를 공유해 시점 불일치를 줄인다
전처리→학습→평가를 단계로 묶어 재현SageMaker Pipelines단계 순서가 코드로 고정돼 "분할 전 전처리" 실수를 구조적으로 막는다
운영 중 입력 분포가 학습 때와 달라졌는지 감시SageMaker Model Monitor검증-운영 성능 괴리를 조기에 포착한다
어떤 피처가 예측을 지배하는지 확인SageMaker Clarify (특성 기여도)단일 피처가 예측을 독점하면 타깃 누수 신호다
데이터 변환 이력을 시각적으로 추적SageMaker Data Wrangler어떤 변환이 언제 적용됐는지 흐름으로 남겨 감사할 수 있다

지문 단서 → 정답 매핑표

지문 표현읽어야 할 신호고를 답
"검증도 테스트도 높은데 운영만 낮다"분할로 안 잡히는 누수타깃 누수
"검증은 높은데 테스트부터 낮다"전처리 오염분할 후 학습 부분만 fit
"시계열을 섞어서 나눴다"시간 역행시간 순 분할(forward-chaining)
"전체 데이터로 스케일링한 뒤 분할했다"테스트 통계 유입Pipeline으로 fold 내부 fit
"한 피처만 빼면 성능이 무너진다"답을 담은 피처그 피처의 생성 시점 감사
"같은 환자의 여러 검사 기록이 있다"그룹 구조GroupKFold, 그룹 단위 분할
"분할 전에 SMOTE로 균형을 맞췄다"합성 샘플이 양쪽에 걸침학습 부분에만 리샘플링
"해지 사유 코드가 가장 중요한 피처다"결과 이후 생성 값타깃 누수, 피처 제거

다음 글은 이 원칙들의 실전편 — 검증 설계: 분할, 교차검증, 층화, 시계열 분할을 다룬다.

📖 용어

  • 데이터 누수(data leakage) : 예측 시점에는 알 수 없었을 정보가 학습에 흘러들어 성능이 부풀려지는 사고.
  • 타깃 누수(target leakage) : 예측 대상의 결과 정보가 피처 안에 들어 있는 누수. 분할로는 잡히지 않는다.
  • train-test 오염 : 분할 전에 전체 데이터로 전처리해 테스트 정보가 학습에 새는 현상.
  • 시계열 누수 : 미래 데이터를 써서 과거를 예측하게 되는 누수. 무작위 분할이 주범이다.
  • 그룹 누수 : 같은 사용자·환자의 행이 학습과 검증에 나뉘어 들어가 성능이 과대평가되는 현상.
  • forward-chaining : 항상 과거로 학습하고 미래로 평가하는 시계열 검증 방식.
  • shift 후 rolling : 현재 행을 제외하고 과거 값만으로 이동 통계를 계산해 누수를 막는 기법.
  • Pipeline : 전처리와 모델을 하나로 묶어, 각 fold의 학습 부분에서만 fit이 일어나도록 강제하는 구조.
  • fit / transform 구분 : 통계를 학습하는 단계(fit)와 그 통계를 적용하는 단계(transform). 테스트에는 transform만 쓴다.
  • 검증셋 독립성 : 검증 점수가 일반화 성능을 추정하려면 검증 데이터가 학습 과정과 완전히 분리돼야 한다는 원칙.

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

이탈 예측 모델에서 한 특성 해지_사유_코드의 중요도가 비정상적으로 높고 검증 정확도가 99%였다. 이 현상의 가장 유력한 원인은?

문제 2

일별 매출 시계열을 무작위로 섞어 train/test를 나눴더니 검증 점수가 매우 높았지만 실제 미래 예측은 형편없었다. 올바른 조치는?

문제 3

scikit-learn에서 전처리(스케일링·대치)를 교차검증 시 누수 없이 적용하는 가장 안전한 방법은?

문제 4

다음 중 train/validation/test 분할을 깨끗이 해도 탐지되지 않는 누수 유형은?

문제 5

시계열 모델에서 최근 7일 이동평균 특성을 만들 때 누수를 피하는 올바른 방법은?

이전상관관계 분석: 상관계수·상관과 인과의 차이·다변량 관계Week 5 · Day 2다음 검증 설계: 학습/검증/테스트 분할·교차 검증·시계열 분할·층화 샘플링Week 5 · Day 4

참고 공식 자료

  • MLS-C01 공식 시험 안내(새 탭에서 열림)
  • Amazon SageMaker AI 공식 문서(새 탭에서 열림)

이 페이지

  • 데이터 누수란 무엇인가
  • 누수 유형 → 증상 → 탐지 → 예방 (핵심 표)
  • 타깃 누수: 미래·결과 정보가 섞여 든다
  • 누수 의심 신호표
  • 시계열 누수: 미래가 과거로 새어 든다
  • train-test 오염: 전처리를 통한 누수
  • 누수와 지표: 왜 "너무 좋은 점수"가 위험 신호인가
  • 데이터 누수 예방 체크리스트
  • AWS 서비스 매핑표
  • 지문 단서 → 정답 매핑표
  • 용어
  • 연습 문제