ML 파이프라인 (Machine Learning Pipeline)
데이터 전처리, 특성 엔지니어링, 모델 훈련을 하나의 재사용 가능한 단위로 통합하는 설계 패턴. 데이터 누수를 방지하고 프로덕션 배포를 간소화한다.
설명
ML 파이프라인은 “재현 가능한 워크플로우”이다. 각 단계가 순서대로 실행되며, 훈련·테스트·프로덕션 환경에서 동일한 변환이 자동으로 적용된다.
구성:
- Transformer: 데이터 변환 (스케일링, 인코딩, 결측치 대체)
- Estimator: 예측 모델 (분류, 회귀)
핵심 문제: 데이터 누수 (Data Leakage)
상황: 정보 누출
[전체 데이터]
↓
[스케일링] ← 평균·표준편차 계산 (전체 데이터 포함!)
↓
[Train-Test 분할]
├─ 훈련 데이터: 스케일링됨
└─ 테스트 데이터: 스케일링됨 (훈련 통계 기반)
문제: 테스트 데이터의 통계가 훈련에 영향 → 모델 성능 과평가
해결책: 파이프라인으로 자동화
from sklearn.pipeline import Pipeline
pipe = Pipeline([
('scaler', StandardScaler()),
('classifier', LogisticRegression())
])
# 훈련 시: 스케일러가 X_train의 통계 학습
pipe.fit(X_train, y_train)
# 테스트 시: 훈련된 스케일러만 적용 (재학습 X)
pipe.predict(X_test)결과:
- 스케일러는 X_train에서만 학습
- X_test는 X_train의 규칙으로만 변환
- 현실적인 성능 평가 가능
ColumnTransformer: 혼합 자료형 처리
실무 데이터는 수치형(연속변수) + 범주형(카테고리)이 함께 있다.
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
ct = ColumnTransformer([
('numeric', Pipeline([
('imputer', SimpleImputer(strategy='mean')), # 결측치 → 평균
('scaler', StandardScaler()) # 정규화
]), numeric_columns),
('categorical', Pipeline([
('imputer', SimpleImputer(strategy='most_frequent')), # 결측치 → 최빈값
('encoder', OneHotEncoder()) # 범주 → 0/1
]), categorical_columns)
])
pipe = Pipeline([
('preprocessor', ct),
('classifier', LogisticRegression())
])동작:
- 수치형 브랜치: 결측치(평균) → 정규화
- 범주형 브랜치: 결측치(최빈값) → 원-핫 인코딩
- 두 결과 병렬 실행 후 좌우 연결
- 로지스틱 회귀에 입력
하이퍼파라미터 최적화: GridSearchCV
파이프라인의 모든 단계 파라미터를 체계적으로 탐색:
from sklearn.model_selection import GridSearchCV
param_grid = {
'preprocessor__numeric__scaler__with_mean': [True, False],
'classifier__C': [0.1, 1, 10],
'classifier__penalty': ['l1', 'l2']
}
gs = GridSearchCV(pipe, param_grid, cv=5)
gs.fit(X_train, y_train)
print(f"최고 점수: {gs.best_score_:.3f}")
print(f"최적 파라미터: {gs.best_params_}")명명 규칙:
preprocessor: ColumnTransformer 이름numeric: 수치형 브랜치 이름scaler: StandardScaler 이름with_mean: 스케일러 파라미터
4대 이점
1. 데이터 누수 방지
훈련·테스트 데이터 격리 → 현실적 성능 평가
2. 코드 정리 & 유지보수성
전처리와 모델이 분리 → 각각 독립적 수정 가능
# 스케일러만 교체
pipe.named_steps['preprocessor']3. 교차검증 간편화
from sklearn.model_selection import cross_val_score
scores = cross_val_score(pipe, X, y, cv=5)각 폴드에서 자동으로 전처리 규칙 재학습 → 일관성 보장
4. 모델 배포 & 재사용
import joblib
# 저장
joblib.dump(pipe, 'model.pkl')
# 프로덕션 로드
pipe = joblib.load('model.pkl')
y_pred = pipe.predict(X_new)파이프라인 전체(전처리 + 모델)를 단일 파일로 배포 → 재현성 보장
성능 최적화
캐싱 (Caching)
교차검증 중 fit된 변환자 재사용:
pipe = Pipeline([...], memory='/tmp/cache')
cross_val_score(pipe, X, y, cv=5) # fit된 변환자 캐시 재사용효과: 계산 시간 50% 단축
병렬화 (Parallelization)
gs = GridSearchCV(pipe, param_grid, n_jobs=-1)모든 CPU 코어 활용 → 그래프 탐색 속도 대폭 향상
커스텀 변환자
BaseEstimator + TransformerMixin 상속으로 확장:
from sklearn.base import BaseEstimator, TransformerMixin
class MyTransformer(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
self.mean_ = X.mean()
return self
def transform(self, X):
return X - self.mean_
pipe = Pipeline([
('custom', MyTransformer()),
('classifier', LogisticRegression())
])주의사항
| 실수 | 결과 | 해결책 |
|---|---|---|
| 전체 데이터 전처리 후 분할 | 데이터 누수 | 파이프라인으로 자동화 |
| fit_transform을 테스트에 사용 | 테스트 규칙 학습(오염) | transform만 사용 |
| 파이프라인 외부에서 스케일링 | 일관성 부족 | 모든 변환을 파이프라인 내부에 |
관련 개념
- exploratory-data-analysis-eda — 파이프라인 설계 전 데이터 이해
- hyperparameter-tuning — GridSearchCV로 최적화
실전 적용
scikit-learn 의 구현 도구
- Pipeline, ColumnTransformer, GridSearchCV
- Transformer 클래스 (StandardScaler, OneHotEncoder)
- Estimator 클래스 (LogisticRegression, RandomForest)
pandas-dataframe 과의 연관
- 입력 데이터 소스
- 혼합 자료형 데이터 처리