Module 9

Evidently AI로 데이터 드리프트 감지

MLOps 과정 | 직접 구현 → 전문 도구로 교체

Section 1

왜 Evidently AI인가?

지금까지 배운 것

Module 7
드리프트 개념
PSI 이론
Module 8
detect_drift.py
직접 구현
Module 9
Evidently AI
전문 도구

Module 8: 원리를 이해하기 위해 직접 구현 (~170줄)
Module 9: 현업에서 사용하는 전문 도구로 교체 (~50줄)

직접 구현 vs Evidently

항목detect_drift.py (직접)Evidently AI
통계 검정평균 비교 (단순)Wasserstein, KS, Jensen-Shannon (자동)
결과 확인터미널 출력만터미널 + HTML 시각화
코드량~170줄~50줄
데이터 타입수동 구분자동 감지
현업 사용교육용GitHub 7,300+ Stars

원리를 직접 구현해서 이해했으니, 이제 실무 도구로 넘어갑니다.

Evidently AI란?

ML 모니터링을 위한 오픈소스 라이브러리

학습 데이터(Reference)와 운영 데이터(Current)를 비교하여
드리프트를 자동으로 감지하고, HTML 리포트를 생성합니다.

  • GitHub Stars: 7,300+
  • MLOps 표준 도구로 자리잡음
  • 데이터 드리프트 감지 분야에서 가장 널리 사용
  • Evidently Cloud (SaaS)도 제공

Section 2

핵심 개념 3가지

3가지만 알면 됩니다

Reference Data
"정상" 기준 데이터
loan_data.csv
(모델 학습에 사용)
Current Data
비교 대상 데이터
prediction_logs.csv
(운영 중 수집된 데이터)
Report
두 데이터 비교 결과
HTML 리포트
(시각화 + 통계 수치)

Reference
(학습 데이터)
Evidently
비교 분석
Current
(운영 데이터)

통계 검정을 자동으로 선택

데이터 타입과 크기에 따라 최적의 검정 방법을 자동 선택합니다.
우리가 직접 고를 필요 없습니다!

데이터 타입크기자동 선택되는 검정
수치형1,000건 이상Wasserstein distance (normed)
수치형1,000건 미만K-S 검정 (p-value)
범주형-Jensen-Shannon distance

Module 8: "평균 차이 20% 이상이면 드리프트" (단순 규칙)
Evidently: 통계적으로 검증된 방법 (더 정확)

Section 3

설치 & 핵심 코드

설치

pip install evidently

# 설치 확인
python -c "import evidently; print(evidently.__version__)"
# 출력: 0.7.21

핵심 코드 5줄

import pandas as pd
from evidently import Report
from evidently.presets import DataDriftPreset

# 데이터 로드
train_df = pd.read_csv("data/loan_data.csv")
pred_df  = pd.read_csv("data/prediction_logs.csv")

feature_cols = ["나이", "연소득", "근속연수", "신용점수",
                "기존대출건수", "연간카드사용액", "부채비율",
                "대출신청액", "대출기간",
                "성별", "주거형태", "대출목적", "상환방식"]

ref = train_df[feature_cols]   # Reference (학습)
cur = pred_df[feature_cols]    # Current (운영)

# === 이 3줄이 전부입니다! ===
report = Report(metrics=[DataDriftPreset()])
snapshot = report.run(reference_data=ref, current_data=cur)
snapshot.save_html("drift_report.html")

핵심 3줄 해석

# 1. Report 객체 생성 — "어떤 분석을 할지" 지정
report = Report(metrics=[DataDriftPreset()])

# 2. 분석 실행 — Reference와 Current를 비교
#    Snapshot 객체가 반환됨
snapshot = report.run(reference_data=ref, current_data=cur)

# 3. HTML 리포트 저장
snapshot.save_html("drift_report.html")

DataDriftPreset() = "데이터 드리프트 분석해줘"
Evidently가 알아서 모든 피처의 통계 검정을 수행합니다.

import 경로 주의!

v0.7 (현재) - 정상
from evidently import Report
from evidently.presets import DataDriftPreset
구버전 - 에러!
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset

인터넷에서 Evidently 예제를 검색하면 구버전 코드가 많이 나옵니다.
반드시 from evidently import Report를 사용하세요!

Section 4

실행 & 결과 확인

detect_drift_evidently.py 실행

cd 01-loan-api-server
python detect_drift_evidently.py

이 스크립트는 핵심 3줄 + 결과를 보기 좋게 출력하는 코드입니다.
터미널 출력과 HTML 리포트를 모두 생성합니다.

실행 결과

나이
0.543
DRIFT!
연소득
0.710
DRIFT!
근속연수
0.662
DRIFT!
신용점수
0.705
DRIFT!
부채비율
0.984
DRIFT!
성별
OK
상환방식
OK

드리프트 피처: 11/13개 (84.6%) → 재학습이 필요합니다!

HTML 리포트

