loanguard / src /evaluation /fairness.py
adwitiyashukla's picture
edited the README file
8c66d1b
Raw
History Blame Contribute Delete
1.35 kB
from __future__ import annotations
import numpy as np
import pandas as pd
from sklearn.metrics import roc_auc_score
def fairness_report(y_true: np.ndarray, y_proba: np.ndarray, groups: pd.Series, threshold: float=0.5, min_group_size: int=200) -> pd.DataFrame:
df = pd.DataFrame({'y': y_true, 'p': y_proba, 'g': groups.values})
rows = []
overall_auc = roc_auc_score(y_true, y_proba)
overall_fpr = float(((y_proba >= threshold) & (y_true == 0)).sum() / max((y_true == 0).sum(), 1))
for (g, sub) in df.groupby('g'):
if len(sub) < min_group_size or sub['y'].nunique() < 2:
continue
pred = (sub['p'] >= threshold).astype(int)
tp = int(((pred == 1) & (sub['y'] == 1)).sum())
fp = int(((pred == 1) & (sub['y'] == 0)).sum())
fn = int(((pred == 0) & (sub['y'] == 1)).sum())
tn = int(((pred == 0) & (sub['y'] == 0)).sum())
tpr = tp / max(tp + fn, 1)
fpr = fp / max(fp + tn, 1)
auc = roc_auc_score(sub['y'], sub['p'])
rows.append({'group': g, 'n': len(sub), 'positive_rate': float(sub['y'].mean()), 'auc': float(auc), 'auc_gap': float(auc - overall_auc), 'tpr': float(tpr), 'fpr': float(fpr), 'fpr_gap': float(fpr - overall_fpr), 'approval_rate': float((pred == 0).mean())})
return pd.DataFrame(rows).sort_values('auc_gap').reset_index(drop=True)