모델 설명 (실시간 SHAP XAI)
배포된 모델의 예측을 실시간 Top-K SHAP 설명으로 해석하고, 격리된 샌드박스에서 What-if 실험(입력값을 바꿔가며 설명이 어떻게 변하는지)을 수행하는 워크플로우를 안내합니다. 신용평가·여신심사처럼 "왜 이 예측이 나왔는가"를 근거와 함께 제시해야 하는 시나리오를 위한 기능입니다.

이 기능이 푸는 문제
| 요구 | GenD 구현 |
|---|---|
| 모델 버전별 설명기 사전 생성 | MLflow run 에 explainer/explainer.pkl 아티팩트로 부착 + gend.explainer=ready 태그 |
| 예측 서비스 ↔ 설명 서비스 분리 | 설명 전용 런타임 gend-xai 가 예측 predictor 와 독립 배포·확장·장애격리 |
| Top-K 중심 빠른 실시간 설명 | tree 모델은 shap.TreeExplainer 로 ms 단위 계산, 기여도 상위 K개만 반환 |
| 격리 샌드박스 What-if | 입력 섭동 → 예측+설명 재계산 → 시나리오 저장/비교 (원본 서빙 트래픽과 분리) |
| 입력·모델버전·데이터버전·설명결과 감사 | 모든 explain 호출이 HMAC 체인 감사 로그로 기록 (재현 3-tuple) |
사전 준비
- 관리자 또는 analyst 역할로 로그인
- tree 기반 모델이 배포되어 있을 것 (예:
demo_credit_risk— GradientBoosting 신용위험 데모) - 해당 모델 버전에 SHAP explainer 아티팩트가 생성되어 있을 것
데모 환경 시드:
# 1) tree 기반 demo_credit_risk 모델 등록 (GradientBoostingClassifier)
make seed-demo-ml
# 2) Phase 1 explainer asset materialize — explainer.pkl 생성 + gend.explainer=ready 태그
# Dagster UI 에서 demo_credit_risk_explainer asset 을 실행하거나 job 을 launch
실시간 SHAP 의 핵심은 TreeExplainer 입니다. 트리 앙상블(GradientBoosting·RandomForest 등)은 정확한 SHAP 값을 ms 단위로 계산할 수 있어 "실시간 설명"이 가능합니다. 선형 모델(LogisticRegression)은 TreeExplainer 대상이 아니므로, 데모 신용 모델은 GradientBoosting 으로 구성되어 있습니다.
demo_credit_risk 는 사람단위 실제 범위(age 18–70 · income 15k–150k · credit_history_len 0–30)로 학습됩니다. 트리 모델의 SHAP 은 구간상수(piecewise-constant)라, 입력이 학습된 split threshold 를 넘지 못하면 예측·설명이 값 그대로 동일하게 나옵니다. 데모 모델을 표준정규(~[-3, 3]) 같은 다른 스케일로 학습해 두고 age=35·income=50000 같은 사람단위 값을 서빙하면, 모든 split 을 지나쳐(saturate) 무엇을 입력해도 예측·SHAP 이 변하지 않는 것처럼 보입니다. What-if 를 실습할 때는 아래 세 페르소나처럼 학습 분포 안의 값을 사용하세요.
| 페르소나 | age | income | credit_history_len | 기대 예측 |
|---|---|---|---|---|
| 저리스크 | 25 | 30,000 | 2 | 거절(0) |
| 중간 | 45 | 80,000 | 12 | 경계(0) |
| 고리스크 | 65 | 140,000 | 25 | 승인(1) |
세 페르소나는 회귀 가드 E2E(ui/tests/whatif-responsiveness-e2e.spec.ts, 시드 픽스처 ui/tests/whatif-personas.ts)의 데이터 소스이자 이 문서 스크린샷의 캡처 소스입니다.
1. 모델 선택
ML 허브 → 모델 → 모델 설명 탭(/ml-hub/models?tab=explain)으로 이동합니다. ready 상태의 배포가 칩 목록으로 표시되며, 칩을 클릭하거나 입력란에 엔드포인트 이름을 입력하고 적용 을 누릅니다.
호출(ModelGrant.invoke) 권한이 없는 배포는 칩이 비활성화되고 권한 없음 배지가 함께 표시됩니다. 비활성 칩을 클릭하면 선택되는 대신 관리자에게 권한을 요청하라는 안내가 표시됩니다 — 제출 후 403 을 만나는 막다른 길을 사전에 차단합니다.
2. 피처 입력 → Top-K 설명
모델을 선택하면 피처 입력 폼이 나타나고, 학습 시점 피처 스키마를 조회해 피처 이름이 자동으로 채워집니다 — 값만 입력하면 됩니다. 모든 피처에 값이 입력되면 짧은 디바운스 후 설명이 자동 계산됩니다. 일부 값이 비어 있으면 "값 입력 대기 중: …" 안내가 표시되고 호출되지 않습니다.

