2장

공정성 지표

공정성을 측정하는 것은 AI 시스템의 편향을 탐지하고 완화하는 데 필수적입니다. 이 장에서는 공정성 지표의 수학적 기초, 적용 방법, 한계, 그리고 실제 구현에 대해 탐구합니다.

공정성 지표 소개

편향을 해결하기 전에 먼저 측정할 수 있어야 합니다. 공정성 지표는 AI 시스템이 서로 다른 그룹을 공평하게 대우하는지 평가하는 정량적 방법을 제공합니다. 그러나 공정성은 단일적이고 획일적인 개념이 아닙니다. 무엇이 공정한 대우를 구성하는지에 대한 여러 가지, 때로는 경쟁적인 정의가 존재합니다.

불가능성 정리

연구에 따르면 사소한 경우를 제외하고는 모든 공정성 기준을 동시에 만족시키는 것이 수학적으로 불가능합니다. 이는 실무자들이 특정 맥락과 사용 사례에 가장 적합한 공정성 정의에 대해 정보에 입각한 선택을 해야 함을 의미합니다.

그룹 공정성 지표

그룹 공정성 지표는 서로 다른 인구통계학적 그룹 간의 결과를 비교합니다. 이러한 지표는 일반적으로 보호 속성으로 정의된 그룹 간의 통계적 균등성 또는 동등한 대우를 보장하는 데 초점을 맞춥니다.

1. 인구통계학적 균등성 (통계적 균등성)

인구통계학적 균등성은 모든 그룹에서 긍정적 예측의 비율이 동일할 것을 요구합니다. 즉, 의사결정이 보호 속성과 독립적이어야 합니다.

P(Ŷ = 1 | A = a) = P(Ŷ = 1 | A = b) for all groups a, b

여기서 Ŷ는 예측이고 A는 보호 속성(예: 인종, 성별)입니다.

# 인구통계학적 균등성 구현
import numpy as np

def demographic_parity(y_pred, protected_attribute):
    """
    인구통계학적 균등성 지표 계산
    최소값 대 최대값의 긍정 비율 비율 반환
    """
    groups = np.unique(protected_attribute)
    positive_rates = {}

    for group in groups:
        mask = protected_attribute == group
        positive_rate = np.mean(y_pred[mask])
        positive_rates[group] = positive_rate
        print(f"그룹 {group}: {positive_rate:.3f}")

    rates = list(positive_rates.values())
    parity_ratio = min(rates) / max(rates) if max(rates) > 0 else 1.0

    print(f"\n인구통계학적 균등성 비율: {parity_ratio:.3f}")
    print(f"상태: {'통과' if parity_ratio >= 0.8 else '실패'}")

    return parity_ratio, positive_rates

# 사용 예
y_pred = np.array([1, 1, 0, 1, 0, 1, 0, 0, 1, 1])
protected = np.array(['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'])

ratio, rates = demographic_parity(y_pred, protected)

장점:

한계:

2. 동등한 확률

동등한 확률은 그룹 간에 진양성률(TPR)과 위양성률(FPR)이 모두 동일할 것을 요구합니다. 이는 모델의 오류가 동등하게 분산되도록 보장합니다.

P(Ŷ = 1 | Y = y, A = a) = P(Ŷ = 1 | Y = y, A = b)
for y ∈ {0, 1} and all groups a, b
# 동등한 확률 구현
def equalized_odds(y_true, y_pred, protected_attribute):
    """
    각 그룹의 진양성률과 위양성률 계산하여
    동등한 확률 평가
    """
    groups = np.unique(protected_attribute)
    results = {}

    for group in groups:
        mask = protected_attribute == group

        # 진양성률
        tp = np.sum((y_true[mask] == 1) & (y_pred[mask] == 1))
        fn = np.sum((y_true[mask] == 1) & (y_pred[mask] == 0))
        tpr = tp / (tp + fn) if (tp + fn) > 0 else 0

        # 위양성률
        fp = np.sum((y_true[mask] == 0) & (y_pred[mask] == 1))
        tn = np.sum((y_true[mask] == 0) & (y_pred[mask] == 0))
        fpr = fp / (fp + tn) if (fp + tn) > 0 else 0

        results[group] = {'tpr': tpr, 'fpr': fpr}
        print(f"그룹 {group}:")
        print(f"  TPR: {tpr:.3f}, FPR: {fpr:.3f}")

    # 불일치 확인
    tprs = [r['tpr'] for r in results.values()]
    fprs = [r['fpr'] for r in results.values()]

    tpr_disparity = max(tprs) - min(tprs)
    fpr_disparity = max(fprs) - min(fprs)

    print(f"\nTPR 불일치: {tpr_disparity:.3f}")
    print(f"FPR 불일치: {fpr_disparity:.3f}")
    print(f"상태: {'통과' if (tpr_disparity < 0.1 and fpr_disparity < 0.1) else '실패'}")

    return results

