ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학습·테스트를 나눴는데도 점수가 과하게 좋은 이유
    AI Agent 2026. 9. 21. 12:28
    728x90
    반응형
    나무 경계 양쪽의 파란 블록과 주황 블록, 파란 쪽에 놓인 측정 도구
    학습 자료에서 규칙을 맞추고 별도 자료로 평가하는 구분을 표현한 AI 생성 개념 이미지입니다.

    전처리의 fit에 테스트 자료가 들어갔는지 확인하고, 분할 안에서 학습되는 Pipeline으로 평가 절차를 구성하세요.

    학습 자료와 테스트 자료를 나눴는데도 점수가 지나치게 좋아 보인다면, 분할 코드 앞에서 무엇을 했는지 살펴볼 필요가 있습니다. 모델의 fit에는 학습 자료만 넣었어도 전처리의 평균·분산이나 특징 선택 기준을 전체 자료에서 구했다면 테스트 정보가 먼저 들어갔을 수 있습니다.

    데이터 누수는 정답 열을 그대로 입력한 경우만 뜻하지 않습니다. 실제 예측 시점에는 알 수 없을 정보를 모델이나 처리 규칙을 만드는 데 사용했는지가 핵심입니다. 점수가 높다는 이유만으로 누수를 확정할 수는 없지만, 평가 경로는 확인할 수 있습니다.

    이 글은 2026년 9월 16일 확인한 scikit-learn 1.9.1 문서를 기준으로 합니다. 실제 모델 학습이나 점수 비교는 하지 않았습니다. 아래 숫자는 정보가 섞이는 지점을 보여 주는 가상 계산이며 성능 측정값이 아닙니다.

    분할하기 전에 계산한 평균에도 테스트 정보가 들어갑니다

    가상으로 학습에 사용할 값이 2와 4이고 테스트 값이 100이라고 해보겠습니다. 학습 값만의 평균은 3입니다. 세 값을 함께 쓰면 평균은 약 35.33이 됩니다.

    어느 평균으로 중심을 옮기느냐에 따라 학습 자료의 표현이 달라집니다. 전체 평균을 썼다면 학습 단계의 변환 기준에 테스트 값 100이 영향을 준 것입니다. 정답 레이블을 읽지 않았더라도 정보의 경계가 달라졌습니다.

    이 예시는 평균만 비교한 간단한 계산입니다. StandardScaler의 전체 처리나 실제 모델 점수가 얼마나 바뀌는지를 계산한 것은 아닙니다. 누수를 찾기 위해 반드시 성능이 오른 결과를 먼저 보여야 하는 것도 아닙니다.

    scikit-learn은 전처리 규칙을 학습 자료에서만 배워야 하며, 예를 들어 정규화에 쓰는 평균도 전체 자료가 아닌 학습 집합에서 구해야 한다고 설명합니다. 전처리의 데이터 누수

    fit과 transform은 다른 일을 합니다

    StandardScaler를 예로 들면 fit은 자료에서 평균·분산 같은 변환 기준을 학습하고, transform은 이미 정한 기준을 자료에 적용합니다. 학습에서 구한 기준을 나중 자료에도 적용하는 구조입니다. StandardScaler의 학습과 변환

    따라서 테스트 자료를 전처리하면 안 된다는 뜻은 아닙니다. 테스트에도 같은 변환을 적용해야 하지만, 테스트 자료를 이용해 그 변환을 다시 학습해서는 안 된다는 뜻입니다.

    가상 흐름을 비교하면 차이가 분명합니다.

    문제가 되는 순서:
    전체 X로 전처리 fit_transform
    → 변환된 자료를 학습·테스트로 분할
    → 모델 학습·평가
    
    검토할 순서:
    원본 X를 학습·테스트로 분할
    → 학습 X로 전처리 fit
    → 같은 전처리로 학습·테스트 transform
    → 모델 학습·평가

    두 번째 순서에서 테스트 자료를 별도로 fit하면 학습과 다른 기준을 적용하게 됩니다. 학습·테스트에 같은 절차를 쓴다는 말은 각자 자기 평균을 구하라는 뜻이 아닙니다.

    정답을 보지 않는 전처리도 점검 대상입니다

    레이블을 사용하지 않는 변환이라도 테스트 자료의 분포를 학습할 수 있습니다. 평균·분산 계산, 결측값 대체 기준, 차원 축소처럼 자료에서 규칙을 추정하는 단계가 대표적인 점검 대상입니다.

    특징 선택처럼 정답을 직접 사용하는 처리라면 경계가 더 분명합니다. 전체 자료를 보고 좋은 특징을 고른 뒤 테스트로 나누면, 평가할 자료가 이미 선택 과정에 관여한 것입니다. scikit-learn은 이런 사례와 Pipeline 사용을 함께 설명합니다. 전처리 누수의 사례

    그렇다고 모든 전처리가 반드시 분할마다 학습해야 하는 통계 연산이라는 뜻은 아닙니다. 자료를 보고 값을 정하는 단계인지, 이미 정해진 변환을 적용하는 단계인지 구분해야 합니다. 중요한 것은 함수 이름보다 어떤 정보로 규칙을 만들었는가입니다.

    가상의 평가 기록에서는 각 처리 단계 옆에 fit에 들어간 자료 범위를 적어 볼 수 있습니다. ‘정규화함’이라는 한 줄보다 ‘학습 집합에서 계산한 평균을 테스트에도 적용함’이 훨씬 정확합니다.

    Pipeline은 전처리를 평가 절차 안에 두는 방법입니다

    Pipeline은 전처리와 모델을 하나의 학습·예측 절차로 묶을 수 있습니다. 이를 교차 검증 함수에 넘기면 각 분할의 학습 부분에서 필요한 fit이 이뤄지는 구조를 만들 수 있습니다.

    핵심은 Pipeline 자체를 분할 안에서 학습시키는 것입니다. 전체 자료를 먼저 전처리한 뒤 모델만 Pipeline에 넣어도 이미 들어간 테스트 정보가 사라지지는 않습니다.

    가상 분류 데이터 X, y가 준비돼 있다고 가정한 예시는 다음과 같습니다.

    from sklearn.model_selection import train_test_split
    from sklearn.model_selection import StratifiedKFold, cross_val_score
    from sklearn.preprocessing import StandardScaler
    from sklearn.linear_model import LogisticRegression
    from sklearn.pipeline import make_pipeline
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, stratify=y, random_state=17
    )
    
    pipeline = make_pipeline(
        StandardScaler(),
        LogisticRegression(max_iter=1000),
    )
    
    cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=17)
    cv_scores = cross_val_score(
        pipeline, X_train, y_train, cv=cv, scoring="accuracy"
    )
    
    pipeline.fit(X_train, y_train)
    test_score = pipeline.score(X_test, y_test)

    코드의 X와 y는 실제 자료로 준비해야 하는 입력입니다. 클래스별 표본이 분할과 교차 검증을 수행하기에 충분하고, 독립 표본의 분류 문제라는 가정이 있습니다. 시간·그룹 구조가 있는 자료에 그대로 적용하는 만능 평가 코드가 아닙니다.

    이 글에서는 실행하지 않았으므로 cv_scores나 test_score의 숫자를 제시하지 않습니다. 설명하려는 것은 전처리와 모델이 어디에서 fit되는지입니다.

    교차 검증에서도 검증 fold는 학습에서 제외합니다

    교차 검증은 학습 집합을 다시 여러 부분으로 나눠 평가합니다. 따라서 최종 테스트 집합을 빼뒀더라도, 교차 검증에 넣을 전체 학습 자료로 전처리를 한 번 fit한 뒤 나누면 각 검증 fold의 정보가 앞서 들어갈 수 있습니다.

    앞의 예시는 전처리와 모델을 묶은 pipeline을 cross_val_score에 전달합니다. 이 구조에서 fold별 학습 자료로 변환 기준과 모델을 맞추고, 해당 검증 부분에는 그 기준을 적용하게 됩니다. Pipeline과 교차 검증

    최종 테스트는 그와 별도로 둡니다. 설정 선택에 테스트 점수를 계속 사용하면 이름이 test인 변수에 들어 있어도 독립된 마지막 평가 역할을 유지하지 못합니다.

    실제로는 모델과 하이퍼파라미터를 선택하는 검증 절차를 먼저 정하고, 마지막 확인용 자료를 언제 사용할지 명시해야 합니다. 코드 한 줄로 train과 test를 나눈 사실보다 자료가 의사결정에 쓰인 경로가 중요합니다.

    같은 사람·같은 시간대의 자료가 양쪽에 섞이는지도 봅니다

    Pipeline이 전처리 누수를 줄여 주더라도 분할 설계의 모든 문제를 해결하지는 않습니다. 같은 대상의 거의 같은 기록이 학습과 테스트 양쪽에 있으면, 실제로 처음 보는 대상에서의 성능을 평가하려던 목적과 어긋날 수 있습니다.

    가령 가상의 한 기기에서 반복 수집한 행이 많다면 행 단위 무작위 분할만으로 충분한지 검토해야 합니다. 평가하려는 대상이 새 기기인지, 같은 기기의 새 시점인지에 따라 분할 단위가 달라집니다.

    시간 순서가 중요한 문제에서는 미래 자료가 과거 예측의 학습에 섞이지 않는지도 봅니다. scikit-learn의 교차 검증 안내는 그룹과 시계열 자료에 맞는 분할을 별도로 다룹니다. 자료 구조에 맞는 교차 검증

    또한 결과가 나온 뒤에만 알 수 있는 열을 특징으로 사용하는 문제는 전처리 Pipeline 안팎과 별개입니다. 실제 예측 시점에 그 정보를 얻을 수 있는지 확인해야 합니다. Pipeline이 있다는 이유로 이런 누수까지 없다고 판정하지 않습니다.

    높은 점수의 원인을 하나로 단정하지 않습니다

    평가 점수가 좋다는 사실만으로 누수라고 말할 수는 없습니다. 문제가 쉬울 수도 있고, 자료가 실제 사용 범위를 충분히 대표하지 못할 수도 있으며, 지표 선택의 문제일 수도 있습니다.

    반대로 누수를 고친 뒤 점수가 크게 떨어지지 않았다고 기존 경로가 올바른 것은 아닙니다. 특정 자료와 모델에서는 그 영향이 작게 나타날 수도 있습니다. 정보가 어디에 사용됐는지와 관찰한 점수 변화는 구분해야 합니다.

    가상의 점검에서는 분할 전 fit 호출, 특징 선택, 결측 처리, 같은 대상의 중복, 시간 경계, 평가 결과를 이용한 반복 선택을 하나씩 확인합니다. 발견한 문제와 아직 확인하지 않은 문제를 나누어 기록합니다.

    수정 결과를 보고할 때는 동일한 평가 조건에서 어떤 경로를 바꿨는지 남깁니다. 점수가 낮아졌으니 이제 정직하다는 식의 결론보다, 테스트 정보가 학습 규칙에 들어가지 않는 구조를 확인한 것이 더 중요한 근거입니다.

    마지막에는 점수와 함께 평가 절차를 남기세요

    평가를 공유할 때는 원본 자료의 범위, 분할 단위, 전처리의 fit 위치, 교차 검증 방식, 마지막 테스트의 사용 시점을 함께 적습니다. 점수 하나만 있으면 독자가 무엇을 검증한 결과인지 알 수 없습니다.

    학습·테스트를 나눴는데 결과가 의심스럽다면 분할 줄 앞의 처리부터 확인하세요. 원본을 먼저 나누고, 학습이 필요한 전처리를 Pipeline 안에 두어 분할마다 맞춘 뒤, 시간·그룹·중복과 정보 시점을 추가로 검수하면 됩니다.

    완료 기준은 점수를 낮추는 것이 아닙니다. 실제로 예측할 때 알 수 있는 정보만으로 만든 규칙을, 그 규칙을 만드는 데 쓰지 않은 자료에서 평가했는지 확인하는 것입니다. 그 경로를 설명할 수 있어야 좋은 점수도 의미 있게 읽을 수 있습니다.

    728x90
    반응형
Designed by Tistory.