IT·AI

교차검증과 데이터 누수로 모델 평가가 잘못되는 원인과 해결 방법

2026-10-19 00:37
교차검증과 데이터 누수로 모델 평가가 잘못되는 원인과 해결 방법 representative image

교차검증과 데이터 누수 문제는 모델 자체보다 평가 절차 때문에 성능이 부풀려지는 대표적인 원인입니다. 특히 전체 데이터로 스케일링·결측치 대체·특징 선택을 먼저 한 뒤 교차검증을 수행하면 검증 데이터의 정보가 학습 과정에 섞일 수 있습니다.


📌 핵심 5줄 요약

1. 교차검증은 여러 훈련·검증 분할을 사용해 모델의 일반화 성능을 추정하는 방법입니다.

2. 데이터 누수는 예측 시점에 알 수 없는 정보가 학습이나 평가 과정에 들어가는 현상입니다.

3. 스케일링, 결측치 처리, 특징 선택은 전체 데이터가 아니라 각 훈련 폴드에 맞춰 학습해야 합니다.

4. 전처리와 모델을 Pipeline으로 묶으면 교차검증 과정에서 누수를 줄이기 쉽습니다.

5. 사용자·환자·장비·날짜가 겹치는 데이터는 일반 K-Fold보다 그룹 또는 시간 기준 분할이 적합할 수 있습니다.


📌 목차

01 | 교차검증은 무엇을 평가하는가

02 | 데이터 누수의 정확한 의미

03 | 모델 평가가 부풀려지는 구조

04 | 전처리에서 발생하는 누수

05 | 특징 선택과 피처 엔지니어링 누수

06 | 하이퍼파라미터 튜닝과 테스트셋 오염

07 | 중복 샘플과 그룹 누수

08 | 시계열 데이터의 시간 누수

09 | 분류 문제의 교차검증 선택

10 | Pipeline으로 안전하게 구성하기

11 | 잘못된 평가 코드와 올바른 코드

12 | 누수를 찾는 점검 방법

13 | 실무 평가 설계 순서

14 | 결과를 해석할 때 주의할 점


01 | 교차검증은 무엇을 평가하는가

교차검증은 하나의 데이터셋을 여러 번 훈련 집합과 검증 집합으로 나누어 모델 성능을 확인하는 방법입니다. 대표적인 K-Fold 방식에서는 데이터를 K개 폴드로 나누고, 한 폴드를 검증용으로 사용하는 과정을 반복합니다.

목적은 학습 데이터에만 잘 맞는지 확인하는 것이 아니라, 모델이 보지 못한 데이터에도 얼마나 잘 일반화되는지 추정하는 데 있습니다. 같은 데이터로 학습과 평가를 동시에 하면 이미 본 정답을 외우는 모델도 높은 점수를 받을 수 있으므로 평가가 왜곡됩니다.


02 | 데이터 누수의 정확한 의미

데이터 누수는 모델이 실제 예측 시점에는 이용할 수 없는 정보를 학습 또는 평가 과정에서 간접적으로 사용하는 현상입니다. 누수는 반드시 정답 열을 직접 넣어야만 발생하는 것이 아닙니다.

검증 데이터의 평균·분산·분포·정답과 관련된 통계가 전처리나 변수 생성 과정에 포함되어도 누수가 될 수 있습니다. 그 결과 교차검증 점수는 좋아 보이지만, 새로운 데이터나 실제 운영 환경에서는 성능이 크게 낮아질 수 있습니다.


03 | 모델 평가가 부풀려지는 구조

안전한 평가에서는 먼저 최종 테스트셋을 별도로 보관하고, 나머지 개발 데이터 안에서 전처리·모델 선택·하이퍼파라미터 탐색을 진행합니다. 마지막에 한 번만 테스트셋을 사용해 최종 성능을 확인하는 방식입니다.

반대로 전체 데이터에 전처리를 적용한 뒤 교차검증을 수행하면 각 검증 폴드의 정보가 전처리 통계에 반영됩니다. 또 테스트셋 점수를 여러 번 확인하면서 모델과 변수 구성을 계속 바꾸면 테스트셋이 사실상 튜닝 데이터로 변합니다. scikit-learn 문서도 테스트 데이터로 모델 선택을 반복하면 일반화 성능을 과대평가할 위험이 있다고 설명합니다.


04 | 전처리에서 발생하는 누수

