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 4

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

MLS-C01· AssociateWeek 5 · Day 4읽기 약 13분
핵심 정리
  • 테스트셋은 모든 결정이 끝날 때까지 봉인하고 단 한 번만 본다. 보면서 고치는 순간 테스트셋은 검증셋이 된다.
  • 데이터가 적으면 k-fold 교차검증으로 모든 행을 검증에 쓰고 k개 점수의 평균 ± 표준편차를 본다(k=5 또는 10이 균형점).
  • 분류, 특히 클래스 불균형이면 층화(stratified)가 사실상 필수다. 각 분할에서 원본 클래스 비율을 유지한다.
  • 시계열은 TimeSeriesSplit. 학습 구간이 항상 검증 구간보다 과거여야 한다(forward-chaining).
  • 같은 사용자·환자의 행이 여럿이면 GroupKFold로 그룹 단위로 분할해야 성능이 부풀지 않는다.

Day 4 - 검증 설계: 학습/검증/테스트 분할·교차 검증·시계열 분할·층화 샘플링

왜 셋으로 나누는가: train / validation / test

어제는 누수가 검증을 어떻게 망치는지 봤다. 오늘은 그 거울상 — 누수 없이 검증을 설계해 모델의 일반화 성능을 정직하게 추정하는 일이다. 좋은 모델 선택은 결국 "본 적 없는 데이터에서 얼마나 잘할까?"를 믿을 만하게 추정하는 능력이고, 그 신뢰도는 전적으로 검증 설계에 달려 있다.

가장 기본은 데이터를 셋으로 나누는 것이다. 각각 역할이 다르다.

분할역할핵심사용 횟수
학습(training)모델 파라미터를 학습보통 60~80%로 가장 큰 비중매 학습마다
검증(validation)하이퍼파라미터 튜닝·모델 선택반복해서 본다여러 번
테스트(test)최종 성능 평가끝까지 봉인정확히 한 번

핵심 원칙: 테스트셋은 모든 결정이 끝날 때까지 봉인하고 정확히 한 번만 본다. 테스트 점수를 보고 모델을 수정하면 테스트셋이 사실상 검증셋이 되어 최종 추정치가 낙관적으로 오염된다.

from sklearn.model_selection import train_test_split
 
# 1차: train+val 대 test (테스트는 봉인)
X_temp, X_test, y_temp, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
# 2차: train 대 validation
X_train, X_val, y_train, y_val = train_test_split(
    X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp
)
# 결과: 60% / 20% / 20%

검증셋과 테스트셋을 분리하는 이유는 다중 비교 문제(multiple comparisons problem) 때문이다. 검증셋 위에서 수십 개 하이퍼파라미터 조합을 비교하면, 우연히 그 검증셋에 잘 맞는 조합이 선택되어 검증 점수에 "선택 편향"이 쌓인다. 그 점수는 더 이상 일반화 성능을 공정하게 추정하지 못한다. 그래서 모든 선택이 끝난 뒤, 한 번도 쓰지 않은 테스트셋에서 최종 성능을 잰다. 그때에야 추정이 정직해진다.

세 분할의 역할 구분표

질문학습셋검증셋테스트셋
무엇을 결정하는가모델 파라미터(가중치)하이퍼파라미터·알고리즘·피처아무것도 결정하지 않는다
몇 번 보는가제한 없음여러 번한 번
전처리 통계를 여기서 뽑는가그렇다아니다(transform만)아니다(transform만)
점수가 뜻하는 것적합도(과적합 진단용)선택을 위한 상대 비교값일반화 성능 추정치
오염되면 생기는 일과적합 감지 불가선택 편향 누적최종 보고 수치가 거짓이 된다

k-fold 교차검증: 데이터를 아낀다

단일 분할은 운에 좌우된다. 특히 데이터가 적으면 어떤 행이 검증에 들어가느냐가 점수를 크게 흔든다. k-fold 교차검증은 데이터를 k등분해 각각을 한 번씩 검증으로 쓰고 나머지로 학습하며, k번 반복한 점수를 평균한다.

5-fold 교차검증 (■ = 검증 fold, □ = 학습 fold)

Fold 1  ■ □ □ □ □   → score₁
Fold 2  □ ■ □ □ □   → score₂
Fold 3  □ □ ■ □ □   → score₃
Fold 4  □ □ □ ■ □   → score₄
Fold 5  □ □ □ □ ■   → score₅
                     ────────────────────
                     평균 ± 표준편차로 보고
                     (모든 행이 정확히 한 번 검증에 쓰인다)
