튜토리얼
01. ML Pipeline

01. ML Pipeline 완전정복

Train/Val/Test Split, Cross-Validation, Data Leakage 방지


학습 목표

이 튜토리얼을 완료하면 다음을 할 수 있습니다:

  1. Train/Validation/Test Split의 원리와 올바른 분할 방법 이해
  2. Cross-Validation (K-Fold, Stratified K-Fold) 구현 및 활용
  3. Data Leakage의 위험성과 이를 방지하는 Pipeline 구축
  4. Feature Scaling 방법들 (Standard, MinMax, Robust) 비교 분석
  5. sklearn.pipeline.PipelineColumnTransformer를 활용한 재현 가능한 ML 워크플로우 구축

핵심 개념

1. Machine Learning Pipeline이란?

ML Pipeline은 데이터 전처리부터 모델 학습까지의 모든 단계를 순차적으로 연결한 워크플로우입니다.

Raw Data → 전처리 → Feature Engineering → 모델 학습 → 예측

Pipeline이 없으면:

  • 전처리 단계를 수동으로 관리해야 함
  • Train/Test 데이터에 서로 다른 변환이 적용될 위험
  • Data Leakage 발생 가능성 증가

2. Train/Validation/Test Split

왜 3-way Split이 필요한가?

세트용도비율
Train모델 학습60-70%
Validation하이퍼파라미터 튜닝15-20%
Test최종 성능 평가 (한 번만!)15-20%
⚠️

Test Set은 최종 평가에만 한 번 사용해야 합니다. 여러 번 사용하면 Test Set에 오버피팅됩니다.

잘못된 방법: 단순 Random Split

# stratify 없이 분할 → 클래스 비율 불균형 발생 가능
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

올바른 방법: Stratified Split

from sklearn.model_selection import train_test_split
 
# 타겟 분포 유지하며 분할
X_temp, X_test, y_temp, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
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
)
# 결과: Train 60%, Val 20%, Test 20% (모두 같은 클래스 비율)

3. Data Leakage (데이터 누수)

Test 데이터의 정보가 학습 과정에 유출되는 현상

주요 원인

  1. 전처리 누수: 전체 데이터로 평균/표준편차 계산 후 스케일링
  2. Target Leakage: 타겟에서 파생된 피처 사용
  3. 시간 누수: 미래 데이터로 과거 예측 (시계열)

잘못된 예시

# ❌ 전체 데이터로 스케일링 → 분할 (Leakage!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)  # 전체 데이터의 mean/std 사용
X_train, X_test = train_test_split(X_scaled, ...)
 
# 문제: Test 데이터의 정보가 Train에 유출됨

올바른 예시

# ✅ 분할 → Train만 fit → 각각 transform
X_train, X_test = train_test_split(X, ...)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # Train만!
X_test_scaled = scaler.transform(X_test)  # transform만 (fit 없음)
🚫

Leakage가 있어도 테스트 성능이 좋게 나올 수 있습니다. 하지만 실제 운영 환경에서 성능이 크게 저하됩니다!


4. Cross-Validation

단일 Split의 한계를 극복하기 위해 데이터를 여러 번 분할하여 평가

K-Fold CV

데이터를 K개로 나누고, 각 fold를 한 번씩 validation으로 사용:

from sklearn.model_selection import cross_val_score, StratifiedKFold
 
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=cv, scoring='accuracy')
print(f"평균: {scores.mean():.4f}{scores.std():.4f})")

K-Fold vs Stratified K-Fold

방법특징사용 시점
K-Fold단순히 K등분회귀 문제
Stratified K-Fold클래스 비율 유지하며 K등분분류 문제 (특히 불균형 데이터)

여러 메트릭으로 CV

from sklearn.model_selection import cross_validate
 
scoring = {
    'accuracy': 'accuracy',
    'precision': 'precision',
    'recall': 'recall',
    'f1': 'f1',
    'roc_auc': 'roc_auc'
}
 
results = cross_validate(pipeline, X, y, cv=cv, scoring=scoring)

5. Feature Scaling 비교

Scaler공식특징사용 시점
StandardScaler(x - μ) / σ평균 0, 분산 1일반적인 경우
MinMaxScaler(x - min) / (max - min)[0, 1] 범위신경망, 이미지
RobustScaler(x - Q2) / (Q3 - Q1)중앙값, IQR 사용이상치가 많을 때

Scaling이 필요한 모델 vs 불필요한 모델

Scaling 필수Scaling 불필요
Logistic RegressionDecision Tree
SVMRandom Forest
KNNXGBoost, LightGBM
Neural Network

Pipeline 구축

기본 Pipeline

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
 
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('classifier', RandomForestClassifier())
])
 
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)

ColumnTransformer로 수치형/범주형 분리 처리

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
 
# 수치형 전처리
numeric_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())
])
 
# 범주형 전처리
categorical_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('encoder', OneHotEncoder(handle_unknown='ignore'))
])
 
# 통합
preprocessor = ColumnTransformer([
    ('num', numeric_transformer, ['age', 'fare', 'sibsp', 'parch']),
    ('cat', categorical_transformer, ['pclass', 'sex', 'embarked'])
])
 
# 전체 파이프라인 (전처리 + 모델)
pipeline = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier(n_estimators=100))
])
 
# 학습 & 예측
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)

Learning Curve 분석

Train/Validation 성능의 변화를 통해 Overfitting/Underfitting 진단:

from sklearn.model_selection import learning_curve
 
train_sizes, train_scores, val_scores = learning_curve(
    pipeline, X, y,
    train_sizes=np.linspace(0.1, 1.0, 10),
    cv=5, scoring='accuracy'
)
 
# 시각화
plt.plot(train_sizes, train_scores.mean(axis=1), label='Train')
plt.plot(train_sizes, val_scores.mean(axis=1), label='Validation')
plt.xlabel('Training Set Size')
plt.ylabel('Accuracy')
plt.legend()

해석:

  • 두 곡선이 수렴 → 좋은 신호
  • Gap이 크면 → Overfitting (정규화 또는 단순한 모델 필요)
  • 두 곡선 모두 낮으면 → Underfitting (더 복잡한 모델 필요)

체크리스트

단계체크 항목
데이터 분할☐ Stratified Split 사용
☐ Train/Val/Test 3-way Split
☐ Test Set은 최종 평가에만 사용
전처리☐ Split 후에 전처리 수행
☐ Pipeline 사용하여 Leakage 방지
☐ fit_transform은 Train에만
검증☐ Cross-Validation 사용
☐ 여러 메트릭 사용
☐ Learning Curve로 과적합 체크

면접 질문 맛보기

  1. Data Leakage란 무엇이고, 어떻게 방지하나요?
  2. K-Fold CV와 Hold-out의 차이점은?
  3. Stratified Split은 언제 사용하나요?
  4. StandardScaler와 RobustScaler의 차이는?
  5. Pipeline을 사용하는 이유는?

더 많은 면접 질문은 Premium Interviews (opens in a new tab)에서 확인하세요.


실습 노트북

Titanic 데이터셋으로 위 개념들을 직접 실습해보세요:

노트북에서는 추가로 다음 내용을 다룹니다:

  • EDA (탐색적 데이터 분석) 및 시각화
  • Leakage 유무에 따른 성능 비교 실험
  • 여러 Scaler별 모델 성능 비교
  • Feature Importance 분석
  • 연습문제

다음: 02. Linear Regression