콘텐츠로 이동

ML 파이프라인 설계 (ML Pipeline Design)

난이도: 중급
선수 지식: 교차 검증, 데이터 누수
관련 문서: 실험 추적 | 모델 배포 | ML 시스템 설계 패턴

핵심 요약: ML 파이프라인은 데이터 → 전처리 → 학습 → 평가 → 배포의 전체 흐름이다. 항상 단순한 모델(베이스라인)부터 시작하라 — 복잡한 모델이 베이스라인을 이기지 못하면, 문제는 모델이 아니라 데이터에 있다.

  • 파이프라인(Pipeline): 데이터 전처리부터 모델 학습, 평가, 배포까지를 하나의 흐름으로 연결한 자동화된 워크플로우.
  • 베이스라인(Baseline): 비교 기준이 되는 가장 단순한 모델. “모든 예측을 평균으로” 또는 로지스틱 회귀 같은 간단한 모델이 해당.
  • 교차 검증(Cross-Validation): 데이터를 K개로 나누어 K번 학습/평가를 반복하는 방법. 한 번의 평가보다 신뢰할 수 있는 성능 추정을 제공한다.
  • 하이퍼파라미터(Hyperparameter): 모델이 학습하는 것이 아니라 사람이 미리 설정하는 값. 학습률, 트리 깊이 등.

ML 파이프라인은 문제 정의부터 데이터 수집, 전처리, 모델 학습, 평가, 배포까지의 전체 워크플로우를 체계적으로 구성한 것이다. 좋은 파이프라인은 재현 가능하고, 자동화 가능하며, 데이터 누수를 방지한다. ML 프로젝트의 성패는 종종 모델 아키텍처가 아니라 파이프라인의 견고함에 달려 있다.

비유: ML 파이프라인은 공장 조립 라인이다. 원재료(원본 데이터)가 들어와 세척(전처리), 가공(특성 공학), 조립(학습), 검사(평가)를 거쳐 제품(모델)이 나온다. 핵심은 모든 공정이 같은 순서로, 같은 방식으로 반복 가능해야 한다는 것이다. 어제는 되고 오늘은 안 되는 라인은 공장이 아니라 수공예다.


ML 파이프라인 설계라는 개념이 체계화되기까지는 수많은 실패와 기술 부채(Technical Debt)의 역사가 있었다.

초기 ML 파이프라인의 진화:

  • Netflix (2006~2009): Netflix Prize 대회를 통해 추천 알고리즘의 가능성을 확인했지만, 수상 알고리즘을 프로덕션에 적용하는 데만 수년이 걸렸다. 대회에서 우승한 복잡한 앙상블 모델은 실시간 서빙에 적합하지 않았고, 이 경험은 “학습 환경과 프로덕션 환경은 전혀 다르다”는 교훈을 남겼다.
  • Google (2010~2014): 대규모 ML 시스템을 운영하면서 데이터 수집, 전처리, 학습, 서빙의 각 단계가 서로 다른 팀에 의해 독립적으로 관리되는 문제를 경험했다. 이는 Training-Serving Skew, 데이터 누수, 재현 불가능한 실험 등 수많은 문제를 야기했다.
  • Uber (2015~2017): Michelangelo 플랫폼을 개발하면서, End-to-End ML 파이프라인의 표준화가 팀 생산성을 극적으로 향상시킨다는 것을 증명했다.

2015년 Google에서 발표한 논문 “Hidden Technical Debt in Machine Learning Systems”는 업계에 큰 반향을 일으켰다. 이 논문의 핵심 메시지는 다음과 같다:

“ML 시스템에서 실제 ML 코드는 전체 시스템의 극히 일부에 불과하다. 나머지는 데이터 검증, 특성 추출, 서빙 인프라, 모니터링 등 주변 인프라이며, 이 인프라의 기술 부채가 시스템 전체의 안정성을 위협한다.”

이 논문 이후 ML 파이프라인 설계는 “모델을 잘 만드는 것”에서 “전체 시스템을 견고하게 설계하는 것”으로 패러다임이 전환되었고, MLOps라는 새로운 분야가 탄생하는 계기가 되었다.