가장 흔한 사례는 전체 데이터에 fit_transform()을 적용한 뒤 교차검증하는 것입니다. 표준화라면 전체 평균과 표준편차를 사용하게 되고, 결측치 대체라면 검증 폴드의 값이 대체 기준 계산에 들어갈 수 있습니다.

올바른 방식은 각 반복에서 훈련 폴드에만 fit을 수행하고, 검증 폴드에는 학습된 변환을 transform만 적용하는 것입니다. 스케일링, 결측치 처리, PCA, 특징 선택 등 여러 변환에 같은 원칙이 적용됩니다.


05 | 특징 선택과 피처 엔지니어링 누수

상관관계가 높은 변수를 고르거나, 통계 검정으로 유의한 특징을 선별하거나, 차원 축소를 수행할 때도 검증 데이터가 포함되면 누수가 발생할 수 있습니다.

예를 들어 전체 데이터와 정답을 이용해 상위 특징을 먼저 고른 다음 교차검증하면 검증 폴드의 정답 정보가 변수 선택에 반영됩니다. 변수 선택 자체도 모델 학습의 일부로 보고 각 훈련 폴드 안에서 다시 수행해야 합니다.

미래 정보를 이용해 만든 변수도 주의해야 합니다. 예측일 이후에 발생한 거래 결과, 사후 확정된 등급, 미래 기간의 평균값이 현재 시점의 입력 변수에 포함되면 시간 누수에 해당합니다.


06 | 하이퍼파라미터 튜닝과 테스트셋 오염

교차검증은 모델의 하이퍼파라미터를 선택하는 데 사용할 수 있지만, 선택이 끝난 뒤에는 별도의 테스트셋으로 최종 평가하는 것이 안전합니다.

테스트 점수를 확인한 뒤 학습률, 트리 깊이, 특징 목록, 데이터 처리 방법을 바꾸고 다시 테스트하면 테스트셋에 간접적으로 맞춘 결과가 됩니다. 이 경우 테스트 점수는 더 이상 완전히 새로운 데이터에 대한 객관적인 평가가 아닙니다.

데이터가 충분하다면 개발용 데이터와 최종 테스트셋을 분리하고, 개발용 데이터에서 교차검증과 탐색을 끝낸 뒤 테스트셋을 한 번만 사용하세요.


07 | 중복 샘플과 그룹 누수

같은 사람, 같은 상품, 같은 장비, 같은 문서에서 파생된 샘플이 서로 다른 폴드에 나뉘면 모델이 새로운 대상을 예측하는 것이 아니라 이미 본 대상의 특징을 재사용하게 될 수 있습니다.

예를 들어 한 사용자의 여러 기록이 훈련 폴드와 검증 폴드에 동시에 들어가면 사용자별 고유 패턴을 학습해 점수가 높아질 수 있습니다. 새로운 사용자 성능이 목표라면 사용자 ID를 그룹으로 묶고 한 그룹이 여러 폴드에 흩어지지 않도록 해야 합니다.

이때 GroupKFold 같은 그룹 기반 분할을 고려할 수 있습니다. scikit-learn 문서도 동일한 그룹의 샘플을 훈련과 검증에 함께 넣으면 새로운 그룹에 대한 성능보다 좋은 결과가 나올 수 있다고 설명합니다.


08 | 시계열 데이터의 시간 누수

시계열에서는 무작위로 섞어 K-Fold를 적용하면 미래 데이터로 과거를 예측하는 구조가 만들어질 수 있습니다. 예측 시점 이후에 수집된 값이나 미래 기간의 통계가 훈련 데이터에 들어가면 실제 운영 상황과 다른 평가가 됩니다.

주가·수요·센서·로그처럼 시간 순서가 중요한 데이터는 과거로 학습하고 이후 기간으로 검증하는 방식이 적합합니다. 특징을 만들 때도 각 행의 기준 시점에서 실제로 이용 가능했는지 확인해야 합니다.

시간이 지나면서 분포가 변하는 문제라면 한 번의 평균 점수보다 기간별 성능, 최근 구간 성능, 시간에 따른 오차 변화를 함께 확인하는 편이 실용적입니다.


09 | 분류 문제의 교차검증 선택

분류 데이터의 클래스 비율이 불균형하다면 일반 K-Fold보다 각 폴드의 클래스 비율을 유지하는 StratifiedKFold가 적합할 수 있습니다. 다만 같은 그룹이 여러 폴드에 들어가면 층화만으로는 그룹 누수를 해결할 수 없습니다.

