Skip to content

v1.3.0 — Intersectional Bias Analysis: auditing two protected attributes at once

Choose a tag to compare

@yakew7 yakew7 released this 13 Jul 17:41

Intersectional bias — seeing the harm a single-axis audit can't

Every Fair Code audit so far measured fairness one protected attribute at a
time: sex, then race, then age, each against everyone else. That averaging is
exactly what hides the group at the intersection of two attributes. This release
adds intersectional auditing — crossing two protected attributes to check the
doubly-disadvantaged group directly — grounded in Crenshaw's (1989) original
argument that a harm landing on, say, minority women is invisible to a race-only
or sex-only analysis.

🔀 New: intersectional_report (faircode.significance)

Give it an outcome and two boolean masks (each marking the disadvantaged side of
one attribute) and it splits the population into the four quadrants of the two
attributes, then compares the doubly-disadvantaged cell against the
baseline cell with the same bootstrap CI + permutation p-value the
single-axis audits already use. It also reports:

  • each attribute's marginal gap (what it would report on its own), so the
    single-axis and intersectional views sit side by side
  • a superadditive flag — true when the compounded gap exceeds the sum of
    the two marginals (the intersection is worse than the parts)
  • per-quadrant rates and sizes, so a thin doubly-disadvantaged cell is visible
    before the small-sample warning even fires

Pure numpy/pandas — no new dependencies.

📉 Wired into the three multi-attribute audits

Each now prints an intersectional block after its existing single-attribute
output, in both unfair.py and fair.py:

  • Insurance Denial — Age × Sex (Young × Female)
  • Benefits Denial — Sex × Race (Female × Minority)
  • Healthcare Readmission — Sex × Race (Female × Minority)

COMPAS, AI Fair Recruitment, and German Credit Lending track a single protected
attribute each and are unchanged — there is nothing to cross.

📓 New notebook: 07_intersectional_bias_audit.ipynb

Walks through what intersectionality means and why marginal fairness gaps can
hide a worse compounded one, then runs intersectional_report on the biased vs.
mitigated models for all three pairs. The finding worth reading: proxy removal
closes the intersectional gap roughly in step with the marginals for Benefits
and Healthcare — but for Insurance the marginal age and sex gaps shrink while the
compounded gap for young women does not, tipping the mitigated model into
superadditive territory. Removing proxies fixed the single-axis numbers without
fixing the intersection.

✅ Tests & docs

  • Three new significance tests (additive, superadditive, small-cell warning) —
    50 passing
  • Methodology note in README.md; Phase 5 roadmap item checked off;
    CONTRIBUTING.md audit template now asks 2+-attribute audits to report at
    least one intersectional pair

Note: intersectional auditing does not replace the marginal audit — the
doubly-disadvantaged cell is the smallest quadrant, so its gap carries the widest
CI and a non-significant result means "not enough evidence," not "no bias." It
catches the harm the marginal audit is structurally unable to see.

Full changelog: v1.2.5...v1.3.0