1. End-to-End 파이프라인 다이어그램

2. 데이터 분할 비율 (Data Split Ratios)

섹션 제목: “2. 데이터 분할 비율 (Data Split Ratios)”

전체 데이터셋 DD를 학습(train), 검증(validation), 테스트(test)로 분할한다. 일반적인 비율은 다음과 같다:

D=DtrainDvalDtest,Dtrain:Dval:Dtest=60:20:20D = D_{train} \cup D_{val} \cup D_{test}, \quad |D_{train}| : |D_{val}| : |D_{test}| = 60 : 20 : 20

데이터가 충분히 많을 때(예: D>106|D| > 10^6)는 검증/테스트 비율을 줄여도 통계적 신뢰성을 유지할 수 있다:

Dval=Dtest12ϵ2ln2δ|D_{val}| = |D_{test}| \geq \frac{1}{2\epsilon^2} \ln\frac{2}{\delta}

  • ϵ\epsilon: 허용 오차 (예: 0.01)
  • δ\delta: 실패 확률 (예: 0.05)

이 부등식은 Hoeffding 부등식에서 유도되며, 평가 지표의 신뢰도를 보장하기 위한 최소 테스트 세트 크기를 결정한다.

항상 간단한 기준 모델부터 시작한다.

과제 유형기준 모델 예시
분류로지스틱 회귀, 다수 클래스 예측
회귀평균 예측, 선형 회귀
시계열이전 값 반복, 이동 평균
NLPTF-IDF + 로지스틱 회귀

규칙: 복잡한 모델이 baseline을 의미 있게 이기지 못하면, 모델이 아니라 데이터/특성 문제를 먼저 해결하라.

3. 교차 검증 전략 (Cross-Validation)

섹션 제목: “3. 교차 검증 전략 (Cross-Validation)”
전략적합한 데이터설명
K-Fold (K=5, 10)일반 정형 데이터가장 기본적
Stratified K-Fold분류 (불균형 포함)클래스 비율 유지
Group K-Fold그룹 데이터 (환자, 사용자)같은 그룹이 train/test에 겹치지 않음
Time Series Split시계열시간 순서 유지, expanding window
Nested CV튜닝 + 성능 추정 분리가장 엄격한 평가

K-Fold 교차 검증의 일반화 오차 추정은 다음과 같다:

E^CV=1Kk=1KL(f(k),  Dk)\hat{E}_{CV} = \frac{1}{K}\sum_{k=1}^{K} L\bigl(f^{(-k)},\; D_k\bigr)

  • KK: fold 수
  • f(k)f^{(-k)}: kk번째 fold를 제외하고 학습한 모델
  • DkD_k: kk번째 fold (검증용)
  • LL: 손실 함수 (예: 0-1 loss, MSE)

교차 검증 추정의 분산은 fold 간 상관관계로 인해 단순히 1/K1/K로 줄어들지 않는다:

Var(E^CV)=1Kσ2+K1Kρσ2\text{Var}(\hat{E}_{CV}) = \frac{1}{K}\sigma^2 + \frac{K-1}{K}\rho\sigma^2

  • σ2\sigma^2: 개별 fold 오차의 분산
  • ρ\rho: fold 간 오차의 상관계수 (학습 데이터가 대부분 겹치므로 양수)

Nested Cross-Validation: 외부 루프는 성능 추정, 내부 루프는 하이퍼파라미터 튜닝. 검증 세트에 과적합하는 것을 방지한다.

4. 하이퍼파라미터 튜닝 (Hyperparameter Tuning)

섹션 제목: “4. 하이퍼파라미터 튜닝 (Hyperparameter Tuning)”
방법효율성설명
Grid Search낮음모든 조합 탐색, 차원이 늘면 비효율
Random Search중간Bergstra & Bengio (2012) — Grid보다 효율적
Bayesian Optimization높음이전 결과를 활용한 지능적 탐색 (Optuna, Hyperopt)
Early Stopping-Validation 성능이 개선되지 않으면 학습 조기 종료

Random Search가 Grid Search보다 좋은 이유: 하이퍼파라미터마다 중요도가 다르다. Grid Search는 불필요한 조합에 자원을 낭비하지만, Random Search는 중요한 차원을 더 넓게 탐색한다.