따라서 분할 방식은 데이터의 생성 구조와 목표에 맞춰 선택해야 합니다.

상황우선 검토할 분할 방식
독립적인 일반 샘플K-Fold
클래스 비율이 불균형한 분류StratifiedKFold
사용자·환자·장비별 묶음 존재GroupKFold 계열
시간 순서가 중요한 데이터시간 순서 기반 분할
그룹과 클래스 비율을 함께 고려그룹·층화 조건을 함께 만족하는 분할 전략

10 | Pipeline으로 안전하게 구성하기

전처리와 모델을 하나의 Pipeline으로 묶으면 교차검증의 각 훈련 폴드에서 전처리 학습과 모델 학습이 함께 수행됩니다. 이렇게 하면 전체 데이터로 변환기를 먼저 학습하는 실수를 줄일 수 있습니다.

일반적인 구조는 결측치 처리, 범주형·수치형 변환, 특징 선택, 최종 모델을 순서대로 Pipeline 또는 ColumnTransformer 안에 넣는 방식입니다. 하이퍼파라미터 탐색도 개별 모델이 아니라 전체 파이프라인을 대상으로 수행해야 전처리 설정까지 평가 절차에 포함됩니다.

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

model = Pipeline([
("scale", StandardScaler()),
("classifier", LogisticRegression())
])

scores = cross_val_score(model, X, y, cv=5)

코드의 핵심은 StandardScaler를 전체 데이터에 따로 적용하지 않고 Pipeline 안에 넣는 것입니다.


11 | 잘못된 평가 코드와 올바른 코드

잘못된 흐름

X_scaled = scaler.fit_transform(X)처럼 전체 입력 데이터에 먼저 적합한 뒤 cross_val_score(model, X_scaled, y)를 실행하는 방식입니다. 전처리 통계가 모든 샘플을 사용하므로 검증 폴드의 정보가 훈련 과정에 섞일 수 있습니다.

올바른 흐름

Pipeline([("scale", scaler), ("model", estimator)])처럼 전처리와 모델을 묶고, 원본 X를 Pipeline에 전달합니다. 그러면 각 교차검증 반복에서 전처리 단계도 훈련 폴드 기준으로 새로 학습됩니다.

특징 선택, 이상치 제거 기준, 목표 인코딩, 텍스트 어휘 사전 생성도 같은 원칙으로 Pipeline 내부에 포함해야 합니다.


12 | 누수를 찾는 점검 방법

교차검증 점수가 비정상적으로 높거나 운영 성능과 큰 차이가 난다면 다음 항목을 순서대로 확인하세요.

  • 전처리 객체가 전체 데이터에 먼저 fit되지 않았는가
  • 정답 또는 정답 생성 이후의 값이 입력 변수에 포함되지 않았는가
  • 동일한 사용자·환자·장비·문서가 훈련과 검증에 함께 들어가지 않았는가
  • 시간 순서를 무시하고 데이터를 무작위로 섞지 않았는가
  • 테스트셋 점수를 본 뒤 모델 구성을 반복 수정하지 않았는가
  • 중복 행이나 거의 동일한 파생 샘플이 분할 경계를 넘지 않았는가

가장 강력한 검증은 실제 배포 상황을 모사하는 별도 평가입니다. 새로운 사용자, 새로운 기간, 새로운 장비처럼 실제로 마주할 대상이 검증셋에 반영되어야 합니다.


13 | 실무 평가 설계 순서

첫째, 모델이 운영 환경에서 언제 어떤 정보를 이용할 수 있는지 정의합니다. 둘째, 데이터의 독립 단위가 행인지 사용자·기간·장비인지 결정합니다. 셋째, 그 단위에 맞는 분할 방식을 선택합니다.

넷째, 최종 테스트셋을 먼저 분리하고 보관합니다. 다섯째, 전처리·특징 생성·모델·하이퍼파라미터 탐색을 개발 데이터 안에서 수행합니다. 여섯째, 교차검증 평균뿐 아니라 폴드별 편차와 각 하위 집단의 성능을 확인합니다.

마지막으로 모델과 전처리 과정을 고정한 뒤 테스트셋을 한 번 평가합니다. 테스트 결과가 예상보다 크게 낮다면 모델을 무조건 수정하기보다 먼저 누수와 분할 방식부터 재검토해야 합니다.