# 사용 예
y_true = np.array([1, 1, 0, 1, 0, 0, 1, 0, 1, 0])
y_pred = np.array([1, 1, 0, 1, 0, 1, 1, 0, 0, 0])
protected = np.array(['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'])

results = equalized_odds(y_true, y_pred, protected)

장점:

한계:

3. 동등한 기회

동등한 기회는 동등한 확률의 완화된 버전으로, 그룹 간에 진양성률만 동일할 것을 요구합니다. 이는 위음성이 위양성보다 더 해로운 경우에 특히 관련이 있습니다.

P(Ŷ = 1 | Y = 1, A = a) = P(Ŷ = 1 | Y = 1, A = b)
# 동등한 기회 구현
def equal_opportunity(y_true, y_pred, protected_attribute):
    """
    각 그룹의 진양성률 계산
    """
    groups = np.unique(protected_attribute)
    tprs = {}

    for group in groups:
        mask = protected_attribute == group
        positives = y_true[mask] == 1

        if positives.sum() == 0:
            tprs[group] = None
            print(f"그룹 {group}: 양성 샘플 없음")
            continue

        tp = np.sum((y_true[mask] == 1) & (y_pred[mask] == 1))
        tpr = tp / positives.sum()
        tprs[group] = tpr
        print(f"그룹 {group} TPR: {tpr:.3f}")

    # 불일치 계산
    valid_tprs = [t for t in tprs.values() if t is not None]
    if len(valid_tprs) > 1:
        disparity = max(valid_tprs) - min(valid_tprs)
        print(f"\nTPR 불일치: {disparity:.3f}")
        print(f"상태: {'통과' if disparity < 0.1 else '실패'}")

    return tprs

4. 예측적 균등성 (결과 테스트)

예측적 균등성은 그룹 간에 정밀도(양성 예측 값)가 동일할 것을 요구합니다. 이는 그룹 구성원 자격에 관계없이 긍정적 예측이 동일한 의미를 갖도록 보장합니다.

P(Y = 1 | Ŷ = 1, A = a) = P(Y = 1 | Ŷ = 1, A = b)
# 예측적 균등성 구현
def predictive_parity(y_true, y_pred, protected_attribute):
    """
    각 그룹의 정밀도(PPV) 계산
    """
    groups = np.unique(protected_attribute)
    precisions = {}

    for group in groups:
        mask = protected_attribute == group
        predicted_positive = y_pred[mask] == 1

        if predicted_positive.sum() == 0:
            precisions[group] = None
            continue

        tp = np.sum((y_true[mask] == 1) & (y_pred[mask] == 1))
        precision = tp / predicted_positive.sum()
        precisions[group] = precision
        print(f"그룹 {group} 정밀도: {precision:.3f}")

    # 불일치 확인
    valid_prec = [p for p in precisions.values() if p is not None]
    if len(valid_prec) > 1:
        disparity = max(valid_prec) - min(valid_prec)
        print(f"\n정밀도 불일치: {disparity:.3f}")
        print(f"상태: {'통과' if disparity < 0.1 else '실패'}")

    return precisions

개인 공정성

개인 공정성은 그룹 공정성과 다른 접근 방식을 취합니다. 그룹을 비교하는 대신, 유사한 개인이 유사한 예측을 받아야 한다고 요구합니다.