모델 성능 개선의 가장 효과적인 방법은 오류를 분석하는 것이다.

  • Confusion Matrix 분석: 어떤 클래스 간에 혼동이 많은지
  • 오분류 샘플 시각화: 왜 틀렸는지 직관적 이해
  • Slice-based Evaluation: 특정 부분 집합(subgroup)별 성능 확인
    • 예: 성별, 연령대, 지역별로 성능이 다른지

데이터 100,000건을 어떻게 나눌지 계산해 보자.

용도비율건수
학습(train)60%60,000
검증(validation)20%20,000
테스트(test)20%20,000

검증셋이 이만큼 필요할까? Hoeffding 부등식으로 최소 크기를 구해 보자. 성능 추정 오차를 ϵ=0.01\epsilon = 0.01 이내로, 신뢰도 95%(δ=0.05\delta = 0.05)로 두면:

nln(2/δ)2ϵ2=ln402×0.000118,445n \geq \frac{\ln(2/\delta)}{2\epsilon^2} = \frac{\ln 40}{2 \times 0.0001} \approx 18{,}445

20,000건이면 충분하다.

그런데 데이터가 1,000,000건이라면? 필요량은 여전히 약 18,445건이므로, 20%(200,000건)를 검증에 쓰는 것은 낭비다. 2%(20,000건)로 줄이고 나머지 96만 건을 학습에 돌리는 편이 낫다.

교훈: 60:20:20은 법칙이 아니라 데이터가 적을 때의 관습이다. 검증셋 크기는 비율이 아니라 필요한 정밀도로 정해야 한다.

# --- 실행을 위한 준비 ---
from sklearn.datasets import make_classification
from sklearn.impute import SimpleImputer
from sklearn.model_selection import cross_val_score
X, y = make_classification(n_samples=300, n_features=8, random_state=0)
# sklearn Pipeline으로 데이터 누수 방지
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
pipe = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler()),
('model', RandomForestClassifier())
])
# cross_val_score가 각 fold 내부에서 fit/transform을 올바르게 처리
scores = cross_val_score(pipe, X, y, cv=5, scoring='f1')

모델 선택 가이드 다이어그램

ML 파이프라인 설계는 모든 ML 프로젝트의 기반이다. 특히:

  • 프로덕션 배포를 목표로 하는 프로젝트
  • 여러 실험을 체계적으로 비교해야 하는 경우
  • 팀 협업이 필요한 경우
  • 재현 가능성이 중요한 경우

베이스라인 없이 170만 달러를 낭비한 팀

섹션 제목: “베이스라인 없이 170만 달러를 낭비한 팀”

한 핀테크 스타트업이 사기 탐지(Fraud Detection) 시스템을 구축하면서 겪은 실화이다.

상황: 이 팀은 “최첨단 기술을 적용해야 한다”는 경영진의 요구에 따라, 프로젝트 시작부터 복잡한 앙상블 모델(XGBoost + LightGBM + 딥러닝 + 룰 엔진의 스태킹)을 설계했다. 간단한 베이스라인 모델은 “너무 단순해서 의미가 없다”며 건너뛰었다.

진행 과정:

기간활동비용
1~3개월복잡한 앙상블 파이프라인 설계 및 구현인건비 $300K
4~6개월GPU 클러스터 구축, 하이퍼파라미터 튜닝인프라 $500K + 인건비 $300K
7~9개월Training-Serving Skew 디버깅, 재구현인건비 $400K
10~12개월성능이 기대에 미치지 못해 전면 재설계 결정인건비 $200K

총 비용: 약 $1.2M (인건비) + $500K (인프라) = $1.7M

반전: 재설계 과정에서 가장 먼저 만든 로지스틱 회귀(Logistic Regression) 베이스라인이 F1 0.89를 달성했다. 12개월간 공들인 앙상블 모델의 최종 성능은 F1 0.91이었다. 한계 이득(Marginal Gain) 0.02를 위해 170만 달러와 1년의 시간을 소비한 셈이다.