drift_report.html을 브라우저에서 열면:

  • 전체 드리프트 요약 — 몇 개 피처에서 감지됐는지
  • 피처별 분포 비교 그래프 — Reference vs Current 히스토그램
  • 통계 검정 결과 — 검정 방법, 점수
  • 드리프트 여부 — 피처별 DRIFT / OK

터미널은 숫자만 보이지만, HTML에서는
"왜 이 피처에서 드리프트가 발생했는지" 그래프로 바로 이해 가능

Section 5

코드 상세 분석

결과 추출: metric_results

import re

for key, val in snapshot.metric_results.items():
    # "Value drift for 나이" 형태의 결과만 추출
    if val.display_name.startswith("Value drift for "):
        col_name = val.display_name.replace("Value drift for ", "")

        # widget에서 드리프트 정보 추출
        label = val.widget[0].params["counters"][0]["label"]
        is_drift = "detected" in label and "not detected" not in label

        method = re.search(r"method: (.+?)\.", label).group(1)
        score = float(re.search(r"score: (.+?)$", label).group(1))

        print(f"{col_name}: {'DRIFT!' if is_drift else 'OK'}")

widget label 해석

각 피처의 결과는 문자열로 들어있습니다:

드리프트 감지 시
"Data drift detected.
Drift detection method: Wasserstein distance (normed).
Drift score: 0.543"
드리프트 미감지 시
"Data drift not detected.
Drift detection method: Jensen-Shannon distance.
Drift score: 0.026"

정규표현식으로 method와 score를 파싱합니다.

v0.7 API 주의점

# 전체 드리프트 비율 가져오기
for key, val in snapshot.metric_results.items():
    if val.display_name == "Count of Drifted Columns":
        # get_share()는 SingleValue 객체를 반환!
        # 반드시 .value를 붙여야 합니다

        drift_share = val.get_share().value   # 0.846
        drift_count = val.get_count().value   # 11.0

잘못된 코드 (에러!)
share = val.get_share()
# SingleValue 객체 → float 변환 불가!
올바른 코드
share = val.get_share().value
# 0.846 → 정상!

Section 6

기존 파이프라인에 적용

1단계만 교체하면 됩니다

단계Module 8Module 9 (교체)
1. 드리프트 감지 detect_drift.py detect_drift_evidently.py
2. 재학습 retrain.py 동일
3. 배포 deploy_model.py 동일

드리프트 감지
detect_drift_evidently.py
재학습
retrain.py
배포
deploy_model.py

교체 후 실행 순서

cd 01-loan-api-server

# 1. 드리프트 감지 (Evidently 버전)
python detect_drift_evidently.py

# → drift_report.html을 브라우저에서 열어 확인

# 2. 재학습 필요시
python retrain.py

# 3. 배포 결정시
python deploy_model.py

기존 파이프라인을 유지하면서 드리프트 감지만 전문 도구로 업그레이드

Section 7

Evidently 추가 기능

다양한 분석 Preset

Preset용도언제 사용
DataDriftPreset입력 데이터 분포 변화이번 실습
DataQualityPreset결측값, 이상치, 품질 체크데이터 파이프라인
TargetDriftPreset예측 결과 분포 변화모델 성능 저하 감지
ClassificationPreset분류 모델 성능 리포트모델 평가
RegressionPreset회귀 모델 성능 리포트모델 평가

여러 Preset 동시 사용

from evidently import Report
from evidently.presets import DataDriftPreset, DataQualityPreset

# 여러 Preset을 동시에 사용 가능
report = Report(metrics=[
    DataDriftPreset(),
    DataQualityPreset(),
])
snapshot = report.run(reference_data=ref, current_data=cur)
snapshot.save_html("full_report.html")

metrics 리스트에 원하는 Preset을 추가하기만 하면 됩니다.
한 번에 드리프트 + 데이터 품질을 함께 확인할 수 있습니다.

Section 8

전체 정리

Module 9 정리

  • Evidently AI = 현업 표준 드리프트 감지 도구
  • 핵심 코드 3줄이면 드리프트 감지 가능
  • 통계 검정을 자동 선택 (Wasserstein, KS, Jensen-Shannon)
  • HTML 리포트로 시각적 분석 가능
  • 기존 파이프라인에서 1단계만 교체하면 적용 완료
  • import 경로: from evidently import Report

Module 8에서 원리를 이해했고,
Module 9에서 실무 도구를 익혔습니다.

이것이 MLOps 학습의 올바른 흐름입니다!

실습

cd 01-loan-api-server

# 1. Evidently 설치
pip install evidently

# 2. 드리프트 감지 실행
python detect_drift_evidently.py

# 3. HTML 리포트 확인
# drift_report.html을 브라우저에서 열기

# 4. 재학습이 필요하면
python retrain.py
python deploy_model.py

확인 포인트:
- 어떤 피처에서 드리프트가 감지되었는가?
- 각 피처에 어떤 통계 검정이 사용되었는가?
- HTML 리포트에서 분포 그래프를 확인했는가?