방식설명적합한 상황
k-foldk등분, k회 반복(보통 k=5 또는 10)일반적인 기본값
Stratified k-fold각 fold에서 클래스 비율 유지분류, 특히 불균형
Leave-One-Out (LOO)k = n, 한 행씩 검증데이터가 극히 적을 때(비용 큼)
Repeated k-foldk-fold를 여러 번 반복추정 분산을 더 줄이고 싶을 때
GroupKFold같은 그룹은 한쪽에만 배치사용자·환자 등 그룹 구조
Nested CV바깥 fold로 평가, 안쪽 fold로 튜닝튜닝까지 포함한 정직한 성능 추정

교차검증의 이득: (1) 모든 행이 한 번씩 검증에 쓰여 데이터를 아끼고, (2) k개 점수의 평균과 분산을 얻어 성능의 안정성까지 볼 수 있다.

from sklearn.model_selection import StratifiedKFold, cross_val_score
 
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(pipe, X, y, cv=skf, scoring="f1")
print(f"F1: {scores.mean():.3f} ± {scores.std():.3f}")  # 평균 ± 표준편차

k 선택에는 편향-분산 트레이드오프가 있다. k가 작으면(예: 2-fold) 각 학습셋이 작아져 추정이 비관적으로 편향된다. k가 매우 크면(LOO, k=n) 학습셋이 거의 전체라 편향은 작지만 fold 결과가 서로 비슷해져 추정 분산이 커지고 계산량이 폭발한다. 경험적으로 k=5 또는 10이 편향·분산·비용의 균형점이라 널리 쓰인다.

k 값 트레이드오프표

k학습셋 크기편향분산계산 비용언제
2~3작다(50~67%)비관적으로 크다작다매우 낮음데이터가 아주 많고 빠른 확인만 필요할 때
580%작다보통낮음일반적 기본값
1090%더 작다보통~약간 큼중간데이터가 적당히 적고 정밀한 추정이 필요할 때
n (LOO)거의 전체거의 없음크다매우 높음데이터가 수십~수백 행 수준일 때

⚠️ 함정: "k를 키울수록 항상 좋다"는 오답이다. k가 커지면 계산 비용이 k에 비례해 늘고, 학습셋들이 거의 같아져 fold 점수 간 상관이 커지므로 평균 추정의 분산이 오히려 커진다.

층화 표집: 비율을 유지한다

클래스가 불균형한 분류(예: 사기 1%)에서 무작위 분할은 위험하다. 운이 나쁘면 검증에 소수 클래스가 거의 없거나 아예 0개일 수 있다. 층화 표집(stratified sampling)은 각 분할에서 원본 클래스 비율을 유지한다.

  • train_test_split(..., stratify=y): 분할 시 비율 유지
  • StratifiedKFold: 각 fold에서 비율 유지

분류에서는 층화가 거의 항상 권장되며, 불균형 데이터에서는 사실상 필수다. 회귀에서는 타깃을 구간(bin)으로 나눠 층화하기도 한다.

from sklearn.model_selection import train_test_split
 
# stratify=y로 원본 클래스 비율을 분할에 유지한다
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42
)
print(y_train.value_counts(normalize=True))  # 원본과 같은 비율인지 확인

⚠️ 함정: 불균형 데이터를 층화 없이 무작위 분할하면 어떤 fold에는 소수 클래스가 0개가 되어 F1·recall이 계산 불가하거나 왜곡된다. 분류에서 accuracy는 높은데 소수 클래스를 전혀 잡지 못한다면 층화 분할부터 확인한다.

불균형 데이터의 지표 해석표

층화로 분할을 고쳐도, 지표를 잘못 고르면 여전히 속는다.

지표무엇을 말하는가우선해야 할 상황함정
Accuracy전체적으로 자주 맞힘클래스가 균형일 때만양성 1%면 "전부 음성"으로도 99% — 불균형에서 무의미
Precision오탐이 적다오탐 비용이 큼(스팸 차단)소수만 양성으로 예측하면 쉽게 올라간다
Recall미탐이 적다미탐 비용이 큼(사기·질병)전부 양성으로 예측하면 1.0
F1precision·recall의 균형두 비용이 비슷할 때어느 쪽이 문제인지 감춘다
ROC-AUC임계값과 무관한 분별력임계값 미정, 모델 비교극단 불균형에서 지나치게 낙관적
PR-AUC소수 클래스 분별력양성 비율이 매우 낮을 때클래스 비율이 바뀌면 값도 바뀐다
RMSE큰 오차가 적다회귀, 큰 오차를 강하게 벌줄 때이상치에 민감
MAE평균적 오차가 작다회귀, 이상치에 강건해야 할 때큰 오차를 관대하게 본다

