AI Model Wiki

    Skip to main content
    25 min
    Lesson 2 of 4

    Bias and Fairness Testing

    From the course AI Audit & Testing

    Implement comprehensive bias and fairness testing for AI systems.

    Fairness Metrics

    Statistical Fairness Measures

    import pandas as pd
    from sklearn.metrics import confusion_matrix
    import numpy as np
    
    def comprehensive_fairness_audit(predictions, actuals, sensitive_attribute):
        groups = predictions[sensitive_attribute].unique()
        results = {}
        
        for group in groups:
            mask = predictions[sensitive_attribute] == group
            group_preds = predictions.loc[mask, "prediction"]
            group_actual = actuals.loc[mask, "actual"]
            
            tn, fp, fn, tp = confusion_matrix(group_actual, group_preds).ravel()
            
            results[group] = {
                # Selection rate (Demographic Parity)
                "selection_rate": (tp + fp) / len(group_preds),
                
                # True positive rate (Equal Opportunity)
                "tpr": tp / (tp + fn) if (tp + fn) > 0 else 0,
                
                # False positive rate
                "fpr": fp / (fp + tn) if (fp + tn) > 0 else 0,
                
                # Accuracy
                "accuracy": (tp + tn) / len(group_preds),
                
                # Positive predictive value
                "ppv": tp / (tp + fp) if (tp + fp) > 0 else 0
            }
        
        # Calculate fairness ratios between groups
        groups_list = list(groups)
        fairness_analysis = {}
        
        for i, group_a in enumerate(groups_list):
            for group_b in groups_list[i+1:]:
                # Disparate Impact Ratio (aim for > 0.8)
                dir = min(
                    results[group_a]["selection_rate"],
                    results[group_b]["selection_rate"]
                ) / max(
                    results[group_a]["selection_rate"],
                    results[group_b]["selection_rate"]
                )
                
                fairness_analysis[f"{group_a}_vs_{group_b}"] = {
                    "disparate_impact_ratio": dir,
                    "passes_80_pct_rule": dir >= 0.8,
                    "tpr_difference": abs(results[group_a]["tpr"] - results[group_b]["tpr"]),
                    "fpr_difference": abs(results[group_a]["fpr"] - results[group_b]["fpr"])
                }
        
        return results, fairness_analysis
    
    # Generate audit report
    group_metrics, fairness_ratios = comprehensive_fairness_audit(
        pred_df, actual_df, "gender"
    )
    

    Intersectional Fairness

    def intersectional_analysis(predictions, actuals, attributes):
        # Create intersectional groups (e.g., Black women, White men)
        pred_df = predictions.copy()
        pred_df["intersectional_group"] = pred_df[attributes].apply(
            lambda row: "_".join(row.astype(str)), axis=1
        )
        
        # Analyze each intersectional subgroup
        groups = pred_df["intersectional_group"].unique()
        
        for group in groups:
            if len(pred_df[pred_df["intersectional_group"] == group]) < 50:
                continue  # Skip groups too small for reliable analysis
            
            group_preds = pred_df[pred_df["intersectional_group"] == group]
            # Calculate metrics for each intersectional group
            accuracy = (group_preds["prediction"] == group_preds["actual"]).mean()
            
            if accuracy < 0.80:
                print(f"WARNING: Low accuracy for {group}: {accuracy:.2%}")
    

    Fairness-Aware Model Development

    from fairlearn.reductions import ExponentiatedGradient, EqualizedOdds
    from sklearn.linear_model import LogisticRegression
    
    # Constrained optimization for fairness
    base_model = LogisticRegression()
    constraint = EqualizedOdds()  # Equal TPR and FPR across groups
    
    mitigator = ExponentiatedGradient(base_model, constraint)
    mitigator.fit(
        X_train, y_train,
        sensitive_features=X_train["gender"]
    )
    
    # Fair predictions
    fair_predictions = mitigator.predict(X_test)
    

    Key Takeaways

    • •Comprehensive fairness audit measures selection rates, TPR, FPR, and accuracy by group
    • •Disparate Impact Ratio below 0.8 fails the 80% rule used in employment law
    • •Intersectional analysis catches failures missed by single-attribute analysis
    • •Fairlearn enables constrained optimization that directly incorporates fairness objectives
    0 of 4 lessons marked complete

    Progress is kept in this browser only.