데이터 드리프트
Data Drift
시간에 따른 데이터 분포 변화. 모델 성능 저하 원인.
Data Drift
시간에 따른 데이터 분포 변화. 모델 성능 저하 원인.
데이터 드리프트(Data Drift)는 ML 모델의 입력 데이터 분포가 훈련 시점과 추론(운영) 시점 사이에 변화하는 현상입니다. 이로 인해 모델 성능이 시간이 지남에 따라 점진적으로 저하되며, 이를 모델 성능 저하(Model Decay)라고 합니다.
데이터 드리프트는 크게 두 가지로 분류됩니다. Covariate Drift(공변량 드리프트)는 입력 특성 P(X)의 분포 변화이고, Concept Drift(개념 드리프트)는 입력과 출력 간 관계 P(Y|X)의 변화입니다. COVID-19 팬데믹 기간 소비 패턴 변화는 대표적인 Concept Drift 사례입니다.
드리프트 감지 방법은 통계적 테스트(KS Test, Chi-Square, PSI), 분포 거리 측정(KL Divergence, Wasserstein Distance), ML 기반 감지기로 나뉩니다. 2024-2025년 현재 Evidently, Arize, NannyML 등 모니터링 도구들이 자동화된 드리프트 감지를 제공합니다.
실무에서 데이터 드리프트 관리는 MLOps의 핵심입니다. 지속적인 모니터링, 재훈련 파이프라인 자동화, 그리고 드리프트 발생 시 알림 시스템 구축이 필수입니다. EU AI Act도 고위험 AI의 사후 모니터링에서 드리프트 관리를 요구합니다.
# 데이터 드리프트 감지 - Evidently AI 활용
import pandas as pd
import numpy as np
from evidently import ColumnMapping
from evidently.report import Report
from evidently.metrics import DataDriftTable, DatasetDriftMetric
from scipy import stats
# 1. 통계적 드리프트 감지 (기본 구현)
def detect_drift_ks_test(reference_data: np.ndarray,
current_data: np.ndarray,
threshold: float = 0.05) -> dict:
"""
Kolmogorov-Smirnov 테스트로 드리프트 감지
귀무가설: 두 분포가 동일
"""
statistic, p_value = stats.ks_2samp(reference_data, current_data)
return {
"statistic": statistic,
"p_value": p_value,
"drift_detected": p_value < threshold,
"severity": "high" if statistic > 0.2 else "medium" if statistic > 0.1 else "low"
}
# 2. PSI (Population Stability Index) 계산
def calculate_psi(reference: np.ndarray, current: np.ndarray,
buckets: int = 10) -> float:
"""
PSI 계산 - 금융권에서 많이 사용
PSI < 0.1: 변화 없음
0.1 <= PSI < 0.2: 약간의 변화
PSI >= 0.2: 유의미한 변화 (재훈련 필요)
"""
# 버킷 경계 설정 (reference 기준)
breakpoints = np.percentile(reference, np.linspace(0, 100, buckets + 1))
breakpoints[0], breakpoints[-1] = -np.inf, np.inf
# 각 버킷의 비율 계산
ref_counts = np.histogram(reference, breakpoints)[0] / len(reference)
cur_counts = np.histogram(current, breakpoints)[0] / len(current)
# 0 방지
ref_counts = np.clip(ref_counts, 0.0001, None)
cur_counts = np.clip(cur_counts, 0.0001, None)
psi = np.sum((cur_counts - ref_counts) * np.log(cur_counts / ref_counts))
return psi
# 3. Evidently AI 활용 (실무 권장)
def create_drift_report(reference_df: pd.DataFrame,
current_df: pd.DataFrame,
target_column: str = None):
"""Evidently AI로 종합 드리프트 리포트 생성"""
column_mapping = ColumnMapping(target=target_column)
report = Report(metrics=[
DatasetDriftMetric(), # 전체 데이터셋 드리프트
DataDriftTable() # 컬럼별 드리프트
])
report.run(reference_data=reference_df,
current_data=current_df,
column_mapping=column_mapping)
return report
# 사용 예시
np.random.seed(42)
# 훈련 시점 데이터 (정규분포)
reference = np.random.normal(50, 10, 10000)
# 운영 시점 데이터 (분포 이동 발생!)
current = np.random.normal(55, 12, 10000)
# 드리프트 감지
ks_result = detect_drift_ks_test(reference, current)
psi_value = calculate_psi(reference, current)
print(f"KS Test - 드리프트 감지: {ks_result['drift_detected']}")
print(f"PSI 값: {psi_value:.4f} ({'재훈련 필요!' if psi_value >= 0.2 else '정상'})")
2025년 1월 기준 주요 데이터 드리프트 모니터링 도구:
| 도구 | 특징 | 비용 | 적합 환경 |
|---|---|---|---|
| Evidently AI | 오픈소스, 리포트 생성 | 무료 (Cloud: $400/월~) | 스타트업, PoC |
| Arize AI | 실시간 모니터링, LLM 지원 | $750/월~ | 엔터프라이즈 |
| NannyML | 레이블 없이 성능 추정 | 무료 (Cloud: $500/월~) | 레이블 지연 환경 |
| WhyLabs | 프로파일 기반, 경량 | 무료 (Pro: $600/월~) | 대용량 데이터 |
| AWS SageMaker | AWS 통합, 자동 재훈련 | 사용량 기반 | AWS 환경 |
"지난주부터 추천 모델의 CTR이 15% 하락했는데, Evidently 대시보드에서 'user_age' 피처의 PSI가 0.25로 감지됐습니다. 신규 마케팅 캠페인으로 유입된 고객층의 연령대가 달라진 것 같아요. 새 데이터로 재훈련 파이프라인을 트리거하겠습니다."
"데이터 드리프트는 Covariate Drift와 Concept Drift로 구분됩니다. Covariate Drift는 입력 분포 P(X) 변화이고, Concept Drift는 P(Y|X) 변화입니다. 감지에는 통계적 테스트(KS, Chi-Square)와 분포 거리(PSI, KL Divergence)를 사용하고, 저는 Evidently와 Prometheus-Grafana 조합으로 자동화된 모니터링 시스템을 구축한 경험이 있습니다."
"드리프트 대응 전략은 상황에 따라 다릅니다. 점진적 드리프트는 정기 재훈련으로 대응하고, 급격한 드리프트는 즉시 알림과 함께 폴백 모델로 전환이 필요합니다. 온라인 러닝이나 Continual Learning도 고려할 수 있지만, 모델 안정성 관점에서 주의가 필요합니다."
모델 배포만 하고 드리프트 모니터링을 구축하지 않으면 성능 저하를 늦게 발견합니다. 배포와 동시에 모니터링을 설정하세요.
피처마다 드리프트 민감도가 다릅니다. 중요 피처는 낮은 임계값(PSI 0.1), 덜 중요한 피처는 높은 임계값(PSI 0.25)을 설정하세요.
드리프트 감지 → 알림 → 자동 재훈련 → A/B 테스트 → 배포까지 자동화된 파이프라인을 구축하세요. 정기 재훈련 일정도 함께 운영하면 좋습니다.