🤖 AI/ML

XAI

Explainable AI

설명 가능한 AI. 모델 의사결정 과정 해석. LIME, SHAP.

📖 상세 설명

XAI(Explainable AI, 설명 가능한 인공지능)는 AI 모델의 의사결정 과정을 인간이 이해할 수 있도록 해석하고 설명하는 기술 분야입니다. 딥러닝 모델이 복잡해지면서 '블랙박스' 문제가 대두되었고, 모델이 왜 특정 결정을 내렸는지 이해할 수 없는 상황이 많아졌습니다. XAI는 이러한 불투명성을 해소하여 AI 시스템에 대한 신뢰를 구축하고, 규제 요건을 충족하며, 모델 개선에 필요한 인사이트를 제공합니다.

XAI 기법은 크게 두 가지로 분류됩니다. 첫째, 모델 자체가 해석 가능한 **Intrinsic(내재적) 방법**으로, 의사결정 트리나 선형 회귀처럼 구조 자체가 투명한 모델을 사용합니다. 둘째, **Post-hoc(사후) 방법**으로, 복잡한 블랙박스 모델을 학습 후 별도의 기법으로 설명합니다. LIME(Local Interpretable Model-agnostic Explanations)과 SHAP(SHapley Additive exPlanations)이 대표적인 post-hoc 기법입니다.

LIME은 개별 예측에 대해 국소적으로 해석 가능한 모델을 학습하여 설명을 생성합니다. 입력 데이터 주변의 샘플들을 생성하고, 원본 모델의 예측을 사용해 단순한 해석 가능 모델(예: 선형 모델)을 학습합니다. SHAP은 게임 이론의 Shapley 값을 기반으로 각 특성(feature)이 예측에 기여한 정도를 수학적으로 정량화합니다. SHAP 값은 일관성(consistency), 지역 정확도(local accuracy), 미귀속(missingness) 등의 이론적 속성을 만족합니다.

XAI는 의료 진단, 금융 신용 평가, 법적 의사결정, 자율주행 등 설명 책임이 요구되는 도메인에서 필수적입니다. EU AI Act와 같은 규제에서도 고위험 AI 시스템에 대한 투명성 요구가 강화되고 있어, XAI의 중요성은 계속 증가하고 있습니다. Grad-CAM(이미지 분류), Attention Visualization(NLP), Feature Importance(정형 데이터) 등 도메인에 특화된 XAI 기법들도 활발히 연구되고 있습니다.

💻 코드 예제

# XAI 예제: SHAP과 LIME을 사용한 모델 설명
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import shap
import lime.lime_tabular

# 데이터 로드 및 준비
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 모델 학습
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

print(f"모델 정확도: {model.score(X_test, y_test):.4f}")

# ============================================
# SHAP (SHapley Additive exPlanations)
# ============================================
# TreeExplainer: 트리 기반 모델에 최적화
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

# 단일 예측에 대한 SHAP 설명
sample_idx = 0
print(f"\n[SHAP] 샘플 {sample_idx}의 예측: {model.predict(X_test.iloc[[sample_idx]])[0]}")
print("주요 기여 특성:")
feature_importance = pd.DataFrame({
    'feature': X.columns,
    'shap_value': shap_values[1][sample_idx]  # class 1에 대한 기여
}).sort_values('shap_value', key=abs, ascending=False)
print(feature_importance.head(5))

# 전체 데이터에 대한 특성 중요도 요약
print("\n[SHAP] 전역 특성 중요도 (평균 절대값):")
mean_shap = np.abs(shap_values[1]).mean(axis=0)
global_importance = pd.DataFrame({
    'feature': X.columns,
    'importance': mean_shap
}).sort_values('importance', ascending=False)
print(global_importance.head(10))

# ============================================
# LIME (Local Interpretable Model-agnostic Explanations)
# ============================================
lime_explainer = lime.lime_tabular.LimeTabularExplainer(
    training_data=X_train.values,
    feature_names=X.columns.tolist(),
    class_names=['악성', '양성'],
    mode='classification'
)

