Medical AI · Evaluation, safety & deployment · Lesson 2 of 5
Bias and fairness
Reviewed by Dr. Ram Kumar G, MBBS, MD (Internal Medicine), MPH (USA), on · Last updated
- Intermediate
- Clinical focus
- About 30 minutes
- Includes exercise
Before this lesson: External validation and dataset shift, Diagnostic accuracy metrics: sensitivity, specificity, PPV, ROC and calibration
In short
Clinical AI can treat groups of patients unequally even when no one intends it: through labels that measure access to care rather than health need, through data that under-represent some groups, or through models that are well calibrated overall but not within each group. Leaving group membership out of a model does not make it fair. Measure discrimination, calibration, sensitivity and predictive values in each relevant subgroup, choose fairness goals deliberately, and document a dataset's limits, as the STANDING Together recommendations advise.
You will learn to
- Identify the main sources of bias in clinical AI: labels, data, measurement and deployment
- Show in code how a proxy label disadvantages a group with less access to care
- Calculate subgroup sensitivity, PPV and calibration, and interpret differences
- Explain why fairness criteria can conflict and how to choose among them
Where bias comes from
| Source | What happens | Documented example |
|---|---|---|
| Label bias | The outcome used for training is a biased stand-in for what matters | A care-management algorithm used healthcare costs as a proxy for need, underestimating the needs of Black patients (Obermeyer et al., 2019) |
| Representation | Some groups are scarce in the training data | Chest X-ray models under-diagnosed disease more often in under-served groups such as Black, Hispanic and female patients and those on public insurance (Seyyed-Kalantari et al., 2021) |
| Measurement | A device or test works differently across groups | Pulse oximeters overestimating oxygen saturation in Black patients (Sjoding et al., 2020) |
| Built-in group adjustments | A group variable is added in ways that are not biologically justified | Race coefficients in eGFR equations, removed in the CKD-EPI 2021 equation (Inker et al., 2021) |
| Deployment | The model is used differently across groups | Alerts acted on less often for some patients, or a tool offered only in some clinics |
Label bias, in code
In this simulation, two groups have the same distribution of true health need. Group B has less access to care, so it spends less for the same level of need. A programme selects the 10% of patients with the highest spending, the best possible model of the proxy label.
import numpy as np
import pandas as pd
rng = np.random.default_rng(7)
n = 20000
group = rng.choice(["A", "B"], n, p=[0.7, 0.3])
need = rng.gamma(2.0, 1.0, n) # true health need (same distribution in both groups)
access = np.where(group == "A", 1.0, 0.6) # group B spends less for the same need
spending = need * access * rng.lognormal(0, 0.3, n)
df = pd.DataFrame({"group": group, "need": need, "spending": spending})
selected = df.spending >= df.spending.quantile(0.90)
high_need = df.need >= df.need.quantile(0.90)
summary = pd.DataFrame({
"share of population": df.group.value_counts(normalize=True),
"share of high-need patients": df[high_need].group.value_counts(normalize=True),
"share of patients selected": df[selected].group.value_counts(normalize=True),
}).round(2)
print(summary.to_string())
print(f"\nHigh-need patients missed: group A {1 - selected[high_need & (df.group == 'A')].mean():.0%}, "
f"group B {1 - selected[high_need & (df.group == 'B')].mean():.0%}")
# share of population share of high-need patients share of patients selected
# group
# A 0.7 0.68 0.91
# B 0.3 0.32 0.09
#
# High-need patients missed: group A 24%, group B 75%- Group B makes up 32% of high-need patients but only 9% of those selected. Three-quarters of its high-need patients are missed.
- The model of spending is perfect; the problem is the label. No amount of better modelling fixes a biased target. Choosing a label closer to need (for example measures of illness burden) is what fixed the real algorithm.
Subgroup performance, in code
Here the outcome is more common in group B, and the model is not given group membership, a common attempt at being 'group-blind'.
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
rng = np.random.default_rng(8)
n = 20000
group = rng.choice(["A", "B"], n, p=[0.8, 0.2])
x = rng.normal(size=(n, 3))
baseline = np.where(group == "A", -2.0, -1.0) # outcome more common in group B
y = rng.binomial(1, 1 / (1 + np.exp(-(baseline + x @ np.array([1.0, 0.7, 0.4])))))
def subgroup_table(p, threshold=0.2):
flag = p >= threshold
rows = []
for g in ["A", "B"]:
m = group == g
tp, fn = np.sum(flag & (y == 1) & m), np.sum(~flag & (y == 1) & m)
fp = np.sum(flag & (y == 0) & m)
rows.append({"group": g, "outcome rate": y[m].mean(), "mean predicted": p[m].mean(),
"sensitivity": tp / (tp + fn), "PPV": tp / (tp + fp)})
return pd.DataFrame(rows).round(2).to_string(index=False)
p = LogisticRegression().fit(x, y).predict_proba(x)[:, 1] # group not used
print(subgroup_table(p))
# group outcome rate mean predicted sensitivity PPV
# A 0.18 0.2 0.75 0.34
# B 0.31 0.2 0.67 0.55- Ignoring group membership did not make the model fair: it underestimates risk in group B (20% predicted, 31% observed) and misses more of its cases (sensitivity 0.67 versus 0.75).
Fairness criteria can conflict
X_with_group = np.column_stack([x, group == "B"])
p2 = LogisticRegression().fit(X_with_group, y).predict_proba(X_with_group)[:, 1]
print(subgroup_table(p2))
# group outcome rate mean predicted sensitivity PPV
# A 0.18 0.18 0.67 0.37
# B 0.31 0.31 0.87 0.45- Now the model is calibrated in both groups, and group B's sensitivity rises to 0.87, but group A's falls and the groups' sensitivities and PPVs still differ.
- When outcome rates differ between groups, a model generally cannot be calibrated within groups and have equal false-positive and false-negative rates at the same time (Chouldechova, 2017). Fairness requires choosing which property matters most for the decision.
- Whether a group variable should be used at all is a clinical and ethical question, not just a technical one. Race was removed from eGFR equations partly because it was a social label used as a biological proxy.
| Fairness goal | Meaning | Often preferred when |
|---|---|---|
| Calibration within groups | A predicted 20% means 20% in every group | Risks are communicated to patients or used for shared decisions |
| Equal sensitivity (equal opportunity) | The same share of true cases is found in each group | Missing a case is the main harm, such as screening |
| Equal false-positive rates | The same share of non-cases is flagged in each group | Unnecessary interventions carry significant harm |
Practical steps
- Decide which groups matter for this use (for example sex, age bands, ethnicity, language, insurance, site) and check the data contain them reliably.
- Report discrimination, calibration, sensitivity and PPV for each group, with confidence intervals; small groups need larger samples.
- Examine the label: does it measure what matters equally well for everyone?
- Document dataset composition and known limitations, as recommended by the STANDING Together consensus (29 recommendations, 2025).
- Monitor subgroup performance after deployment, since bias can emerge from how a tool is used.
Fairness is a design decision
- There is no purely technical definition of a fair model. Involve clinicians, patients and the communities affected in deciding which errors matter most, and record the reasoning.
Exercise
Audit a synthetic model for label bias and subgroup performance, and explore fairness trade-offs.
Data: Synthetic populations generated in the notebook (no real patient data) (Generated in the notebook)
- Reproduce the label-bias simulation, then select by need instead of spending and compare the selected shares.
- Reproduce the subgroup tables and add AUROC and calibration plots per group.
- Choose group-specific thresholds that equalise sensitivity, and report what happens to PPV and false-positive rates.
- Shrink group B to 5% of the data and see how uncertain its metrics become (bootstrap confidence intervals).
- Write a one-paragraph fairness statement for this model, saying which goal you prioritised and why.
The runnable notebook and worked solution will be published soon. You can work through the steps with the code on this page in the meantime.
Key takeaways
- Bias enters through labels, data, measurement and deployment.
- A biased label defeats a perfect model; check what the label really measures.
- Group-blind is not fair: measure performance within each relevant group.
- Fairness criteria can conflict; choose and justify the one that fits the decision.
Terms used: Calibration, Label bias, Positive predictive value (PPV), Sensitivity (recall)
Related: External validation and dataset shift, The healthcare-AI landscape, Healthcare data types: data reflect care
FAQ
If a model does not use race or sex, can it still be biased?
Yes. Other variables can act as proxies, labels can be biased, and a model can be miscalibrated for groups with different outcome rates. Fairness has to be measured, not assumed.
What is label bias?
Bias that arises because the outcome a model is trained to predict is a flawed stand-in for what matters, such as healthcare costs standing in for health need.
Should models include race or ethnicity?
It depends on the purpose, the evidence and the potential for harm. Race is a social category, and its use as a biological proxy has caused harm, as in older eGFR equations. Decisions need clinical, ethical and community input.
What are the STANDING Together recommendations?
A 2025 international consensus of 29 recommendations on documenting health datasets and using them in ways that identify and reduce algorithmic bias.
Can a model be fair by every definition at once?
Generally not when outcome rates differ between groups. Calibration within groups and equal error rates usually cannot all hold together, so a choice is needed.
Sources
- Obermeyer Z, et al. Dissecting racial bias in an algorithm used to manage the health of populations. Science 2019;366(6464):447–453. doi:10.1126/science.aax2342
- Seyyed-Kalantari L, et al. Underdiagnosis bias of artificial intelligence algorithms applied to chest radiographs in under-served patient populations. Nature Medicine 2021;27:2176–2182. doi:10.1038/s41591-021-01595-0
- Sjoding MW, et al. Racial bias in pulse oximetry measurement. N Engl J Med 2020;383:2477–2478. doi:10.1056/NEJMc2029240
- Inker LA, et al. New creatinine- and cystatin C-based equations to estimate GFR without race. N Engl J Med 2021;385:1737–1749. doi:10.1056/NEJMoa2102953
- Chouldechova A. Fair prediction with disparate impact: a study of bias in recidivism prediction instruments. Big Data 2017;5(2):153–163. doi:10.1089/big.2016.0047
- Rajkomar A, et al. Ensuring fairness in machine learning to advance health equity. Ann Intern Med 2018;169(12):866–872. doi:10.7326/M18-1990
- Alderman JE, et al. Tackling algorithmic bias and promoting transparency in health datasets: the STANDING Together consensus recommendations. Lancet Digital Health 2025;7(1):e64–e88. doi:10.1016/S2589-7500(24)00224-3
Educational content only. This material teaches methods; it is not clinical advice. Code, models and examples here are not validated medical devices and must not be used to make decisions about real patients without proper clinical validation, governance and any required regulatory approval. Examples use synthetic or openly licensed de-identified data only. Never paste identifiable patient information into public AI tools. Mentions of models, tools or vendors are for identification, not endorsement.