인식을 통한 공정성

개인 공정성의 원칙은 "유사한 개인은 유사하게 대우받아야 한다"고 명시합니다. 과제는 편향을 인코딩하지 않으면서 의미 있는 방식으로 "유사성"을 정의하는 것입니다.

# 예제: 개인 공정성 확인
from sklearn.metrics.pairwise import cosine_similarity

def check_individual_fairness(X, y_pred, threshold=0.9):
    """
    유사한 개인이 유사한 예측을 받는지 확인
    """
    # 쌍별 유사도 계산
    similarities = cosine_similarity(X)

    fairness_violations = 0
    total_pairs = 0

    for i in range(len(X)):
        for j in range(i + 1, len(X)):
            if similarities[i, j] > threshold:
                total_pairs += 1
                if y_pred[i] != y_pred[j]:
                    fairness_violations += 1

    violation_rate = fairness_violations / total_pairs if total_pairs > 0 else 0
    print(f"유사한 쌍: {total_pairs}")
    print(f"공정성 위반: {fairness_violations}")
    print(f"위반율: {violation_rate:.3f}")

    return violation_rate

불균형 영향 분석

불균형 영향(부정적 영향이라고도 함)은 차별을 평가하는 데 사용되는 법적 개념입니다. "80% 규칙" 또는 "5분의 4 규칙"이 일반적으로 임계값으로 사용됩니다.

불균형 영향 비율 = (보호 그룹의 선택률) / (참조 그룹의 선택률)

0.8(80%) 미만의 비율은 종종 불균형 영향의 증거로 간주됩니다.

# 불균형 영향 계산
def disparate_impact(y_pred, protected_attribute, reference_group):
    """
    불균형 영향 비율 계산
    참조 그룹은 일반적으로 다수 또는 유리한 그룹
    """
    groups = np.unique(protected_attribute)
    selection_rates = {}

    for group in groups:
        mask = protected_attribute == group
        selection_rate = np.mean(y_pred[mask])
        selection_rates[group] = selection_rate

    reference_rate = selection_rates[reference_group]

    print("선택률:")
    for group, rate in selection_rates.items():
        di_ratio = rate / reference_rate if reference_rate > 0 else 0
        status = "통과" if di_ratio >= 0.8 else "실패"

        print(f"  {group}: {rate:.3f} (DI 비율: {di_ratio:.3f}) [{status}]")

    return selection_rates

# 예제
y_pred = np.array([1, 1, 1, 1, 0, 1, 0, 0, 1, 0])
protected = np.array(['다수', '다수', '다수', '다수', '다수',
                      '보호', '보호', '보호', '보호', '보호'])

rates = disparate_impact(y_pred, protected, '다수')

보정 및 점수 기반 지표

하드 분류가 아닌 확률 점수를 출력하는 모델의 경우, 보정은 중요한 공정성 고려 사항입니다.

그룹별 보정

모델이 예측이 실제 확률을 반영하는 경우 보정됩니다. 그룹 보정은 이것이 각 인구통계학적 그룹에 대해 별도로 유지되어야 한다고 요구합니다.

# 그룹별 보정 확인
def calibration_by_group(y_true, y_score, protected_attribute, n_bins=10):
    """
    각 그룹에 대해 별도로 보정 평가
    """
    from sklearn.calibration import calibration_curve

    groups = np.unique(protected_attribute)

    for group in groups:
        mask = protected_attribute == group

        prob_true, prob_pred = calibration_curve(
            y_true[mask],
            y_score[mask],
            n_bins=n_bins,
            strategy='uniform'
        )

        print(f"\n그룹 {group} 보정:")
        for i, (true_p, pred_p) in enumerate(zip(prob_true, prob_pred)):
            print(f"  빈 {i+1}: 예측={pred_p:.3f}, 실제={true_p:.3f}")

    return True

적절한 지표 선택

적절한 공정성 지표 선택은 응용 분야, 법적 요구 사항, 윤리적 고려 사항에 따라 달라집니다:

