hetest / docs /drift_detection.md
jkkim
Drift Detection κ΅¬ν˜„ β€” SPEC Β§2.4 (4) + μ΄λ‘ Β·κ΅¬ν˜„ λ¬Έμ„œ (PPT + MD)
14ed140
|
Raw
History Blame Contribute Delete
8.73 kB

Drift Detection β€” μ‚¬μš©μž λΆ„λ₯˜ νŒ¨ν„΄ λ³€ν™” 감지

SPEC Β§2.4 (4) κ΅¬ν˜„. λͺ¨λ“ˆ drift_detection.py Β· 라우트 /api/drift/* Β· νƒ­ "Drift 탐지".


1. 문제 β€” λΆ„λ₯˜ νŒ¨ν„΄μ€ μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ λ³€ν•œλ‹€

μ‹€μ œ μ‹œλ‚˜λ¦¬μ˜€

μ‹œμ  상황 κ²°κ³Ό
1κ°œμ›”μ°¨ AI: "이메일=S 민감" β†’ μ‚¬μš©μž λ™μ˜ 정확도 90%
3κ°œμ›”μ°¨ νšŒμ‚¬ μ •μ±… λ³€κ²½: "이메일=O 일반" μ‚¬μš©μž 맀번 μ •μ •, κ°­ λˆ„μ 
κ·Έ λ™μ•ˆ AI λŠ” λ³€ν™” λͺ¨λ¦„ ν•™μŠ΅ μžλ™ 적용 μ „κΉŒμ§€ 정확도 ↓
더 심각 μ‚¬λžŒμ΄ 정확도 ν‘œλ₯Ό 맀일 봐야 μ•Œμ•„μ±” β€” μ•ˆ λ΄„ ν’ˆμ§ˆμ΄ 쑰용히 λ¬΄λ„ˆμ§

핡심 톡찰: λ³€ν™”λ₯Ό μžλ™ κ°μ§€Β·μ•Œλ¦Όν•˜μ§€ μ•ŠμœΌλ©΄ λΆ„λ₯˜κΈ° ν’ˆμ§ˆμ΄ 쑰용히 λ¬΄λ„ˆμ§„λ‹€.

ML μš©μ–΄ β€” drift 의 3 μ’…λ₯˜

  • Concept drift β€” "μ •λ‹΅μ˜ 의미" κ°€ 변함. (μœ„ μ‹œλ‚˜λ¦¬μ˜€: 이메일 λ“±κΈ‰ κΈ°μ€€ λ³€κ²½)
  • Data drift β€” μž…λ ₯ 데이터 뢄포가 변함. (예: μƒˆλ‘œμš΄ λ¬Έμ„œ μœ ν˜• λ“±μž₯)
  • User drift β€” μ‚¬μš©μž νŒλ‹¨ 기쀀이 변함. (쑰직 μ •μ±… / μƒˆ λ‹΄λ‹Ήμž / ν•™μŠ΅ λ“±)

λ³Έ λͺ¨λ“ˆμ€ κ²°μ • 이λ ₯μ—μ„œ μœ„ μ„Έ κ°€μ§€λ₯Ό ν†΅ν•©μ μœΌλ‘œ κ°μ§€ν•©λ‹ˆλ‹€ (정확도·갭·entity 뢄포).


2. μ•Œκ³ λ¦¬μ¦˜ β€” 3 μ§€ν‘œλ‘œ drift μΈ‘μ •

μœˆλ„μš° λΆ„ν• 

κ²°μ • 이λ ₯을 μ‹œκ°„μˆœ μ •λ ¬ β†’ 졜근 N건 (window A) vs 이전 N건 (window B) 으둜 λΆ„ν• .

μ‹œκ°„ ←──────────────────────────────────→
   β”Œβ”€β”€β”€β”€ window B β”€β”€β”€β”€β”β”Œβ”€β”€β”€β”€ window A ────┐
   [b1, b2, ..., bN]    [a1, a2, ..., aN]
       (이전)                 (졜근)

μ§€ν‘œ 1 β€” 정확도 drift

acc_A = (AI = User in A) / |A|
acc_B = (AI = User in B) / |B|

drift = acc_A βˆ’ acc_B
의미 AI κ°€ μ‚¬μš©μžμ™€ μ–Όλ§ˆλ‚˜ 맞고 μžˆλ‚˜μ˜ λ³€ν™”
μž„κ³„κ°’ acc_drift ≀ βˆ’0.15 β†’ alert (λΉ λ₯Έ ν•˜λ½)
acc_drift β‰₯ +0.15 β†’ info (ν•™μŠ΅ 효과 / νŒ¨ν„΄ μ•ˆμ •ν™”)

μ§€ν‘œ 2 β€” 평균 κ°­ drift

gap_A = mean(|AI βˆ’ User|) in A          # O=0, S=1, C=2 μ ˆλŒ€ 차이
gap_B = mean(|AI βˆ’ User|) in B

drift = gap_A βˆ’ gap_B
의미 μ‚¬μš©μžκ°€ 더 큰 폭으둜 μ •μ •ν•˜λŠ”κ°€
μž„κ³„κ°’ gap_drift β‰₯ +0.3 β†’ warn (Oβ†’C 같은 두 단계 μ •μ • 증가)

μ§€ν‘œ 3 β€” Entity 뢄포 drift (PSI)

ratio_A = count_A(ent) / total_A
ratio_B = count_B(ent) / total_B

psi = (ratio_A βˆ’ ratio_B) Β· log( (ratio_A + Ξ΅) / (ratio_B + Ξ΅) )
의미 μ–΄λ–€ PII κ°€ 자주 λ‚˜μ˜€λŠ”μ§€μ˜ λ³€ν™”
μž„κ³„κ°’ `
특수 appeared: 이전에 μ—†λ˜ entity κ°€ β‰₯3건 λ“±μž₯ β†’ info
disappeared: 이전 β‰₯5건 β†’ 졜근 0건 β†’ info

PSI = Population Stability Index β€” 두 λΆ„ν¬μ˜ μ•ˆμ •μ„± μΈ‘μ • (production ML ν‘œμ€€ μ§€ν‘œ).

μ‹œκ³„μ—΄

sliding window (κΈ°λ³Έ 10건씩, 5건 λ‹¨μœ„λ‘œ 이동) 둜 accuracy Β· mean_gap 의 μ‹œκ°„ 좔이λ₯Ό 계산. SVG 차트둜 μ‹œκ°ν™” (νŒŒλž€μ„ =정확도, μ£Όν™©μ„ =평균 κ°­).


3. 데이터 흐름

[κ²°μ • 이λ ₯]    [μœˆλ„μš° λΆ„ν• ]    [3 μ§€ν‘œ 계산]    [μ‹œκ³„μ—΄]      [μ•Œλ¦Ό 생성]
decisions.db β†’ 졜근 N (A)    β†’ acc / gap / PSI β†’ sliding bin β†’ alert/warn/info
μ‹œκ°„μˆœ μ •λ ¬   이전 N (B)                          (κΈ°λ³Έ 10건)   μž„κ³„κ°’ 기반

API 라우트

GET /api/drift/snapshot?window=30
   &accuracy_drop=0.15
   &gap_rise=0.3
   &entity_psi=0.1

β†’ 응닡: recent, previous, drift, entities[], alerts[]

GET /api/drift/timeline?bin=10

β†’ 응닡: bins[] (각 bin 의 idx, n, accuracy, mean_gap, start_at, end_at)


4. μ•Œλ¦Ό μ˜ˆμ‹œ β€” μ‹€μ œ 응닡

검증 μ‹œ 받은 μ‹€μ œ 데이터 (window=8):

{
  "ok": true,
  "window_size": 8,
  "recent":   { "n": 8, "accuracy": 0.375, "mean_gap": 1.00 },
  "previous": { "n": 8, "accuracy": 0.750, "mean_gap": 0.25 },
  "drift": {
    "accuracy_drift": -0.375,   //  ← 37.5%p ν•˜λ½
    "gap_drift":      +0.75     //  ← 갭이 0.75 증가
  },
  "alerts": [
    {
      "severity": "alert",
      "type": "accuracy_drop",
      "message": "정확도 37.5%p ν•˜λ½ β€” λΆ„λ₯˜κΈ°κ°€ μ‚¬μš©μž μ˜λ„μ™€ 점점 어긋남."
    },
    {
      "severity": "warn",
      "type": "gap_rise",
      "message": "평균 갭이 0.75 증가 β€” μ‚¬μš©μžκ°€ 더 큰 폭으둜 μ •μ • 쀑."
    }
  ]
}

이 응닡이 μ˜λ―Έν•˜λŠ” 것

  • 졜근 8건의 정확도가 37.5% 둜, 이전 8건의 75% 보닀 절반.
  • 평균 갭도 0.25 β†’ 1.00 으둜 4λ°°.
  • β†’ μ‚¬μš©μžκ°€ AI 와 점점 λ‹€λ₯Έ λ°©ν–₯으둜 λ§€κΈ°λŠ” νŒ¨ν„΄. ν•™μŠ΅ λ˜λŠ” λ£° κ²€ν†  ν•„μš” μ‹ ν˜Έ.

5. UI ꡬ쑰 β€” "Drift 탐지" νƒ­

μ˜μ—­ λ‚΄μš©
1. 초보 κ°€μ΄λ“œ details/open β€” drift λž€? + 3 μ’…λ₯˜ + 3 μ§€ν‘œ + μž„κ³„κ°’
2. μœˆλ„μš°/μž„κ³„κ°’ μ„€μ • window 크기 + acc/gap/PSI μž„κ³„κ°’ input + "Drift 뢄석 μ‹€ν–‰" λ²„νŠΌ
3. μ•Œλ¦Ό μ˜μ—­ 🚨 alert (λΉ¨κ°•) Β· ⚠️ warn (μ£Όν™©) Β· ℹ️ info (νšŒμƒ‰) μΉ΄λ“œ list. 쒌츑 4px 보더
4. μœˆλ„μš° 비ꡐ μΉ΄λ“œ (3 컬럼) πŸ“Š 졜근 Β· πŸ“Š 이전 Β· ↕ Drift (Aβˆ’B). 각 μΉ΄λ“œ: n / 정확도 / 평균갭 / entity 합계
5. μ‹œκ³„μ—΄ SVG νŒŒλž€μ„ =정확도 (μ’ŒμΆ• 01) Β· μ£Όν™©μ„ =평균갭 (μš°μΆ• 0maxGap) Β· 점 ν‘œμ‹œ + bin size μ‘°μ •
6. Entity 뢄포 λ³€ν™” ν‘œ Entity Type Β· 졜근 Β· 이전 Β· λΉ„μœ¨ λ³€ν™” Β· PSI Β· μƒνƒœ (μ‹ κ·œ/μ†Œλ©Έ/λ³€ν™” 큼)

6. 파일 λ³€κ²½ μš”μ•½

파일 μœ ν˜• λΆ„λŸ‰ λ‚΄μš©
drift_detection.py μ‹ κ·œ ~180쀄 snapshot() / timeline() / _window_stats / _entity_drift / _build_alerts
app.py / app_lite.py μˆ˜μ • +30쀄 Γ— 2 import + 2 라우트
templates/index.html μˆ˜μ • +280쀄 μ‚¬μ΄λ“œλ°” nav 1 + μƒˆ νƒ­ panel + JS (SVG μ‹œκ³„μ—΄)
templates/index.html μˆ˜μ • +30쀄 전체 ꡬ성도 9번째 νŒŒμ΄ν”„λΌμΈ + κ°€μ΄λ“œ κ°±μ‹ 
docs/drift_detection.pptx μ‹ κ·œ 8 μŠ¬λΌμ΄λ“œ 이둠 + κ΅¬ν˜„ + 검증 PPT
docs/drift_detection_theory_and_impl.py μ‹ κ·œ ~350쀄 PPT 생성 슀크립트
docs/drift_detection.md μ‹ κ·œ 이 λ¬Έμ„œ λ§ˆν¬λ‹€μš΄ 정리본

7. 검증 절차

# 1) κ²°μ • 이λ ₯ λˆ„μ  β€” 파일 뢄석 νƒ­μ—μ„œ [C][S][O] 클릭으둜 μ΅œμ†Œ 20+ 건
#    (window=10 κΈ°μ€€)

# 2) μ‚¬μ΄λ“œλ°” β†’ 운영 β†’ "Drift 탐지" 클릭

# 3) window 크기 + μž„κ³„κ°’ μ„€μ • ν›„ "Drift 뢄석 μ‹€ν–‰"
#    β†’ μ•Œλ¦Ό μΉ΄λ“œ, μœˆλ„μš° 비ꡐ 3컬럼, Entity ν‘œ, μ‹œκ³„μ—΄ SVG λͺ¨λ‘ ν‘œμ‹œ

# 4) bin size λ³€κ²½ ν›„ "μ‹œκ³„μ—΄ μƒˆλ‘œκ³ μΉ¨" β€” 정확도·갭 좔이 확인

# 5) curl 직접 검증
curl "http://127.0.0.1:5050/api/drift/snapshot?window=8"
curl "http://127.0.0.1:5050/api/drift/timeline?bin=5"

검증 κ²°κ³Ό (ν˜„μž¬ λ…ΈνŠΈλΆ)

  • accuracy_drift = βˆ’37.5%p β†’ alert
  • gap_drift = +0.75 β†’ warn
  • 총 μ•Œλ¦Ό 2건 (μ‹€μ œ κ²°μ • 이λ ₯ 기반)

8. ν–₯ν›„ 보완 (선택)

ν•­λͺ© λΆ„λŸ‰ 효과
주기적 μžλ™ μ‹€ν–‰ (cron + Slack/email μ•Œλ¦Ό) 1일 μ‚¬λžŒμ΄ 탭을 μ•ˆ 봐도 μ•ŒλžŒ
KS κ²€μ • / CUSUM 2일 ν†΅κ³„μ μœΌλ‘œ 더 μ—„λ°€ν•œ 변화점 탐지
μ‚¬μš©μžλ³„ 뢄리 (user_id 별 drift) 1일 닀쀑 μ‚¬μš©μž ν™˜κ²½
Drift 원인 μžλ™ λΆ„λ₯˜ (concept vs data vs user) 2~3일 진단 μžλ™ν™”
μ•Œλ¦Ό μ˜μ† (alerts.db + λŒ€μ‹œλ³΄λ“œ) 1일 이λ ₯ 좔적

9. SPEC Β§2.4 μ™„λ£Œ μƒνƒœ

ν•­λͺ© λͺ¨λ“ˆ μƒνƒœ
(1) sample weight (ν•™μŠ΅ μ‹œ κ°€μ€‘μΉ˜) train.py βœ…
(2) Platt calibration (신뒰도 보정) platt_calibration.py βœ…
(3) Rule mining (μžλ™ λ£° 후보) rule_mining.py βœ…
(4) Drift detection (νŒ¨ν„΄ λ³€ν™” 감지) drift_detection.py βœ… 이번 κ΅¬ν˜„

SPEC Β§2.4 κ°­ ν™œμš© 4κ°€μ§€ μ „λΆ€ κ΅¬ν˜„ μ™„λ£Œ.


μ°Έκ³ 

  • SPEC: SPEC_νŒŒμΌλΆ„λ₯˜_PoC.md Β§2.4 (4) β€” "User profile drift detection: νŠΉμ • μ‚¬μš©μžμ˜ 갭이 컀지면 β†’ μ •μ±… λ³€κ²½/쑰직 λ³€κ²½ μ‹ ν˜Έλ‘œ μ•Œλ¦Ό"
  • PSI 이둠: Karakoulas (2004) "Empirical Validation of Retail Credit-Scoring Models"
  • 보쑰 자료: docs/drift_detection.pptx β€” μŠ¬λΌμ΄λ“œλ‘œ 같은 λ‚΄μš©