πŸŽ‰ 75% of content is free forever β€” Unlock Premium from $10/mo β†’
CW
Search courses…
πŸ’Ό Servicesℹ️ Aboutβœ‰οΈ ContactView Pricing Plansfrom $10

Ethics & Bias: Fairness in ML, Algorithmic Accountability

Data Scientist Role InterviewEthics, Bias & Fairness in Machine Learning⭐ Premium

Advertisement

βš–οΈ

Asked at Google & Microsoft

Ethics & Bias

Fairness in ML, Algorithmic Accountability

The Interview Question

"You've built a model that predicts loan default. How would you ensure it's fair across different demographic groups?"

Ethics and bias are critical topics in modern data science β€” companies face legal, reputational, and moral consequences for biased algorithms.


Why Companies Ask This

ℹ️

Google and Microsoft are under intense scrutiny for algorithmic bias. They need data scientists who can build fair systems, understand the ethical implications of their work, and navigate complex trade-offs between accuracy and fairness.

Interviewers evaluate:

  1. Bias Awareness β€” Can you identify potential sources of bias?
  2. Fairness Knowledge β€” Do you understand different fairness definitions?
  3. Mitigation Skills β€” Can you implement bias mitigation techniques?
  4. Ethical Reasoning β€” Can you navigate complex ethical trade-offs?
  5. Regulatory Knowledge β€” Do you understand legal requirements?

The Ethics and Bias Framework

Step 1: Identify Potential Bias Sources

bias_sources = {
    'historical_bias': {
        'description': 'Data reflects past discrimination',
        'example': 'Loan approval data from historically biased lending practices',
        'mitigation': 'Debias training data, use fairness-aware algorithms',
    },
    'representation_bias': {
        'description': 'Some groups are underrepresented in data',
        'example': 'Medical training data mostly from white patients',
        'mitigation': 'Collect more diverse data, use stratified sampling',
    },
    'measurement_bias': {
        'description': 'Features are measured differently across groups',
        'example': 'Credit score calculated differently by location',
        'mitigation': 'Standardize measurement, validate across groups',
    },
    'aggregation_bias': {
        'description': 'One model doesn\'t fit all groups',
        'example': 'A model that works well on average but poorly for minorities',
        'mitigation': 'Train separate models, use group-specific features',
    },
    'evaluation_bias': {
        'description': 'Benchmark doesn\'t represent deployment context',
        'example': 'Testing on easy examples, deploying on hard ones',
        'mitigation': 'Use representative test sets, diverse evaluation',
    },
    'deployment_bias': {
        'description': 'Model used in ways it wasn\'t designed for',
        'example': 'Risk assessment model used for different decisions',
        'mitigation': 'Clear documentation, usage guidelines',
    },
}

Step 2: Define Fairness

fairness_definitions = {
    'demographic_parity': {
        'definition': 'Prediction rates should be equal across groups',
        'formula': 'P(Yhat=1 | A=0) = P(Yhat=1 | A=1)',
        'example': 'Loan approval rate should be equal for men and women',
        'tradeoff': 'May reduce accuracy if base rates differ',
    },
    'equalized_odds': {
        'definition': 'True positive and false positive rates should be equal',
        'formula': 'TPR and FPR equal across groups',
        'example': 'Among qualified applicants, approval rates should be equal',
        'tradeoff': 'May not be achievable if base rates differ significantly',
    },
    'predictive_parity': {
        'definition': 'Positive predictive value should be equal',
        'formula': 'PPV = TP / (TP + FP) equal across groups',
        'example': 'Among those predicted to default, actual default rate should be equal',
        'tradeoff': 'Conflicts with equalized odds in some cases',
    },
    'calibration': {
        'definition': 'Predicted probabilities should match actual outcomes',
        'formula': 'P(Y=1 | Yhat=p) = p for all groups',
        'example': 'A 30% predicted default rate should mean 30% actually default',
        'tradeoff': 'Most intuitive but hardest to achieve',
    },
    'individual_fairness': {
        'definition': 'Similar individuals should receive similar predictions',
        'formula': 'Distance(Yhat_i, Yhat_j) <= L * Distance(X_i, X_j)',
        'example': 'Similar loan applicants should get similar decisions',
        'tradeoff': 'Requires defining "similarity" β€” subjective',
    },
}

Example: Fair Loan Default Prediction

Step 1: Assess Current Bias

import pandas as pd
import numpy as np
from sklearn.metrics import confusion_matrix

def assess_fairness(y_true, y_pred, protected_attribute):
    """
    Assess fairness across protected groups.
    """
    groups = protected_attribute.unique()
    metrics = {}
    
    for group in groups:
        mask = protected_attribute == group
        group_true = y_true[mask]
        group_pred = y_pred[mask]
        
        # Confusion matrix
        tn, fp, fn, tp = confusion_matrix(group_true, group_pred).ravel()
        
        metrics[group] = {
            'n_samples': len(group_true),
            'approval_rate': group_pred.mean(),
            'true_positive_rate': tp / (tp + fn) if (tp + fn) > 0 else 0,
            'false_positive_rate': fp / (fp + tn) if (fp + tn) > 0 else 0,
            'positive_predictive_value': tp / (tp + fp) if (tp + fp) > 0 else 0,
            'accuracy': (tp + tn) / (tp + tn + fp + fn),
        }
    
    return metrics

