Bias is the enemy of fairness. A biased AI model systematically discriminates against certain groups. This page covers bias types, measurement, and correction.


1. Types of Bias

REPRESENTATION BIAS
  Definition: Training data underrepresents certain groups
  Example: Facial recognition trained 90% on white males
  Impact: Model performs poorly for other ethnicities/genders
  Fix: Balanced data collection

SELECTION BIAS
  Definition: How training data is collected is flawed
  Example: Hiring data only includes successful candidates
  Impact: Model favors already-advantaged groups
  Fix: Unbiased sampling strategies

MEASUREMENT BIAS
  Definition: Feature definitions are unfair
  Example: "Quality of life" measured only by salary
  Impact: Marginalized groups systematically undervalued
  Fix: Fairness-aware feature engineering

ALGORITHMIC BIAS
  Definition: Model amplifies bias in the data
  Example: Recidivism prediction: Black defendants rated higher
  Impact: Feedback loop: more incarceration → more bias
  Fix: Fairness constraints during training

AUTOMATION BIAS
  Definition: Humans blindly trust models
  Example: Judge implements model recommendation without checking
  Impact: Unfair decisions are scaled
  Fix: Human-in-the-loop review

2. Fairness Metrics

from typing import Dict
import numpy as np

class FairnessMetrics:
    """Computes fairness metrics for models"""

    @staticmethod
    def demographic_parity(predictions: np.array, protected_attribute: np.array) -> float:
        """
        Demographic Parity: Selection rate equal across groups
        P(Ŷ=1 | A=0) ≈ P(Ŷ=1 | A=1)
        """
        group_0_positive = np.mean(predictions[protected_attribute == 0])
        group_1_positive = np.mean(predictions[protected_attribute == 1])

        return abs(group_0_positive - group_1_positive)

    @staticmethod
    def equalized_odds(predictions: np.array, true_labels: np.array, protected_attribute: np.array) -> Dict:
        """
        Equalized Odds: TPR and FPR equal across groups
        """
        group_0_mask = protected_attribute == 0
        group_1_mask = protected_attribute == 1

        # Calculate TPR, FPR for each group
        tp_0 = np.sum((predictions[group_0_mask] == 1) & (true_labels[group_0_mask] == 1))
        fp_0 = np.sum((predictions[group_0_mask] == 1) & (true_labels[group_0_mask] == 0))
        fn_0 = np.sum((predictions[group_0_mask] == 0) & (true_labels[group_0_mask] == 1))
        tn_0 = np.sum((predictions[group_0_mask] == 0) & (true_labels[group_0_mask] == 0))

        tpr_0 = tp_0 / (tp_0 + fn_0) if (tp_0 + fn_0) > 0 else 0
        fpr_0 = fp_0 / (fp_0 + tn_0) if (fp_0 + tn_0) > 0 else 0

        # Similar for group 1...
        return {
            "tpr_difference": abs(tpr_0 - tpr_1),
            "fpr_difference": abs(fpr_0 - fpr_1),
        }

# Usage:
metrics = FairnessMetrics()

predictions = np.array([0, 1, 1, 0, 1, 1, 0, 0])
true_labels = np.array([0, 1, 1, 0, 1, 0, 0, 0])
protected_attr = np.array([0, 0, 0, 0, 1, 1, 1, 1])

dp = metrics.demographic_parity(predictions, protected_attr)
print(f"Demographic Parity Difference: {dp:.3f} (0 = fair)")

3. Debiasing Techniques

3.1 Pre-Processing: Balanced Data

from collections import Counter
import random

class BalancedDataCollector:
    """Helps collect balanced training data"""

    @staticmethod
    def stratified_sample(data: list, protected_attribute_key: str, sample_size: int) -> list:
        """Stratified sampling: each group represented proportionally"""
        groups = {}
        for sample in data:
            attr_val = sample[protected_attribute_key]
            if attr_val not in groups:
                groups[attr_val] = []
            groups[attr_val].append(sample)

        # Sample from each group
        balanced_sample = []
        for group_val, samples in groups.items():
            size = int(len(samples) / len(data) * sample_size)
            balanced_sample.extend(random.sample(samples, min(size, len(samples))))

        return balanced_sample[:sample_size]

4. Tools: Fairlearn, AIF360

pip install fairlearn aif360
from fairlearn.metrics import demographic_parity_difference

dpd = demographic_parity_difference(true_labels, predictions, sensitive_features=protected_attr)
print(f"Demographic Parity Difference: {dpd:.3f}")