AI Ethics: Building Responsibly
1 · The lesson
readA machine-learning system is more than a piece of code. It makes decisions about real people, at scale. A misconfigured spam filter loses an email. A misconfigured risk-assessment model misclassifies people as flight risks and they spend an extra month in jail. The engineering practices that mostly work for the spam filter (train, evaluate on a holdout, ship) cause harm in the second case, unless you design the system to prevent it.
This lesson is about that design work: the harm categories, the practical measurements, the documentation practices, the regulatory shape of 2026, and the questions you should answer for every system you ship. There is no library you can import to make a system ethical. The work is judgement plus a small set of tools.
1. Why This Matters: Scale Multiplies Mistakes
A human reviewer at a bank, even a biased one, can review maybe 50 loan applications a day. A model reviews 500,000. If the model learns the same bias, it applies it 10,000 times more often, and the unfair outcomes affect a whole population. ML mostly repeats existing human failures, but at a much larger scale.
Three properties make ML harms different from non-ML harms:
- Scale: a single trained model can affect millions of decisions per day.
- Opacity: you can't audit the model's reasoning the way you can read a human reviewer's notes.
- Path dependence: biased decisions early in a pipeline shape the data that trains the next model. The error grows with each new version.
If you can't answer "who is harmed if this is wrong, and how badly?" for the system you're building, you don't yet understand the problem.
2. The Five Harm Categories
These overlap, but it's useful to name them separately because the mitigations differ.
| Harm | Example | Primary mitigation |
|---|---|---|
| Bias / discrimination | Hiring AI screens out women's CVs | Disaggregated metrics, debiasing, oversight |
| Privacy violation | Training data memorised and leaked verbatim | Differential privacy, data minimisation |
| Misinformation / deepfakes | Generated audio of a politician saying things they didn't say | Provenance, watermarking, platform policy |
| Job displacement | Automating call centres with no transition plan | Not something the ML team can solve alone. It needs design and policy |
| Autonomous decision-making without recourse | Algorithm denies you a loan, no appeal path | Human-in-the-loop, transparent process, appeals mechanism |
Most production ML systems touch multiple categories. A facial recognition system in policing is at once a bias problem (higher error rates on darker skin), a privacy problem (mass surveillance), and a recourse problem (you can't appeal a stop based on an algorithm you can't see).
3. Bias in Practice
"Bias" in the ML sense means a model treats otherwise similar people differently, in ways correlated with protected attributes such as race, gender, age, disability or religion. It has three sources:
- Biased training data. Loan applications historically approved at higher rates for one group → a model trained on those decisions reproduces the disparity.
- Biased labels. "Good employee" labelled by managers who promoted men → the model learns that men are good employees.
- Biased problem framing. Choosing "arrest" as the proxy for "crime" puts bias into the target you're predicting, because arrests are themselves biased.
The third source is the hardest to fix. You can fix the data, and you can fix the labels. But if the target variable doesn't measure what you care about, no amount of training will fix it.
Detection: Disaggregated Metrics
Overall accuracy can hide large differences between groups. A model can be 95% accurate overall and 99% accurate on group A while being 60% accurate on group B. The aggregate number doesn't tell you that, but the per-group breakdown does.
Start with a table of (group, metric) cells. For a classifier:
import numpy as np from sklearn.metrics import precision_score, recall_score, f1_score def per_group_metrics(y_true, y_pred, groups): out = [] for g in np.unique(groups): mask = groups == g out.append({ "group": g, "n": int(mask.sum()), "precision": precision_score(y_true[mask], y_pred[mask], zero_division=0), "recall": recall_score(y_true[mask], y_pred[mask], zero_division=0), "f1": f1_score(y_true[mask], y_pred[mask], zero_division=0), }) return out
That's the minimum. Larger systems compute false-positive rate, false-negative rate, calibration, equal opportunity, demographic parity, and selection rate per group. Different fairness definitions are mutually incompatible: you cannot satisfy them all at the same time, except in special, trivial cases (Chouldechova 2017, Kleinberg et al. 2017). Pick the definition that matches the harm you're trying to prevent, not the one that gives the nicest table.
Mitigation
In rough order of intrusiveness:
- Re-weighting: change sample weights during training to balance group representation. Cheap, often effective.
- Re-sampling: over-sample under-represented groups, or under-sample over-represented ones. Effective for class imbalance combined with group imbalance.
- Adversarial debiasing: train an adversary to predict the protected attribute from your model's representations, and penalise the main model when the adversary succeeds.
- Post-processing: adjust thresholds per group (e.g. equalised odds post-processing). Controversial because it makes the disparate treatment explicit.
- Reframe the problem: sometimes the right answer is "don't predict that".
Libraries: Fairlearn (Microsoft, Python) and AIF360 (IBM) implement these mitigations with consistent APIs. They make the mechanics easy, but they cannot decide for you about which fairness definition matters for your problem.
4. Privacy
Models can memorise their training data. Large language models can be prompted into reciting copyrighted text or personal information verbatim from their training set (Carlini et al. 2021). Image classifiers can leak training images through membership inference attacks ("was this exact image in your training set?").
Three layers of defence:
Data Minimisation
The data you don't collect can't leak. Check what you really need, and delete the rest. "We might use it later" is not a justification.
Differential Privacy in Training (DP-SGD)
A trained model is differentially private if you can prove that the model would be almost the same whether or not any single training example was included. The standard implementation, DP-SGD, clips per-example gradients and adds noise during training. It costs accuracy (often 1–10 percentage points) for a quantifiable privacy guarantee (epsilon).
Libraries: opacus for PyTorch, tensorflow-privacy for TF.
Federated Learning
Train the model on data that never leaves user devices. Each device computes a gradient update locally, and the server aggregates updates without seeing the raw data. Used at scale for Gboard's next-word prediction (Google), iOS Siri suggestions (Apple), and similar mobile keyboards. It gives strong privacy, but it is complex to engineer. It reduces leakage, but some information can still leak from the aggregated updates.
Membership Inference Attacks
This attack tests whether your model leaks training data. You train "shadow models" that imitate your model, then use them to train an attack model that predicts whether a given input was in the original training set. If the attack succeeds reliably, your model leaks. This is a real risk: over-parameterised models trained without DP are often vulnerable.
5. Explainability
Two related but different things are called by the same name:
- Interpretability: the model's structure is transparent. A linear model with five features, or a small decision tree. You can read the model and know what it's doing.
- Post-hoc explanation: the model is a black box, but you generate explanations alongside its predictions. Why did this loan get denied? Because of feature X (estimated contribution: …).
Post-hoc tools:
- LIME: fits a small interpretable model to the black box's behaviour in the neighbourhood of one input. Local explanation per prediction.
- SHAP: Shapley values from game theory. It attributes the prediction to each feature in a way that satisfies several mathematical properties (axioms) from game theory. It is the current standard.
- Integrated Gradients: for deep networks. Attributes the prediction to input features by integrating the gradient along a path from a baseline.
- Attention visualisation: for transformers. It helps intuition, but it is well documented that it is not a faithful explanation of model behaviour (Jain & Wallace 2019).
An important limit: explainability is not the same as trustworthiness. A confident-looking SHAP plot for a biased model doesn't make the model fair. It describes what the model is doing, which is necessary for debugging and required by regulators in some domains. But it doesn't improve the quality of the decisions. Use explanations to inform oversight, not as a substitute for it.
6. Documentation as Ethics
Two documents that should ship with every model:
Model Cards (Mitchell et al. 2019)
A short structured document attached to a model. Sections:
- Intended use, intended users, out-of-scope uses
- Training data summary
- Evaluation data summary
- Performance metrics, disaggregated by demographic groups
- Ethical considerations and known limitations
- Caveats and recommendations
Hugging Face generates a model card template for models on its hub. Today, a serious model release is expected to include a model card.
Datasheets for Datasets (Gebru et al. 2018)
The dataset-side equivalent. Sections:
- Motivation (why was this dataset created?)
- Composition (what's in it, how many examples, what's the schema?)
- Collection process (how was it gathered, were consents obtained?)
- Preprocessing / cleaning
- Uses (what's it appropriate for? what isn't it appropriate for?)
- Distribution and maintenance
These documents are useful work. Future users read them to decide whether to trust your work.
7. Real-World Incidents
- COMPAS: a recidivism risk-assessment tool used in US courts. ProPublica's 2016 analysis found roughly 2× higher false-positive rates on Black defendants than on white defendants for the same true outcome. The vendor disputed the methodology. The underlying mathematical impossibility of satisfying multiple fairness definitions (Chouldechova 2017) became famous because of this case.
- Facial recognition error rates. NIST's 2019 evaluation of 189 algorithms (mostly commercial) found 10–100× higher false-match rates on women, darker-skinned subjects, and Asian populations vs. white men. This was used to support several US city bans on government use of face recognition.
- Amazon's experimental hiring screening tool (reported 2018). Trained on a decade of resumes that were predominantly from men, the model learned to down-rank resumes containing the word "women's" (as in "women's chess club captain"). Amazon scrapped the project before it was deployed at scale.
- Apple Card credit limits (2019). Couples with shared finances reported the card offering the husband 10–20× higher credit limits than the wife. The bank issued a statement saying the algorithm didn't use gender as a feature. But that alone does not prove a model is fair, because other features that correlate with gender (income history, account ownership) can carry the same signal.
What these cases have in common is not bad intent. In each one, the system was released without the disaggregated evaluation that would have found the problem.
8. AI Regulation in 2026
| Region | Status | Notes |
|---|---|---|
| EU AI Act (2024, in force) | High-risk categories (employment, credit, education, law enforcement, critical infrastructure) require risk assessment, transparency, human oversight, accuracy/robustness/security obligations. "Unacceptable risk" applications (social scoring, real-time biometric ID with exceptions) are banned. | The de facto global baseline: companies serving the EU usually apply its rules everywhere instead of maintaining two versions. |
| US | A mix of different laws. State laws (NYC AI hiring bias audit, Colorado AI Act SB 24-205). Federal: NIST AI Risk Management Framework (voluntary). Executive Order 14110 (2023) set obligations for the largest models but was revoked in January 2025. | No single comprehensive federal law as of 2026. |
| UK | Pro-innovation framework: existing regulators (FCA, MHRA, etc.) extend their authority to AI. | Less prescriptive than the EU. More flexible, but harder to predict. |
| China | Generative AI regulations (2023), algorithmic recommendation regulations. | Very different assumptions and goals. Relevant to anyone with users in China. |
The practical implication: if you ship in multiple jurisdictions, the EU AI Act sets the floor. Build documentation, transparency, and oversight to its standard and you're compliant most places. If you build to a lower standard, you will have a lot of compliance work to do as soon as you grow.
9. The Practical Checklist
Before you ship an ML system, answer these:
1. Who is harmed if the model is wrong? Be specific. Name the groups, the failure modes and how severe they are.
2. Have I measured performance disaggregated by every relevant demographic? Overall metrics are not enough. Always look at the per-group table.
3. Is there a human in the loop for high-stakes decisions? For loan denial, criminal risk assessment, hiring screening and medical triage, the model should assist a person, not make the decision.
4. Can affected users appeal? Can they request an explanation? If not, people have no way to challenge the decisions. That is almost always a design failure.
5. What inputs and outputs am I logging, and for how long? Without logs you cannot audit later. With logs you have a privacy obligation. You have to plan for both.
6. Have I published a model card and a datasheet? Honest documentation is the cheapest way to make a team accountable.
7. How will I monitor drift, both input and output? Models often start hurting people when the data distribution shifts, so you need to detect it.
8. How will I roll back when something goes wrong? It should take hours, not weeks. See deployment.
The questions are simple. Answering them honestly under a tight launch deadline is hard, but it is part of the job.
10. Closing Thoughts
There is no import ethics_filter; ethics_filter.audit(model). Fairlearn, AIF360, SHAP and opacus are useful tools, but only tools. The skill is knowing where to use them, and deciding what is acceptable.
Three habits separate teams that ship responsibly from teams that ship and then have to apologise:
- Always use disaggregated metrics. Look at the table before you announce numbers.
- The documentation is part of the product. The model card, datasheet, monitoring plan and rollback plan are all released and reviewed with the model.
- Someone is accountable per decision. Never "the algorithm decided". A named person or team is responsible for what the system does, including its mistakes.
Everything in this lesson is a tool that supports those habits. No tool replaces them.
Common Mistakes
1. Optimising only overall accuracy.
A 95% accurate model with 99% accuracy on the majority group and 60% on a minority is not "95% accurate" in any meaningful sense. Always report disaggregated metrics.
2. Skipping model and dataset documentation.
"We'll write the model card after we ship." Usually, nobody does. Later, someone (often you) has to maintain an undocumented model with no idea what it is safe to use for.
3. Assuming "the data speaks for itself".
Data is collected by humans with priorities, labelled by humans with priors, sampled by processes with selection effects. The data reflects the choices and biases of the process that produced it. Check where your data came from, the same way you check where your code came from.
4. No recourse mechanism for users.
The model denies someone something: a loan, a job, parole, an insurance claim. They ask why, but there is no way to reach a human, get an explanation or challenge the decision. Leaving out recourse because it is expensive is a failure that regulators are punishing more and more often.
5. Treating fairness as a single number.
Demographic parity, equal opportunity, equalised odds and calibration are different definitions, and in general they are mathematically incompatible. You have to pick which kind of fairness you're optimising for, and that choice is about values, not only about technology. Publishing one number without naming the definition is misleading.
6. Conflating explainability with safety.
A reasonable-looking SHAP plot does not mean the model is fine. Explanations describe behaviour, but they don't validate it. A confident wrong answer with a confident wrong explanation is still wrong. Use explanations for debugging and regulatory compliance, not as a substitute for evaluation.
🎯 Your Turn: Per-Group Precision and Recall
You're given a small inline dataset, a trained classifier, and a "group" column with values A or B. Compute per-group precision and recall. Print whether they differ meaningfully (defined as more than 10 percentage points absolute on either metric). Requirements:
- Use the inline data provided in the skeleton.
- Compute precision and recall for each group.
- Print a small table.
- Print a one-line verdict: either "Disparity detected on
" or "No major disparity detected".
Skeleton:
import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.metrics import precision_score, recall_score # Inline toy data: feature x, label y, group g rng = np.random.default_rng(42) X = rng.normal(size=(400, 2)) g = rng.choice(["A", "B"], size=400, p=[0.5, 0.5]) # Group B has noisier labels, and this creates a disparity y = (X[:, 0] + 0.5 * X[:, 1] > 0).astype(int) flip = (g == "B") & (rng.random(400) < 0.3) y_noisy = np.where(flip, 1 - y, y) # Train a classifier on the noisy labels model = LogisticRegression().fit(X, y_noisy) y_pred = model.predict(X) # TODO 1: compute precision and recall for group A # TODO 2: compute precision and recall for group B # TODO 3: print a table with group, precision and recall (3 decimals) # TODO 4: compare the absolute differences and print if there is a disparity
Hint 1: Masking by group
mask_a = g == "A". Pass y_noisy[mask_a] and y_pred[mask_a] to precision_score / recall_score. Use zero_division=0 on small slices to avoid warnings.
Hint 2: The disparity check
abs(precision_a - precision_b) > 0.10 or abs(recall_a - recall_b) > 0.10 → disparity. Pick the larger of the two deltas to name in the verdict line.
Show full solution
import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.metrics import precision_score, recall_score # Inline toy data rng = np.random.default_rng(42) X = rng.normal(size=(400, 2)) g = rng.choice(["A", "B"], size=400, p=[0.5, 0.5]) y = (X[:, 0] + 0.5 * X[:, 1] > 0).astype(int) flip = (g == "B") & (rng.random(400) < 0.3) y_noisy = np.where(flip, 1 - y, y) model = LogisticRegression().fit(X, y_noisy) y_pred = model.predict(X) def metrics_for(group_label): mask = g == group_label return { "group": group_label, "n": int(mask.sum()), "precision": precision_score(y_noisy[mask], y_pred[mask], zero_division=0), "recall": recall_score(y_noisy[mask], y_pred[mask], zero_division=0), } rows = [metrics_for("A"), metrics_for("B")] print(f"{'group':<6} {'n':>4} {'precision':>10} {'recall':>8}") for r in rows: print(f"{r['group']:<6} {r['n']:>4} {r['precision']:>10.3f} {r['recall']:>8.3f}") # Compute disparities dp = abs(rows[0]["precision"] - rows[1]["precision"]) dr = abs(rows[0]["recall"] - rows[1]["recall"]) THRESHOLD = 0.10 if dp > THRESHOLD or dr > THRESHOLD: worst = "precision" if dp >= dr else "recall" delta = max(dp, dr) print(f"\nDisparity detected on {worst}: {delta:.3f} absolute difference between groups") else: print(f"\nNo major disparity detected (max delta: {max(dp, dr):.3f})")
Sample output:
group n precision recall A 199 0.989 1.000 B 201 0.695 0.682 Disparity detected on recall: 0.318 absolute difference between groups
Notice what this exercise doesn't do: fix the disparity. That's deliberate. The first step in addressing bias is measuring it, and many ML systems in production skip even that. Once you know there's a 32-point recall gap between groups, the next step is the harder work from section 3, which needs judgement: reweight, resample, adversarially debias, post-process, or step back and ask whether the problem framing is wrong. Running the tools is easy, but deciding what to do is the real work.
Try extending the script. Add false-positive rate and false-negative rate per group. Recompute after retraining on y (the clean labels) instead of y_noisy. See how much of the disparity was caused by the label noise and how much by the model itself.
What You Learned
- ML harms differ from non-ML harms in scale, opacity, and path dependence.
- The five harm categories: bias/discrimination, privacy, misinformation, displacement, autonomous decisions without recourse.
- Bias sources are data, labels, and problem framing. The last one is the hardest to fix. Detect with disaggregated metrics, and mitigate with reweighting, resampling, adversarial debiasing, post-processing, or reframing.
- Different fairness definitions are mathematically incompatible. Pick the one matching the harm, and don't claim to satisfy all of them.
- Privacy mitigations: data minimisation, DP-SGD, federated learning. Membership inference attacks are the test.
- Explainability (LIME, SHAP, Integrated Gradients) describes behaviour, but it does not validate it. Explainability is not the same as trustworthiness.
- Model cards and datasheets for datasets are essential documentation. Release them with every model.
- EU AI Act is the de-facto global baseline. Build to it.
- The practical checklist (who's harmed? disaggregated metrics? human-in-the-loop? recourse? logging? documentation? monitoring? rollback?) is part of every release.
- There is no
import ethics. Tools matter, but the work is judgement.
You've reached the end of the AI track. The Generative AI track continues from here. It ends with building production AI applications. The practices in this lesson apply to all of them.
Found this useful? Share it with a friend who’s learning Python.