응용 분야 권장 지표 근거
형사 사법 동등한 확률, 동등한 기회 위양성과 위음성 모두 심각한 결과를 초래함
대출/신용 불균형 영향, 인구통계학적 균등성 법적 준수(ECOA), 동등한 접근 요구 사항
채용 불균형 영향, 동등한 기회 법적 준수(EEOC), 자격을 갖춘 후보자에 초점
의료 동등한 기회, 보정 놓친 진단 최소화, 신뢰할 수 있는 위험 점수
콘텐츠 추천 인구통계학적 균등성, 개인 공정성 동등한 노출, 개인화된 대우

포괄적인 공정성 평가

실제로는 전체 그림을 얻기 위해 여러 공정성 지표를 평가해야 합니다:

# 포괄적인 공정성 보고서
def fairness_report(y_true, y_pred, protected_attribute):
    """
    포괄적인 공정성 평가 생성
    """
    print("=" * 60)
    print("공정성 평가 보고서")
    print("=" * 60)

    # 1. 인구통계학적 균등성
    print("\n1. 인구통계학적 균등성")
    print("-" * 60)
    dp_ratio, _ = demographic_parity(y_pred, protected_attribute)

    # 2. 동등한 확률
    print("\n2. 동등한 확률")
    print("-" * 60)
    eo_results = equalized_odds(y_true, y_pred, protected_attribute)

    # 3. 동등한 기회
    print("\n3. 동등한 기회")
    print("-" * 60)
    eop_results = equal_opportunity(y_true, y_pred, protected_attribute)

    # 4. 예측적 균등성
    print("\n4. 예측적 균등성")
    print("-" * 60)
    pp_results = predictive_parity(y_true, y_pred, protected_attribute)

    # 요약
    print("\n" + "=" * 60)
    print("요약")
    print("=" * 60)
    print("위의 모든 지표를 검토하여 정보에 입각한 공정성 평가를 수행하십시오.")
    print("다른 지표가 충돌할 수 있음을 기억하십시오. 특정 사용 사례와")
    print("이해관계자 가치에 따라 선택하십시오.")
    print("\n弘益人間 - AI가 모든 인류에게 공평하게 이익이 되도록 보장하십시오")
    print("=" * 60)

    return {
        'demographic_parity': dp_ratio,
        'equalized_odds': eo_results,
        'equal_opportunity': eop_results,
        'predictive_parity': pp_results
    }

장 요약

복습 질문

  1. 인구통계학적 균등성이란 무엇이며 언제 적절한 공정성 지표입니까? 한계는 무엇입니까?
  2. 동등한 확률과 동등한 기회의 차이점을 설명하세요. 하나를 다른 것보다 선택하는 경우는 언제입니까?
  3. 모든 공정성 기준을 동시에 만족시키는 것이 수학적으로 불가능한 이유는 무엇입니까? 예를 제공하세요.
  4. 불균형 영향 분석의 80% 규칙은 무엇입니까? 시스템이 이 테스트에 실패하면 무엇을 나타냅니까?
  5. 개인 공정성이 그룹 공정성과 어떻게 다릅니까? 개인 공정성을 구현하는 데 있어서의 과제는 무엇입니까?
  6. 대출 모델이 인구통계학적 그룹 전체에 걸쳐 동등한 정밀도를 가지지만 다른 위양성률을 가집니다. 어떤 공정성 기준을 만족하고 어떤 것을 위반합니까?
  7. 인구통계학적 균등성을 최적화하면 불공정한 개인 수준의 결과로 이어질 수 있는 시나리오를 설명하세요.
  8. 보정이 공정성에 중요한 이유는 무엇입니까? 모델이 전체적으로는 잘 보정되었지만 특정 그룹에 대해서는 잘못 보정될 수 있는 방법은 무엇입니까?
  9. 의료 진단 AI를 위한 공정성 평가 전략을 설계하세요. 어떤 지표를 우선시하고 그 이유는 무엇입니까?
  10. 弘益人間 철학이 공정성 지표의 선택과 적용을 어떻게 안내합니까?