14 | 결과를 해석할 때 주의할 점

교차검증 평균 점수 하나만으로 모델의 품질을 판단하면 안 됩니다. 데이터가 적거나 폴드마다 분포가 크게 다르면 점수의 변동성이 커질 수 있고, 평균이 비슷해도 특정 그룹이나 기간에서 성능이 크게 떨어질 수 있습니다.

정확도 외에도 문제에 맞는 평가지표를 선택해야 합니다. 불균형 분류에서는 정밀도·재현율·F1·ROC-AUC·PR-AUC 등을 목적에 맞게 검토하고, 회귀에서는 평균 절대 오차나 제곱근 평균 제곱 오차처럼 실제 비용과 연결되는 지표를 확인합니다.

또한 교차검증 점수는 모델이 미래나 새로운 그룹에서 반드시 같은 성능을 낸다는 보증이 아닙니다. 평가 설계가 실제 사용 조건을 얼마나 충실하게 재현했는지가 점수 자체보다 중요합니다.


☑ 체크리스트

  • 최종 테스트셋을 모델 개발 전에 별도로 분리했는가
  • 스케일링과 결측치 처리를 Pipeline 안에서 수행했는가
  • 특징 선택과 피처 엔지니어링이 각 훈련 폴드 안에서 실행되는가
  • 동일한 사용자·그룹·장비가 여러 폴드에 나뉘지 않았는가
  • 시간 순서를 지켜 과거 데이터로 미래를 평가했는가
  • 테스트셋 점수를 확인한 뒤 반복적으로 모델을 수정하지 않았는가
  • 평균 점수뿐 아니라 폴드별 편차와 실제 운영 조건을 함께 검토했는가

📖 자주하는 질문 Q&A

전처리를 먼저 하고 교차검증하면 항상 데이터 누수인가요?

전체 데이터의 통계나 정답 정보를 사용해 전처리 기준을 학습했다면 누수 위험이 있습니다. 단순히 고정된 규칙으로 변환하는 과정과 데이터에서 평균·분산·범주 목록을 학습하는 과정은 구분해야 하며, 후자는 보통 Pipeline 안에서 처리하는 것이 안전합니다.

교차검증을 사용하면 테스트셋이 없어도 되나요?

모델 선택과 튜닝에는 교차검증을 사용할 수 있지만, 최종적으로 완전히 보지 않은 데이터를 이용한 확인이 필요하다면 별도의 테스트셋을 두는 편이 좋습니다. 특히 여러 번 모델을 수정하는 프로젝트에서는 테스트셋을 보존해야 합니다.

데이터 누수와 과적합은 같은 문제인가요?

같지는 않습니다. 과적합은 학습 데이터의 특성에 지나치게 맞는 현상이고, 데이터 누수는 평가 또는 학습 과정에 허용되지 않은 정보가 들어가는 문제입니다. 누수는 과적합이 없어 보이는 모델에서도 평가 점수를 부풀릴 수 있습니다.

무작위 K-Fold를 사용하면 안 되는 데이터는 무엇인가요?

시간 순서가 중요한 데이터, 동일 대상의 반복 측정값이 많은 데이터, 그룹 간 독립성이 없는 데이터에서는 무작위 K-Fold가 실제 성능을 과대평가할 수 있습니다. 이 경우 시간 기반 또는 그룹 기반 분할을 우선 검토해야 합니다.


📝 마무리

교차검증의 핵심은 폴드 개수보다 검증 데이터가 학습 과정에 섞이지 않도록 평가 흐름을 설계하는 데 있습니다. 데이터 분할을 먼저 하고, 전처리·특징 선택·튜닝을 훈련 폴드 안에서만 수행하며, 실제 운영 조건에 맞는 그룹·시간 기준을 적용해야 모델 평가를 신뢰할 수 있습니다.

#교차검증 #데이터누수 #모델평가 #머신러닝 #기계학습 #인공지능 #모델검증 #검증데이터 #훈련데이터 #테스트데이터 #검증셋 #교차검증방법 #케이폴드 #KFold #StratifiedKFold #GroupKFold #시계열검증 #데이터전처리 #특징선택 #피처엔지니어링 #스케일링 #결측치처리 #하이퍼파라미터튜닝 #파이프라인 #Pipeline #과적합 #일반화성능 #평가지표 #모델개발 #머신러닝실수