불균형 데이터에서 accuracy가 함정인 이유는 다수 클래스만 맞혀도 점수가 높기 때문이다. 검증 설계(층화)와 지표 선택(PR-AUC·recall)은 함께 고쳐야 한다. 둘 중 하나만 고치면 여전히 잘못된 모델을 고른다.

시계열 분할: 시간을 거스르지 않는다

Day 3에서 봤듯 시계열에 무작위 분할이나 일반 k-fold를 쓰면 미래가 과거로 샌다. 시계열에는 시간 순서를 지키는 분할이 필요하다.

방식설명특징
고정 분할(holdout)기준 시점을 정해 과거=학습, 미래=테스트가장 단순, 한 번만 평가
확장 윈도(expanding)학습 구간을 늘려가며 다음 구간 평가데이터를 모두 활용, 오래된 패턴도 반영
이동 윈도(rolling/sliding)고정 길이 학습 구간을 앞으로 밀며 평가최근 패턴 위주, 분포 변화에 대응

scikit-learn의 TimeSeriesSplit이 이 forward-chaining을 구현한다. 각 분할에서 학습은 항상 검증보다 과거다.

TimeSeriesSplit (확장 윈도, n_splits=4)
시간축 ──────────────────────────────────────────▶

Split 1  [■■■■]───[▨▨]  ·  ·  ·  ·        ■ 학습  ▨ 검증
Split 2  [■■■■ ■■]───[▨▨]  ·  ·
Split 3  [■■■■ ■■ ■■]───[▨▨]  ·
Split 4  [■■■■ ■■ ■■ ■■]───[▨▨]

  · 학습 구간은 매번 확장되고, 검증 구간은 항상 그 "다음" 시점
  · 실제 배포(과거 모델로 미래 예측)와 동일한 구조
from sklearn.model_selection import TimeSeriesSplit
 
# 시간 순 분할: 학습이 항상 검증보다 과거 (누수 차단)
tscv = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in tscv.split(X):
    # train_idx의 모든 시점 < test_idx의 시점
    X_tr, X_te = X.iloc[train_idx], X.iloc[test_idx]
    # 모델 학습/평가 ...

시계열 검증이 일반 교차검증과 다른 이유는 행 독립성 가정이 깨지기 때문이다. 일반 k-fold는 행이 서로 교환 가능하다고 가정하지만, 시계열에서는 순서 자체가 정보다. TimeSeriesSplit은 항상 "과거로 학습, 미래로 평가"를 유지해 실제 배포 상황(과거 모델로 미래를 예측)을 모사한다. 이 정렬 덕분에 검증 점수가 실제 운영 성능과 닮게 된다.

검증 전략 선택표

데이터 특성권장 검증이유
일반 분류, 데이터 충분층화 train/val/test 분할단순하고 빠르며 비율도 유지된다
데이터가 적다층화 k-fold 교차검증모든 행을 검증에 활용, 평균·분산 확보
데이터가 매우 적다Leave-One-Out편향은 최소, 비용을 감수
클래스 불균형층화(stratified) 필수소수 클래스가 모든 분할에 들어가야 한다
시계열TimeSeriesSplit / 시간 순 holdout시간 역행 누수를 차단
그룹 구조(사용자·환자)GroupKFold같은 그룹이 양쪽에 걸치면 성능이 부풀려진다
튜닝까지 포함해 정직하게 평가Nested CV바깥 fold는 튜닝에 관여하지 않아 선택 편향이 없다
회귀이면서 타깃이 크게 치우침타깃을 구간화해 층화극단값이 한쪽 분할에 몰리는 것을 막는다

AWS 서비스 매핑표

상황AWS 서비스·기능이유
하이퍼파라미터를 검증 지표 기준으로 자동 탐색SageMaker 자동 모델 튜닝(하이퍼파라미터 튜닝 잡)목적 지표를 지정하면 여러 학습 잡을 돌려 최적 조합을 찾는다
전처리·학습·평가 순서를 코드로 고정SageMaker Pipelines분할·전처리 순서가 재현돼 누수와 절차 실수를 막는다
학습별 지표·파라미터를 비교 추적SageMaker Experiments검증 점수 비교 이력이 남아 선택 근거를 남길 수 있다
학습이 좋아지지 않을 때 조기 종료해 비용 절감SageMaker의 조기 종료 설정검증 지표가 개선되지 않는 학습을 일찍 끊는다
봉인한 테스트셋으로 대량 채점SageMaker 배치 변환엔드포인트를 상시 유지하지 않고 한 번에 평가한다
배포 후 실제 성능이 검증과 다른지 감시SageMaker Model Monitor검증-운영 괴리를 지표로 포착한다

