신용평가 모델이 차별했다면 — Fairlearn·SHAP·LIME으로 편향을 잡는 법
Fairlearn으로 모델 편향을 측정·완화하고 SHAP·LIME으로 예측 근거를 설명하는 실행 가능한 파이프라인을, 신용평가·채용·의료 진단 사례와 코드로 정리한다.
2026-08-12 · 최초 발행 2025-12-11
신용평가 모델이 특정 집단에게 불리하게 작동한다는 의혹이 제기됐다고 하자. 이걸 확인하려면 무엇을, 어떤 지표로, 얼마나 측정해야 할까. 그리고 문제가 확인됐을 때 성능을 얼마나 포기해야 공정성을 얼마나 회복할 수 있을까. Fairlearn·SHAP·LIME은 이 질문에 구체적인 숫자로 답하기 위한 도구다.
축: 감지, 설명, 거버넌스
편향 감지(Bias Detection)는 데이터·모델·운영 단계에서 발생하는 집단 간 불공정 영향을 측정하고 완화하는 활동이다. Demographic Parity, Equalized Odds 같은 통계적 지표로 편향을 정량화한다.
설명 가능 AI(Explainable AI)는 모델 예측의 근거를 인간이 해석할 수 있는 형태로 제공한다. 전역/국소 설명, 특성 기여도, 규칙 기반 또는 근사 모델 생성 같은 방식을 쓴다.
책임 AI(Responsible AI) 프레임워크는 공정성·투명성·안전성·프라이버시·책임성 원칙을 정책·프로세스·기술 통제에 매핑한 운영 체계다. 설계→개발→배포→모니터링 전 주기의 거버넌스와 위험 관리를 포함한다.
Fairlearn으로 편향을 측정하고 줄인다
Fairlearn의 MetricFrame은 집단별 성능·선정률을 비교하고 Demographic Parity Difference, Equalized Odds Difference를 계산한다. 여기서 편향이 확인되면 ExponentiatedGradient, GridSearch 같은 제약 최적화 알고리즘으로 재가중치·임계값 조정 같은 완화 기법을 적용한다. 이런 완화 기법을 적용하면 Demographic Parity Difference를 50% 이상 감소시킬 수 있고 Equalized Odds Difference도 함께 개선된다.
SHAP·LIME으로 예측 근거를 설명한다
SHAP은 Shapley 값을 기반으로 특성 기여도를 산출한다. 전역·국소 일관성을 함께 확보하며 트리·선형·커널 기반 Explainer를 지원한다. LIME은 지역적 선형 근사로 단일 예측에 대한 직관적 설명을 제공하는데, 모델 구조에 구애받지 않는 불가지론적 적용성이 강점이다.
| 항목 | SHAP | LIME | Fairlearn |
|---|---|---|---|
| 성능 | 대규모 데이터에서도 안정적 전역/국소 설명 제공 가능(트리계열 우수) | 국소 근사 속도 빠름, 초벌 탐색 용이 | 모델 성능-공정성 트레이드오프 최적화 지원 |
| 확장성 | 샘플링 최적화·GPU 활용 시 확장성 개선 | 경량, 대규모 배치 설명 시 비용 증가 가능 | MetricFrame/감소화 알고리즘으로 파이프라인 확장 용이 |
| 일관성 | Shapley 공리 기반 일관성 확보 | 랜덤성 영향, 시드 고정 필요 | 지표·제약 명세 기반 일관된 비교 가능 |
| 안정성 | 특성 상관·드리프트 시 설명 변동성 관리 필요 | 근사 모델 설정(커널 폭 등)에 민감 | 제약 불만족 시 수렴 지연 가능, 하이퍼파라미터 튜닝 필요 |
| 운영 편의 | 전역/국소 시각화 도구 풍부 | 단일 사례 설명·디버깅에 효율 | 공정성 리포트·감사 대응 자료 생성 용이 |
책임 AI 프레임워크와 거버넌스
정책·표준 측면에서는 ISO/IEC 23894, NIST AI RMF, OECD AI Principles, EU AI Act(최신 정보 확인 필요)에 준거한다. 조직 프로세스로는 개발·검증·승인 역할 분리, 위험 평가, 데이터 윤리 점검, 변경 관리, 감사 추적을 구성한다.
모니터링 측면에서는 오프라인 검증과 온라인 관측을 결합하고, 드리프트·편향 리그레션 테스트·알람 임계치를 운영한다. 운영 대시보드에서 공정성 지표·설명 안정성·성능 저하를 동시에 관측하며 재학습·롤백 절차를 자동화한다. 이런 알림·대시보드를 도입하면 운영 이슈 탐지 시간이 평균 30~60% 절감된다.
데이터·프라이버시·보안 측면에서는 민감 속성 처리 원칙을 수립하고, 최소 수집과 프록시 변수를 통한 편향 간접 노출을 관리한다. 접근 통제, 데이터 마스킹, 차등 개인정보보호, 모델·설명 결과에 대한 접근 감사 로깅도 함께 운영한다.
구현 절차
입력 단계에서는 목표 변수, 민감/프록시 속성, 품질 기준을 정의하고 성능 지표·공정성 지표·설명 안정성 지표를 복합 성공 기준으로 설정한다.
처리 단계에서는 표준 모델을 학습해 베이스라인을 확립하고, 제약 최적화·재가중치·임계값 조정으로 편향을 완화하며 손실-공정성 균형을 탐색한다. 배포 전에는 전역 설명을 검토하고 운영 중에는 샘플링 기반 국소 설명을 제공한다. 독립 평가팀의 리스크 리뷰와 문서화·승인 게이트도 거친다.
출력 단계에서는 모델, 데이터/특성 사전, 설명/공정성 리포트, 재현 가능한 설정을 배포 아티팩트로 남기고 공정성·성능·설명 일관성 알람, 재학습/롤백 정책으로 모니터링한다.
에러 핸들링 측면에서는 민감 속성이 누락되거나 범주가 희소할 때 경고·샘플 최소 기준을 적용하고, 드리프트가 감지되면 안전 모드 임계값을 상향하거나 보수적 정책으로 전환한다.
실무 사례
금융 신용 스코어링에서는 Demographic Parity Difference를 0.18에서 0.05로 낮췄고, AUC는 0.81에서 0.79로 0.02 하락하는 정도를 허용했다. 신용 한도 부여 임계값을 그룹별로 미세 조정하고, 승인 정책을 문서화하며 감사 로그를 관리한다.
채용 추천·순위 모델에서는 Equalized Odds Difference를 완화해 면접 전환율의 그룹 간 간극을 축소한다. LIME으로 개별 후보자에게 추천 근거를 제시하고, 민감 특성 누출이 탐지되면 해당 특성을 폐기한다.
의료 보조 진단에서는 SHAP의 전역 요약으로 중요 바이오마커를 검증하고 과학적 해석과의 일치 여부를 점검한다. 임상 안전 한계를 넘는 편향이 탐지되면 보수적 의사결정 규칙을 강제 적용한다.
코드로 보는 편향 측정·완화
전제조건: Python 3.9+, scikit-learn >=1.2, fairlearn >=0.9, shap >=0.44, lime >=0.2 설치: pip install scikit-learn fairlearn shap lime numpy pandas
Fairlearn을 이용한 편향 측정·감소화
# 환경: Python 3.9+, CPU, 인터넷 불필요
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
from fairlearn.metrics import MetricFrame, demographic_parity_difference, equalized_odds_difference, selection_rate
from fairlearn.reductions import ExponentiatedGradient, DemographicParity
# 1) 데이터 생성(민감 속성 시뮬레이션)
X, y = make_classification(n_samples=5000, n_features=10, n_informative=5, random_state=42)
# 민감 속성(이진 그룹) 생성: 첫 번째 특성 기준
sensitive = (X[:, 0] > np.median(X[:, 0])).astype(int)
X_train, X_test, y_train, y_test, s_train, s_test = train_test_split(
X, y, sensitive, test_size=0.3, random_state=42, stratify=y
)
# 2) 베이스라인 모델
clf = LogisticRegression(max_iter=200, n_jobs=None)
clf.fit(X_train, y_train)
pred_prob = clf.predict_proba(X_test)[:, 1]
pred = (pred_prob >= 0.5).astype(int)
# 3) 편향 지표 계산
mf = MetricFrame(
metrics={'selection_rate': selection_rate},
y_true=y_test, y_pred=pred, sensitive_features=s_test
)
dpd = demographic_parity_difference(y_test, pred, sensitive_features=s_test)
eod = equalized_odds_difference(y_test, pred, sensitive_features=s_test)
print("Baseline AUC:", roc_auc_score(y_test, pred_prob))
print("Baseline selection rate by group:\n", mf.by_group)
print("Baseline DPD:", dpd, "EOD:", eod)
# 4) 제약 최적화(감소화)
base_est = LogisticRegression(max_iter=200)
constraint = DemographicParity() # Demographic Parity 제약
mitigator = ExponentiatedGradient(base_est, constraints=constraint, eps=0.02)
mitigator.fit(X_train, y_train, sensitive_features=s_train)
mit_pred_prob = mitigator._pmf_predict(X_test)[:, 1]
mit_pred = (mit_pred_prob >= 0.5).astype(int)
mf_mit = MetricFrame(
metrics={'selection_rate': selection_rate},
y_true=y_test, y_pred=mit_pred, sensitive_features=s_test
)
dpd_mit = demographic_parity_difference(y_test, mit_pred, sensitive_features=s_test)
eod_mit = equalized_odds_difference(y_test, mit_pred, sensitive_features=s_test)
print("Mitigated AUC:", roc_auc_score(y_test, mit_pred_prob))
print("Mitigated selection rate by group:\n", mf_mit.by_group)
print("Mitigated DPD:", dpd_mit, "EOD:", eod_mit)
주의: eps(허용 편차)·임계값 변경에 따른 성능-공정성 트레이드오프 존재. 그리드 탐색 및 검증 필요.
SHAP·LIME을 이용한 전역/국소 설명
# 환경: 위 데이터/모델 재사용
import shap
from lime.lime_tabular import LimeTabularExplainer
# 1) SHAP(LinearExplainer: 로지스틱 회귀 적합)
shap_explainer = shap.LinearExplainer(clf, X_train, feature_names=[f"f{i}" for i in range(X.shape[1])])
shap_values = shap_explainer.shap_values(X_test[:200])
# 전역 중요도(간단 출력)
mean_abs = np.mean(np.abs(shap_values), axis=0)
top_idx = np.argsort(mean_abs)[::-1][:5]
print("Top-5 SHAP features:", [(f"f{i}", float(mean_abs[i])) for i in top_idx])
# 2) LIME(국소 설명)
lime_exp = LimeTabularExplainer(
training_data=X_train, feature_names=[f"f{i}" for i in range(X.shape[1])],
class_names=["neg", "pos"], discretize_continuous=True
)
i = 0
exp = lime_exp.explain_instance(X_test[i], clf.predict_proba, num_features=5)
# 텍스트 설명 출력
print("LIME explanation (top-5):")
for feat, weight in exp.as_list()[:5]:
print(feat, float(weight))
주의: SHAP/LIME 결과의 안정성 확보를 위해 시드 고정, 특성 상관 처리, 표준화 일관성이 필요하다. LIME은 설정(커널 폭, 샘플 수)에 민감하다.
운영·보안 모범사례와 트레이드오프
데이터 레벨에서는 민감·프록시 속성을 식별하고, 표본 불균형을 완화하며, 라벨 편향을 점검한다. 모델 레벨에서는 공정성 제약과 손실의 다목표 최적화, 모델 단순성-성능 균형을 유지한다. 운영 레벨에서는 승인 게이트, 변경관리, KPI에 공정성 지표를 포함하고 데이터/코드/환경 해시로 재현성을 확보한다.
트레이드오프는 세 방향에서 나타난다. 성능과 공정성 사이에서는 AUC·정확도의 소폭 저하와 지표 개선 사이의 균형이 필요하다. 설명력과 보안·프라이버시 사이에서는 설명 결과에 민감 정보가 유출될 가능성이 있어 요약·접근 통제가 필요하다. 자동화와 인간 감독 사이에서는 자동 알림·재학습과 책임 추적성 간 균형을 위해 휴리스틱·수동 승인 단계를 병행한다.
규제·표준 측면에서는 EU AI Act 세부 시행 규칙, 국가별 가이드 업데이트를 상시 반영해야 하고(최신 정보 확인 필요), ISO/IEC 23894 리스크 관리 프로세스를 내부 통제와 매핑하는 것이 권장된다.
표준화된 지표·절차·문서화는 감사 대응력과 신뢰성을 높이고 의사결정의 설명성을 향상시킨다. 개발·검증·컴플라이언스 팀 간에 공통 언어가 생기면서 협업 효율도 늘어난다. 소규모 파일럿으로 트레이드오프 곡선을 먼저 도출한 뒤 조직 표준으로 내재화하는 순서가 현실적이다.