교훈:

  • 베이스라인 없이 시작하면, “개선”의 기준 자체가 없다
  • 복잡한 모델이 베이스라인을 의미 있게 이기지 못하면, 문제는 모델이 아니라 데이터와 특성에 있을 가능성이 높다
  • 이 팀은 결국 로지스틱 회귀 + 규칙 기반 후처리 조합으로 F1 0.93을 달성했고, 유지보수 비용은 앙상블 대비 1/10 수준이었다

from math import log, ceil
# 검증셋 크기는 "비율"이 아니라 "필요한 추정 정밀도"로 정한다 (Hoeffding)
def min_val_size(eps, delta):
return ceil(log(2/delta) / (2*eps**2))
print(f"{'허용 오차':>9} {'신뢰도':>8} {'최소 검증셋':>12}")
for eps in (0.05, 0.02, 0.01):
print(f"{eps:>9.2f} {0.95:>8.2f} {min_val_size(eps, 0.05):>12,}")
need = min_val_size(0.01, 0.05)
print("\n데이터 크기별 권장 분할:")
for N in (1_000, 10_000, 100_000, 1_000_000):
v = min(int(N*0.2), max(need, int(N*0.02)))
print(f" 전체 {N:>9,} -> 검증 {v:>7,} ({v/N:>5.1%}), 학습 {N-2*v:>9,}")
# 실행 결과:
# 허용 오차 신뢰도 최소 검증셋
# 0.05 0.95 738
# 0.02 0.95 4,612
# 0.01 0.95 18,445
#
# 데이터 크기별 권장 분할:
# 전체 1,000 -> 검증 200 (20.0%), 학습 600
# 전체 10,000 -> 검증 2,000 (20.0%), 학습 6,000
# 전체 100,000 -> 검증 18,445 (18.4%), 학습 63,110
# 전체 1,000,000 -> 검증 20,000 ( 2.0%), 학습 960,000

오차 1% 이내로 성능을 추정하는 데 필요한 검증셋은 약 18,445건이다. 데이터가 100만 건이라면 20%(20만 건)를 검증에 쓰는 것은 명백한 낭비다 — 2%만 떼어도 충분하고 나머지 96만 건을 학습에 돌릴 수 있다. 60:20:20은 법칙이 아니라 데이터가 적을 때의 관습이다.


  1. Baseline 없이 복잡한 모델부터 시작: 개선 여부를 판단할 기준이 없다. 항상 간단한 baseline부터 시작하라.

  2. 시계열에 random split 사용: 미래 데이터가 학습에 포함되어 성능이 과대 추정된다.

  3. 교차 검증 전에 전처리: 데이터 누수의 가장 흔한 원인. Pipeline을 사용하여 방지하라.

  4. 검증 세트에 반복 튜닝: 반복적인 하이퍼파라미터 튜닝으로 validation set에 과적합된다. Nested CV 또는 별도의 test set을 유지하라.

  5. EDA를 건너뜀: 데이터를 이해하지 않고 모델링을 시작하면, 근본적인 데이터 문제를 놓치게 된다.

  6. 한 가지 지표만 보기: 비즈니스 목표에 맞는 여러 지표를 함께 살펴야 한다.


1. 복잡한 모델보다 베이스라인을 먼저 만들어야 하는 이유는?

정답 보기

베이스라인이 없으면 “개선”의 기준 자체가 없다. 또한 단순한 모델로 충분한 문제였음을 일찍 알 수 있어, 불필요한 복잡도와 비용을 피할 수 있다.

2. Training-Serving Skew란 무엇인가?

정답 보기

학습 때와 서빙 때의 전처리가 달라 성능이 떨어지는 현상이다. 같은 전처리 코드를 양쪽에서 공유하거나 특성 저장소(feature store)를 쓰면 예방된다.

3. 데이터가 100만 건이면 검증셋을 20%로 잡아야 하는가?

정답 보기

그럴 필요 없다. 검증셋 크기는 비율이 아니라 필요한 추정 정밀도로 정한다. 오차 ±1%, 신뢰도 95%면 약 2만 건으로 충분하므로 나머지는 학습에 쓰는 편이 낫다.