# 단일 예측에 대한 LIME 설명
lime_exp = lime_explainer.explain_instance(
    data_row=X_test.iloc[sample_idx].values,
    predict_fn=model.predict_proba,
    num_features=10
)

print(f"\n[LIME] 샘플 {sample_idx}의 설명:")
print("특성별 기여도:")
for feature, weight in lime_exp.as_list():
    print(f"  {feature}: {weight:.4f}")

# ============================================
# Permutation Importance (순열 중요도)
# ============================================
from sklearn.inspection import permutation_importance

perm_importance = permutation_importance(
    model, X_test, y_test, n_repeats=30, random_state=42
)

print("\n[Permutation Importance] 특성 중요도:")
perm_df = pd.DataFrame({
    'feature': X.columns,
    'importance_mean': perm_importance.importances_mean,
    'importance_std': perm_importance.importances_std
}).sort_values('importance_mean', ascending=False)
print(perm_df.head(10))

📊 성능 & 비용

기법 계산 복잡도 적용 범위 설명 범위
SHAP (TreeExplainer) O(T*L*D) - 빠름 트리 기반 모델 전역 + 국소
SHAP (KernelExplainer) O(N*2^M) - 느림 모든 모델 전역 + 국소
LIME O(N*M) - 중간 모든 모델 국소
Grad-CAM O(1) - 빠름 CNN 모델 국소 (이미지)
Permutation Importance O(M*R) - 중간 모든 모델 전역

* T: 트리 수, L: 최대 잎 노드, D: 특성 차원, N: 샘플 수, M: 특성 수, R: 반복 횟수

성능 팁: SHAP TreeExplainer는 XGBoost, LightGBM 등 트리 기반 모델에서 수초 내 계산 가능. 딥러닝 모델에는 DeepExplainer나 GradientExplainer 사용. LIME은 샘플당 수백 번의 모델 호출이 필요하므로 대규모 배치 분석 시 병렬 처리 권장.

🗣 실무에서 이렇게 말하세요

"이 대출 거절 결정에 대해 XAI로 설명을 붙여주세요."

-> 규제 준수를 위해 고객에게 거절 사유를 설명해야 할 때

"SHAP summary plot 보니까 이 피처가 예측에 가장 큰 영향을 주네요."

-> 모델 디버깅이나 피처 엔지니어링 방향 결정 시

"Grad-CAM으로 모델이 어디를 보고 판단했는지 시각화해 봅시다."

-> 이미지 분류 모델의 주의 영역 확인 시

"EU AI Act 대응으로 XAI 리포트가 필수예요."

-> 고위험 AI 시스템의 규제 준수 논의 시

⚠ 흔한 실수 & 주의사항

SHAP 값을 인과관계로 오해

SHAP 값은 상관관계 기반의 기여도이지, 인과적 영향을 의미하지 않습니다. 특성 A의 SHAP 값이 높다고 해서 A를 바꾸면 결과가 바뀐다는 보장은 없습니다.

LIME의 불안정성 무시

LIME은 무작위 샘플링에 기반하므로, 같은 입력에 대해 실행할 때마다 설명이 달라질 수 있습니다. 중요한 결정에는 여러 번 실행하여 일관성을 확인하세요.

복잡한 모델에 KernelExplainer 무분별 사용

KernelExplainer는 모델에 구애받지 않지만 매우 느립니다. 트리 모델에는 TreeExplainer, 딥러닝에는 DeepExplainer를 사용하세요.

올바른 접근: 목적에 맞는 XAI 기법 선택

전역적 이해가 필요하면 SHAP summary plot, 개별 예측 설명에는 LIME이나 SHAP force plot, 이미지 모델에는 Grad-CAM 등 용도에 맞게 선택하세요.

🔗 관련 용어

📚 더 배우기