지문 단서 → 정답 매핑표

지문 표현읽어야 할 신호고를 답
"시간 순서가 있는 일별 데이터다"시계열TimeSeriesSplit / 시간 순 holdout
"클래스가 0.5%다"극단 불균형층화 분할 + PR-AUC·recall
"데이터가 수백 건뿐이다"데이터 부족k-fold(또는 LOO) 교차검증
"같은 환자의 여러 검사 기록"그룹 구조GroupKFold
"테스트 점수를 보며 모델을 고쳤다"테스트셋 오염새 테스트셋 필요, 봉인 원칙 위반
"fold마다 점수가 크게 다르다"추정 분산 큼k를 늘리거나 Repeated k-fold
"튜닝 결과까지 포함해 정직한 성능을 보고하라"선택 편향 제거 필요Nested CV
"정확도는 높은데 소수 클래스를 못 잡는다"지표·분할 둘 다 문제층화 + recall/PR-AUC로 전환

다음 글에서는 이번 주 전체 — 통계 기초부터 검증 설계까지를 하나의 흐름으로 정리한다.

📖 용어

  • 검증셋(validation set) : 하이퍼파라미터 튜닝과 모델 선택에 반복해서 쓰는 데이터. 최종 성능 보고용이 아니다.
  • 테스트셋(test set) : 모든 결정이 끝난 뒤 딱 한 번만 보는 최종 평가용 데이터.
  • 다중 비교 문제 : 여러 후보를 같은 검증셋으로 비교하면 우연히 잘 맞는 것이 뽑혀 점수가 낙관적으로 편향되는 현상.
  • k-fold 교차검증 : 데이터를 k등분해 각 조각을 한 번씩 검증으로 쓰며 k번 학습·평가하는 방법.
  • 층화 표집(stratified) : 각 분할에서 원본 클래스 비율을 그대로 유지하도록 나누는 방식.
  • GroupKFold : 같은 그룹(사용자·환자)의 행이 학습과 검증으로 갈라지지 않게 하는 교차검증.
  • TimeSeriesSplit : 학습 구간이 항상 검증 구간보다 과거가 되도록 나누는 시계열 전용 교차검증.
  • Nested CV(중첩 교차검증) : 안쪽 fold에서 튜닝하고 바깥 fold에서 평가해 선택 편향까지 제거하는 방법.
  • 편향-분산 트레이드오프(k 선택) : k가 작으면 추정이 비관적으로 편향되고, 매우 크면 분산과 계산 비용이 커지는 관계.
  • PR-AUC : precision-recall 곡선 아래 면적. 양성 비율이 매우 낮을 때 ROC-AUC보다 정직한 신호를 준다.

📝 연습 문제

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

문제 1

하이퍼파라미터를 튜닝하면서 테스트셋 점수를 보고 모델을 반복 수정했다. 이때 발생하는 문제는?

문제 2

데이터가 매우 적은 분류 문제에서 단일 분할의 점수가 분할마다 크게 흔들린다. 더 안정적인 성능 추정을 위한 방법은?

문제 3

사기 거래가 전체의 1%인 극도로 불균형한 데이터를 분할할 때 가장 적절한 방법은?

문제 4

일별 수요 시계열을 검증할 때 누수를 막는 올바른 교차검증 방식은?

문제 5

k-fold 교차검증에서 k를 결정할 때의 트레이드오프로 옳은 것은?

이전데이터 누수(Data Leakage): 원인·탐지·예방과 시계열 누수·타깃 누수Week 5 · Day 3다음 5주차 종합 복습: 통계와 검증 설계Week 5 · Day 5

참고 공식 자료

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

이 페이지

  • 왜 셋으로 나누는가: train / validation / test
  • 세 분할의 역할 구분표
  • k-fold 교차검증: 데이터를 아낀다
  • k 값 트레이드오프표
  • 층화 표집: 비율을 유지한다
  • 불균형 데이터의 지표 해석표
  • 시계열 분할: 시간을 거스르지 않는다
  • 검증 전략 선택표
  • AWS 서비스 매핑표
  • 지문 단서 → 정답 매핑표
  • 용어
  • 연습 문제