def calculate_fairness_metrics(metrics):
    """
    Calculate fairness metrics from group-level metrics.
    """
    groups = list(metrics.keys())
    
    # Demographic parity difference
    approval_rates = [metrics[g]['approval_rate'] for g in groups]
    demographic_parity_diff = max(approval_rates) - min(approval_rates)
    
    # Equalized odds difference
    tpr_diff = max(metrics[g]['true_positive_rate'] for g in groups) - \
               min(metrics[g]['true_positive_rate'] for g in groups)
    fpr_diff = max(metrics[g]['false_positive_rate'] for g in groups) - \
               min(metrics[g]['false_positive_rate'] for g in groups)
    
    return {
        'demographic_parity_difference': demographic_parity_diff,
        'equalized_odds_tpr_difference': tpr_diff,
        'equalized_odds_fpr_difference': fpr_diff,
        'disparate_impact_ratio': min(approval_rates) / max(approval_rates),
    }

Step 2: Mitigate Bias

class FairnessMitigator:
    """
    Various techniques for mitigating bias in ML models.
    """
    
    def __init__(self):
        self.methods = {
            'pre_processing': self.pre_processing_methods,
            'in_processing': self.in_processing_methods,
            'post_processing': self.post_processing_methods,
        }
    
    def pre_processing_methods(self, X, y, protected):
        """
        Modify training data to reduce bias.
        """
        methods = {
            'reweighing': self.reweighing,
            'disparate_impact_remover': self.disparate_impact_remover,
            'learning_fair_representations': self.learning_fair_representations,
        }
        return methods
    
    def reweighing(self, X, y, protected):
        """
        Assign weights to training examples to achieve fairness.
        """
        weights = np.ones(len(y))
        
        for group in protected.unique():
            group_mask = protected == group
            for label in y.unique():
                # Weight = expected count / actual count
                expected = (group_mask.sum() * (y == label).sum()) / len(y)
                actual = (group_mask & (y == label)).sum()
                weights[group_mask & (y == label)] = expected / actual
        
        return weights
    
    def disparate_impact_remover(self, X, protected, repair_level=1.0):
        """
        Modify features to remove disparate impact.
        """
        X_repaired = X.copy()
        
        for col in X.select_dtypes(include=[np.number]).columns:
            # Compute quantiles for each group
            group_quantiles = {}
            for group in protected.unique():
                group_mask = protected == group
                group_quantiles[group] = X.loc[group_mask, col].rank(pct=True)
            
            # Repair: move each group's distribution toward median
            median_quantile = pd.DataFrame(group_quantiles).median(axis=1)
            
            for group in protected.unique():
                group_mask = protected == group
                group_values = X.loc[group_mask, col]
                target_quantile = median_quantile[group_mask]
                
                # Interpolate to target quantile
                repaired = group_values.rank(pct=True) * (1 - repair_level) + \
                          target_quantile * repair_level
                X_repaired.loc[group_mask, col] = repaired
        
        return X_repaired
    
    def in_processing_methods(self):
        """
        Modify learning algorithm to incorporate fairness constraints.
        """
        return {
            'adversarial_debiasing': 'Train model to be fair while maintaining accuracy',
            'prejudice_remover': 'Add fairness regularization term to loss function',
            'exponentiated_gradient': 'Use constrained optimization for fairness',
        }
    
    def post_processing_methods(self, y_pred, protected):
        """
        Adjust predictions after model training.
        """
        methods = {
            'equalized_odds_postprocessing': self.equalized_odds_postprocessing,
            'threshold_adjustment': self.threshold_adjustment,
        }
        return methods
    
    def threshold_adjustment(self, y_scores, protected, target_metric='equalized_odds'):
        """
        Find group-specific thresholds that achieve fairness.
        """
        from scipy.optimize import minimize_scalar
        
        thresholds = {}
        
        for group in protected.unique():
            group_mask = protected == group
            group_scores = y_scores[group_mask]
            
            # Optimize threshold for fairness metric
            def objective(threshold):
                predictions = (group_scores >= threshold).astype(int)
                # Implement fairness metric here
                return abs(predictions.mean() - 0.5)  # Example: target 50% approval
            
            result = minimize_scalar(objective, bounds=(0, 1), method='bounded')
            thresholds[group] = result.x
        
        return thresholds

Google's AI Principles

google_ai_principles = {
    'be_socially_beneficial': 'Avoid creating or reinforcing unfair bias',
    'avoid_creating_or_reinforcing_unfair_bias': {
        'action': 'Test for unfair bias and address it',
        'example': 'Regular fairness audits of search results',
    },
    'be_accountable_to_people': 'Provide explanations for decisions',
    'incorporate_privacy_design_principles': 'Protect user data',
    'uphold_high_standards_of_scientific_excellence': 'Rigorous research',
}

Microsoft's Responsible AI Principles

microsoft_responsible_ai = {
    'fairness': 'AI systems should treat all people fairly',
    'reliability_safety': 'AI systems should perform reliably and safely',
    'privacy_security': 'AI systems should be secure and respect privacy',
    'inclusiveness': 'AI should empower everyone',
    'transparency': 'AI systems should be understandable',
    'accountability': 'People should be accountable for AI systems',
}

Common Mistakes to Avoid

⚠️

These mistakes can have serious legal and ethical consequences:

  1. Ignoring protected attributes β€” Not including them doesn't remove bias
  2. Optimizing only for accuracy β€” Accuracy can mask unfairness
  3. Assuming fairness is binary β€” It's a spectrum with trade-offs
  4. Not testing across groups β€” Average metrics hide disparities
  5. Not documenting decisions β€” Auditability requires documentation
  6. Not monitoring post-deployment β€” Bias can emerge over time

Quiz: Test Your Understanding


Related Topics

Advertisement