JSON 으로 직접 붙여넣고 싶으면 JSON 붙여넣기 토글을 사용합니다. 폼 ↔ JSON 전환 시 입력이 보존되고, 잘못된 JSON 은 입력을 유지한 채 인라인 오류로 표시됩니다.
{ "age": 35, "income": 50000, "credit_history_len": 5 }
입력이 완성되면 화면에 Top-K SHAP bar 가 렌더됩니다. 각 막대는 해당 feature 가 예측을 양(+)/음(−) 방향으로 얼마나 밀었는지를 나타내며, 막대 라벨에 피처 = 입력값 이 함께 표시되어 기여도와 입력을 한눈에 읽을 수 있습니다.
카드 헤더에는 모델/버전·기준값(base value)과 함께 예측값(회귀) 또는 예측 클래스(분류)가 표시됩니다. ⓘ 아이콘에 마우스를 올리면 기준값·기여도의 단위(모델 원시 출력 공간, 예: log-odds)와 "기준값 + 기여도 합 = 원시 출력" 관계를 설명하는 도움말을 볼 수 있습니다.

3. What-if 시나리오 (격리 샌드박스)
What-if 패널에서 feature 값을 바꾸면 예측과 설명이 즉시 재계산됩니다. 분석에 쓰는 샘플 데이터만 실시간으로 재예측하므로, 운영 중인 예측 서비스 트래픽에는 영향을 주지 않습니다. 비교의 기준(베이스라인)은 폼/JSON 으로 입력한 섭동 전 원본 instance 의 설명 스냅샷으로 고정되므로, 값을 여러 번 바꿔도 항상 "원본 대비" 변화를 읽을 수 있습니다.
따라 해보기 — 저리스크 → 고리스크:
- 베이스라인으로 저리스크 페르소나(
age 25 · income 30,000 · credit_history_len 2)를 입력합니다. 헤더의 예측 클래스는 0(거절), Top-K 에서age·income이 예측을 아래로(−) 밀고 있습니다. - What-if 입력을 고리스크(
age 65 · income 140,000 · credit_history_len 25)로 바꾸면 —1개 변경됨배지가 뜨고 짧은 디바운스 후 헤더 예측이 1(승인) 로 뒤집히며, 같은 피처들의 SHAP 부호가 양(+)으로 바뀝니다. 입력이 결과를 실제로 움직이는 것을 한 화면에서 확인할 수 있습니다. - 시나리오 저장 을 누르면 섭동 입력이 재예측·재설명되어 비교표에 한 행으로 추가되고, 베이스라인 행과 나란히 예측값·주요 feature 가 대비됩니다.

비교표에서 한 행을 클릭하면 베이스라인 대비 Top-K 기여도가 좌우로 나란히 그려져, 어떤 피처가 얼마나 달라졌는지 부호·크기까지 비교할 수 있습니다.

시나리오 저장은 섭동 입력을 재예측 + 재설명합니다. 재설명(Top-K)은 gend-xai 가 처리하지만, 재예측은 배포된 KServe 예측 엔드포인트를 호출합니다. 따라서 What-if 시나리오 평가는 (1) 예측 엔드포인트가 v2(Open Inference Protocol) 로 노출되어 feature-dict 어댑터의 모델 메타데이터 조회가 가능하고, (2) 서빙 런타임의 sklearn 버전이 모델 학습 버전과 정합해야 합니다. 설명(Top-K)만 필요하면 예측 엔드포인트 없이도 동작합니다.
아키텍처 노트
- 분리 런타임: 설명은
gend-api가 직접 계산하지 않고 클러스터 내부의gend-xaiService(gend-xai.<ns>.svc.cluster.local/explain)로 위임됩니다. explainer 아티팩트가 아직 없으면gend-xai는 graceful 503 을 반환하고, 시드 후 정상 Top-K 를 반환합니다. - 데이터 버전: 설명 감사 로그의
data_version은 모델이 학습된 MLflowrun_id입니다 — 같은 입력·같은 모델버전·같은 데이터버전이면 같은 설명이 재현됩니다. - 감사: 모든 explain 호출은 입력 해시·모델명·모델버전·데이터버전·Top-K 와 함께 HMAC 체인 감사 로그(→ OpenSearch WORM)로 기록됩니다.