Every individual has a latent "true merit" m ~ N(0,1), drawn from
the same distribution for both groups — underneath, group A and group B
are equally qualified. The true label is
Y = 1 if m + ε_y > 0 (outcome noise ε_y ~ N(0,0.6)).
The classifier never sees m directly — it sees a score
S = m − bias·[group=B] + ε_s, with ε_s ~ N(0,0.5). The
bias slider is the historical bias: it shifts group B's recorded
scores down even though their true merit distribution is identical to A's — a
simplified model of biased training data.
Decision D = 1 if S > threshold_group
Because group B's scores are shifted down by bias, a shared threshold
approves fewer of them — a demographic parity violation. Lowering B's threshold to
restore equal approval rates raises B's FPR (more unqualified people approved) while
barely moving A's — an equalized odds violation. With one threshold per group you
generally cannot close both gaps to zero at once except in the degenerate case where
bias = 0; the "auto-equalize" buttons solve for the closest achievable
setting given the current bias, so you can see the residual gap that remains.
A statistically real model of algorithmic bias: two groups with equal underlying qualification but historically biased recorded scores, two independently draggable decision thresholds, and live demographic parity / equalized odds gaps computed from the actual population — not a scripted animation.
Latent merit m ~ N(0,1) is identical for both groups; the true label is Y = 1 if m+ε>0. The observed score is S = m − bias·[B] + ε_s. A decision is D = 1 if S > threshold_group. Accuracy, demographic parity gap |P(D=1|A)−P(D=1|B)|, and equalized odds gap (average of the TPR and FPR differences between groups) are recomputed from the live population on every threshold change.
Drag the cyan or magenta knob above each score cloud to move that group's threshold, or use the matching slider. Try "Auto-equalize demographic parity" then watch the equalized odds gap — closing one gap generally opens the other, because with biased data one threshold per group can't satisfy both fairness definitions at once.
This is the same impossibility that made the COMPAS recidivism debate famous: demographic parity, equalized odds and calibration cannot all hold simultaneously once base rates differ between groups, unless the classifier is perfect. This lab lets you find that boundary yourself instead of taking it on faith.