Unit 2B · Supervised Learning · Course Outcomes CO2, CO5
A model is a claim. This is the audit.
Unit 2A built six models and reported every one of them with training accuracy, while warning each time that the number means nothing. This file is the repair. It turns out that a single accuracy figure can stay fixed at 0.70 while the model changes from useless to excellent — and the whole point is being able to see the difference.
Section 2.4.1
Ten students, ten probabilities
Is this model any good?
A model trained on the eight students of Unit 2A is applied to ten it has never seen. It outputs a probability of passing for each. Four of the ten actually passed.
Look at the strip before reading any metric. The model is broadly right — passes cluster to the right, failures to the left — but not cleanly: one failure scored 0.78 and one pass scored only 0.35. Every number in this file is a different way of summarising exactly that imperfection.
Sections 2.4.1 – 2.4.2
Draw the line at 0.5
What did that cost?
Threshold at 0.5 and the ten split into four groups: 3 true positives, 2 false positives, 1 false negative, 4 true negatives. Accuracy 0.70.
Those four counts are the confusion matrix, and every classification metric in existence is an arithmetic combination of them. Precision is 0.60, recall 0.75, F1 0.6667 — three different summaries of one table, each answering a different question.
Sections 2.4.3 – 2.4.4
Or draw it anywhere
Why commit to one cut at all?
Move the threshold from 0.70 to 0.30 and recall rises from 0.50 to 1.00 while precision falls from 0.6667 to 0.5714. Accuracy stays at exactly 0.70 the whole way.
ROC and precision–recall curves plot every threshold at once, and the area under the ROC curve is 20/24 = 0.8333 — the probability that a random pass outranks a random failure. Then 2.4.4 puts the cost of each error type into the decision, which is how a threshold is actually chosen.
Section 2.6
The same model, split by group
Fair to whom?
Now suppose the applicants come from two groups with different base rates. One threshold, one model, and the group with fewer positives gets a lower recall and a lower precision.
You cannot fix all of it. Equal selection rates, equal recall and equal precision are mathematically incompatible whenever the base rates differ, and section 2.6 proves it in four lines. Choosing which to equalise is a decision about values, and it cannot be delegated to the model.
What you need before this chapter
Unit 2A, and specifically three things from it. That a classifier outputs a probability and a threshold turns it into a label (2.3.1). That a validation split which has influenced a decision can no longer report an honest number (2.1). And that log loss grades confidence while accuracy grades only which side of the line you fell on (2.3.1).
From Unit 1 you need log loss itself (1.3) and the bias–variance vocabulary (1.6). Nothing here requires the SVM, tree or ensemble material of 2A, so this file can be read directly after 2.3.1 if you are short of time.
The test set this file uses
Ten new students, none of them in Unit 2A's eight. The model has produced a probability of passing for each, and we now know what actually happened. Sorted by score, highest first, because almost every technique in 2.4 depends on that ordering.
| Student | P(pass) predicted | Actual | rank | at t = 0.5 the model says |
|---|---|---|---|---|
| S1 | 0.92 | pass | 1 | pass — correct |
| S2 | 0.85 | pass | 2 | pass — correct |
| S3 | 0.78 | fail | 3 | pass — false positive |
| S4 | 0.66 | pass | 4 | pass — correct |
| S5 | 0.54 | fail | 5 | pass — false positive |
| S6 | 0.47 | fail | 6 | fail — correct |
| S7 | 0.35 | pass | 7 | fail — false negative |
| S8 | 0.24 | fail | 8 | fail — correct |
| S9 | 0.18 | fail | 9 | fail — correct |
| S10 | 0.09 | fail | 10 | fail — correct |
Four passes and six failures, so the prevalence — the proportion of positives — is 0.4. Keep that number: it is the baseline that several metrics are measured against, and it is the reason accuracy will mislead you in section 2.4.2.
Three rows are highlighted because they are the model's three mistakes at a threshold of 0.5, and every one of them is instructive. S3 failed despite scoring 0.78, so the model was confidently wrong. S5 failed at 0.54, barely over the line. S7 passed at 0.35, and is the only pass the model missed. Which of those three matters most depends entirely on what the model is for, and that is section 2.4.4.
The convention this file uses
Which class you call positive is a choice, and it silently determines what precision and recall mean. Reversing it here — calling failure the positive class — gives entirely different numbers for the same model. State the convention before quoting any metric; a great deal of confusion in reported results comes from not doing so.
The Confusion Matrix
Four numbers, from which every classification metric is built. Get these right and the rest is arithmetic.
The question
Accuracy is one number describing ten decisions. Ten decisions can go wrong in two qualitatively different ways — a false alarm and a miss — and those two failures usually have wildly different consequences. One number cannot distinguish them, so a single accuracy figure is compressing away the thing you most need to know.
The intuition
A smoke alarm can fail twice over. It can shriek while you make toast, which is annoying. It can stay silent during a fire, which is fatal. Both are errors and only a fool would trade them one for one.
Accuracy trades them one for one. It counts mistakes without asking which kind, so a model that never predicts a fire scores extremely well in a building that rarely burns. The confusion matrix simply refuses to do the compression: it keeps the two error types in separate boxes and makes you look at both.
The formal treatment
The naming is genuinely confusing and the confusion is worth naming. Recall, sensitivity, true positive rate and hit rate are four names for the identical quantity. Precision and positive predictive value are two names for another. Specificity is the true negative rate. Different fields settled on different words for the same arithmetic, and a question paper may use any of them.
The structural point to hold onto: recall has the actual positives as its denominator, precision has the predicted positives. Recall looks down a column of the table, precision across a row. Every mix-up in this topic is a mix-up about which denominator.
Multi-class
With K classes the matrix is K×K, with correct predictions on the diagonal. Per-class metrics are computed one-versus-rest, then combined three ways: macro averaging takes the unweighted mean over classes, so a rare class counts as much as a common one; weighted averaging weights by class size; micro averaging pools all the counts first, which for single-label problems makes micro-precision, micro-recall and accuracy all equal. Macro is the honest choice when the rare classes matter, which is usually why you have a rare class.
Depth — two summaries that survive imbalance
Balanced accuracy is the mean of recall and specificity, (TPR + TNR)/2. It scores a constant predictor at exactly 0.5 no matter how skewed the classes, which is the property accuracy lacks.
Matthews correlation coefficient uses all four cells and is the one summary that is hard to game:
It is the Pearson correlation between the predicted and actual labels treated as ±1 variables. A constant predictor scores 0, and unlike F1 it is symmetric in the two classes, so relabelling which class is positive leaves it unchanged. Cohen's kappa answers a related question — how much better than chance agreement, κ = (pₒ − pₑ)/(1 − pₑ) where pₑ is the agreement expected if the predictions were shuffled. Both are worth reporting; MCC is the more informative of the two.
The worked example
Worked 2.4.1 — the full confusion matrix at three thresholds
the central table of this filePredict pass when p ≥ 0.50, so S1 to S5 are flagged and S6 to S10 are not.
| t | TP | FP | FN | TN | accuracy | precision | recall | specificity | F1 | MCC | κ |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0.70 | 2 | 1 | 2 | 5 | 0.7000 | 0.6667 | 0.5000 | 0.8333 | 0.5714 | 0.3563 | 0.3478 |
| 0.50 | 3 | 2 | 1 | 4 | 0.7000 | 0.6000 | 0.7500 | 0.6667 | 0.6667 | 0.4082 | 0.4000 |
| 0.30 | 4 | 3 | 0 | 3 | 0.7000 | 0.5714 | 1.0000 | 0.5000 | 0.7273 | 0.5345 | 0.4444 |
Meanwhile recall doubles from 0.5000 to 1.0000, F1 rises from 0.5714 to 0.7273, and MCC rises from 0.3563 to 0.5345.
Three genuinely different classifiers, indistinguishable by accuracy, clearly ranked by everything else.
This is not a contrivance. Accuracy counts FP + FN and treats the two as interchangeable, so any change that converts one false negative into one false positive leaves it untouched. Lowering the threshold does exactly that, one student at a time. Accuracy is blind to the trade it is making, and the trade is the entire decision.
MCC and kappa both rank t = 0.30 highest here, which is worth noticing: on this test set, catching every pass is worth the extra false alarm even under a symmetric criterion. Section 2.4.4 asks the sharper question of what happens when the two error types have genuinely different costs.
The visualization
One threshold, four counts, every metric
interactive — the flagshipDrag the threshold slowly from 1.0 down to 0.0 and watch accuracy. It moves in a narrow band and returns to 0.700 repeatedly, while precision falls monotonically and recall rises monotonically. That divergence between one summary and the underlying counts is the reason this whole section exists.
The pitfalls
Where marks are lost
- Swapping the denominators of precision and recall. Recall divides by actual positives, precision by predicted positives. Write the table out before computing either.
- Not stating which class is positive. On this test set, calling failure positive gives precision 4/5 = 0.8000 and recall 4/6 = 0.6667 — different numbers, same model.
- Transposing the matrix. Conventions differ over whether rows are predictions or actuals. Label the axes on every matrix you draw, including in an exam.
- Reporting accuracy alone on imbalanced data. See 2.4.2. It is the single most common reporting failure in applied work.
- Reading a high accuracy as a working model. Compare against the majority-class baseline first: here that baseline is 0.6000, so 0.7000 is a gain of ten points, not seventy.
- Computing micro-averaged precision for a single-label multi-class problem and presenting it as new information. It equals accuracy exactly.
- Building the matrix on the test set more than once. Each look is a decision. Per 2.1, that makes it a validation set.
Practice
P2.4.1.1 (direct) — A classifier on 200 samples gives TP = 40, FP = 25, FN = 10, TN = 125. Compute accuracy, precision, recall, specificity, balanced accuracy and MCC.
Note the shape of the result: recall 0.80 with precision only 0.62 says the model casts a wide net, flagging 65 to catch 40 of the 50 real positives. Whether that is right depends on the cost of the 25 false alarms.
P2.4.1.2 (variation) — Same 200 samples, but relabel so that the negative class is now called positive. Recompute all six metrics and say which are unchanged.
Accuracy, balanced accuracy and MCC are symmetric: they treat the two classes alike, so relabelling cannot change them. Precision and recall are not, and they swap partners — recall becomes the old specificity and vice versa. Precision changes most dramatically, from 0.6154 to 0.9259, purely by renaming.
The practical consequence is that F1, being built from precision and recall, is also asymmetric, so an F1 score is meaningless without knowing which class was positive. MCC has no such ambiguity, which is the main argument for reporting it alongside.
P2.4.1.3 (interpretation) — A team reports "97% accuracy" for a model detecting a manufacturing defect that occurs in 2% of units. What is the least charitable interpretation, and what four numbers would you request?
The least charitable interpretation is that the model never predicts a defect. Always answering "no defect" scores 98% accuracy on a 2% defect rate — so 97% is actually worse than the trivial baseline, and consistent with a model that finds nothing while occasionally raising a false alarm.
The four numbers to request are the raw cell counts TP, FP, FN and TN. Everything else is derivable from them, and unlike any ratio they cannot hide a degenerate model: if TP is 0, the matrix says so immediately.
Two further requests worth making. The majority-class baseline accuracy, so the 97% has something to be compared against. And the cost of a missed defect versus a false alarm, because in manufacturing those differ by orders of magnitude and the threshold should have been set from them rather than left at 0.5. Until you have the counts, "97% accuracy" carries almost no information.
P2.4.1.4 (synthesis) — Using 2.3.1, explain why accuracy stayed at exactly 0.7000 across all three thresholds in Worked 2.4.1 while log loss would not have moved at all. What does each metric respond to?
Accuracy responds only to which side of the threshold each probability fell on. Lowering the threshold past one student's score changes exactly one prediction, converting one false negative into a true positive or one true negative into a false positive. Between 0.70 and 0.50 the model gained one TP and one FP, so TP + TN went from 7 to 7 — one gained, one lost. Accuracy counts FP + FN without weighting, so a one-for-one swap is invisible to it. That happened twice in a row here, which is why the figure repeats.
Log loss does not see the threshold at all. It is computed from the probabilities themselves, −Σ[y ln p + (1−y)ln(1−p)]/n, and the threshold appears nowhere in that expression. Moving it cannot change log loss by any amount. This is the same fact the weight-scale control in 2.3.1's widget demonstrated from the other direction: scaling the weights changed log loss while leaving accuracy and the boundary fixed.
So the two metrics are sensitive to orthogonal things. Log loss grades the model — how good are the probabilities. Accuracy, precision, recall and F1 grade the model plus a threshold — a deployment decision. Reporting only accuracy conflates two choices and makes it impossible to tell whether a poor result came from a bad model or a badly chosen cut-off. Report a threshold-free measure (log loss, AUC) for the model and a thresholded matrix for the deployment.
Precision, Recall and the F-scores
The trade-off you cannot escape, the harmonic mean that summarises it, and the β that lets you say which side you care about.
The question
Precision and recall move in opposite directions. Worked 2.4.1 showed it: as the threshold fell, precision went 0.6667 → 0.6000 → 0.5714 while recall went 0.5000 → 0.7500 → 1.0000. So you cannot maximise both and any claim to have done so should be checked.
Two questions follow. Can the pair be summarised as one number, for ranking models? And how do you express that in your problem, missing a positive is five times worse than a false alarm?
The intuition
Fishing with a net. A wide net catches every fish in the lake — perfect recall — along with boots, weeds and a bicycle, so precision is dreadful. A tiny net catches one fish and nothing else — perfect precision, dreadful recall.
There is no net that catches every fish and nothing else, unless the lake contains only fish. So the question is never "which is better" but "which failure can you afford". A cancer screening test should have a wide net; a system that automatically deletes email should have a very small one.
The harmonic mean is the right way to combine them because it is dominated by the smaller of the two. Precision 1.0 with recall 0.01 gives an arithmetic mean of 0.505, which flatters a useless model; the harmonic mean gives 0.0198, which does not.
The formal treatment
Read the β convention carefully, because the direction trips people. β multiplies the precision term in the denominator, and a larger denominator term means less influence — so a larger β weights recall more. The mnemonic that works: F₂ is for when you are afraid of misses.
Notice what F1 leaves out. The formula 2TP/(2TP + FP + FN) contains no TN at all. F1 is entirely indifferent to how many true negatives you got right, which is exactly what you want when negatives are abundant and uninteresting, and exactly what you do not want when correctly clearing a negative case has real value.
Depth — when accuracy actively lies, quantified
A hospital screens 1,000 patients for a condition affecting 10 of them. Consider the model that always answers "healthy".
Ninety-nine percent accurate, and it has never once identified a sick patient. Now a real model:
The second model finds 8 of the 10 sick patients and is 8 points less accurate. Any accuracy-based model selection would reject it, and any clinician would deploy it, because 90 unnecessary follow-up tests is a trivial price for 8 lives. Its precision of 0.0816 is genuinely poor — only 1 in 12 flagged patients is ill — and is nonetheless the correct model, because a follow-up test is cheap and a missed diagnosis is not. This is the case study for reporting recall and precision separately and choosing the threshold from costs.
The worked example
Worked 2.4.2 — F1, F2 and F0.5 across the three thresholds
β changes the winnert = 0.70, 0.50, 0.30, and say which threshold each criterion prefers.The second form needs no division until the last step and is what to use under exam conditions.
F₂ = 0.7143 exceeds F1 = 0.6667 because recall (0.7500) exceeds precision (0.6000), and F₂ leans toward recall. F₀.₅ = 0.6250 sits below F1 for the mirror reason. Every Fβ lies between precision and recall, and β chooses where.
| t | precision | recall | F₀.₅ | F1 | F₂ | accuracy |
|---|---|---|---|---|---|---|
| 0.70 | 0.6667 | 0.5000 | 0.6250 | 0.5714 | 0.5263 | 0.7000 |
| 0.50 | 0.6000 | 0.7500 | 0.6250 | 0.6667 | 0.7143 | 0.7000 |
| 0.30 | 0.5714 | 1.0000 | 0.6250 | 0.7273 | 0.8696 | 0.7000 |
F₂ separates the thresholds most sharply, 0.5263 to 0.8696, because recall varies most and F₂ weights recall.
The lesson is not that t = 0.30 is correct. It is that the choice of metric is a choice of threshold, made before you look at the data, and it should follow from what the model is for. Picking the metric after seeing which threshold you prefer is a way of dressing a preference up as a result.
The visualization
How prevalence destroys accuracy and leaves recall alone
interactive — slide the base rateHold recall and specificity fixed — the model's actual skill does not change — and slide prevalence down. Accuracy climbs toward 1 for a reason that has nothing to do with the model: negatives dominate and specificity is high. Precision collapses, because the pool of true positives shrinks while false positives keep arriving from the growing negative pool. Push prevalence to 0.01 and watch a model with recall 0.80 report a precision under 0.10 — the depth box's hospital, reproduced.
The pitfalls
Where marks are lost
- Getting
βbackwards. Largerβfavours recall. Check against the limits:β → ∞gives recall,β → 0gives precision. - Using the arithmetic mean of precision and recall. It rewards extreme imbalance between them. The harmonic mean exists to punish it.
- Reporting F1 on a problem where true negatives matter. F1 contains no TN term. If correctly clearing a negative case has value, use balanced accuracy or MCC.
- Comparing F1 across datasets with different prevalence. F1 depends on the base rate, so an F1 of 0.6 on a balanced set and on a 1% set are not comparable achievements.
- Choosing the metric after seeing the results. This is the most consequential error in the section, and it is invisible in a written report.
- Treating undefined as zero without saying so. Precision is undefined when nothing is flagged. Libraries default to 0 with a warning; a report should state which convention it used.
- Optimising F1 by threshold on the test set. Tune the threshold on validation data. It is a hyperparameter like any other.
Practice
P2.4.2.1 (direct) — A model has precision 0.30 and recall 0.90. Compute F1, F2 and F0.5, and comment on the spread.
The spread from 0.3462 to 0.6429 is wide because precision and recall are far apart, and each Fβ sits nearer whichever it favours. Note also that the arithmetic mean would be 0.600, comfortably above F1's 0.4500 — the harmonic mean is refusing to let recall of 0.90 excuse precision of 0.30.
This profile — high recall, low precision — describes a screening tool. It is the right shape when a miss is costly and a false alarm triggers a cheap second check, and the wrong shape when the flag itself does harm.
P2.4.2.2 (variation) — A fraud detector on 100,000 transactions with 200 frauds achieves recall 0.75 and specificity 0.99. Compute the confusion matrix, precision, F1 and accuracy, and say what the precision means operationally.
Operationally, precision 0.1307 means an investigator opening flagged cases finds fraud in roughly 1 of every 8. At 1,148 flags that is 1,148 investigations to catch 150 frauds, and whether that is acceptable is an economic question about the cost of an investigation against the value of a caught fraud.
Note that accuracy of 0.98952 is below the do-nothing baseline of 0.99800, which is the depth box's pattern exactly. A specificity of 0.99 sounds excellent and produces 998 false alarms, because 1% of 99,800 is a large number. When negatives are abundant, a specificity of 0.99 is not nearly good enough, and this is why fraud systems are tuned on precision at a fixed alert volume rather than on any accuracy-like measure.
P2.4.2.3 (interpretation) — Two models are proposed for triaging emergency-room patients as high or low risk. Model A: precision 0.85, recall 0.40. Model B: precision 0.45, recall 0.95. Which would you deploy, and what would change your mind?
Model B, and not by a small margin. In triage a false negative is a high-risk patient sent home, and a false positive is a low-risk patient who waits for a doctor they did not need. Those costs differ by orders of magnitude. Model A misses 60% of high-risk patients, which is not a triage system.
Quantitatively, with β = 3 to say a miss is nine times worse than a false alarm: F₃(A) = 10(0.85)(0.40)/(9(0.85) + 0.40) = 3.40/8.05 = 0.4224 and F₃(B) = 10(0.45)(0.95)/(9(0.45) + 0.95) = 4.275/5.00 = 0.8550. B wins by a factor of two. Choosing β is where the clinical judgement enters, and it should be recorded.
What would change my mind. If a positive flag consumes a genuinely scarce resource — the only available surgeon, a single ICU bed — then B's precision of 0.45 means over half that resource is spent on patients who did not need it, and the false positives start causing harm to third parties. Also, if these are two thresholds on the same underlying model, the right response is neither: get the ROC curve of 2.4.3, and pick the operating point from an explicit cost ratio rather than from two arbitrary candidates.
P2.4.2.4 (synthesis) — At t = 0.30 the model reaches recall 1.0000 on the ten test students. Using 1.6 and 2.1, explain why you should not report that as evidence the model catches every pass.
Three separate problems, and each alone would be enough.
The sample is four positives. Recall 1.0000 means 4 of 4, and the 95% confidence interval for a proportion of 4/4 reaches down to about 0.40. The point estimate is 1.0 and the evidence is compatible with a true recall of one half. Any recall computed from four cases is a number with almost no precision, in the statistical sense.
The threshold was chosen by looking at these ten students. Per 2.1, a split that has influenced a decision cannot report an honest number. Sweeping the threshold to find the best recall and then quoting that recall is selection on the test set, and the quoted figure is optimistically biased by exactly the amount the search bought. The threshold should be fixed on validation data and then applied once.
Recall 1.0000 is trivially available. Set t = 0 and every classifier on earth achieves it. Recall alone is not a measure of skill; the pair (recall, precision) is, and at t = 0.30 precision fell to 0.5714. In 1.6's terms, driving one metric to its extreme on a small sample is fitting the evaluation rather than the data — the same failure as the degree-4 polynomial, relocated from the model to the report.
Threshold-free Evaluation: ROC and Precision–Recall
Stop choosing a threshold and evaluate every threshold at once. Two curves, two areas, and a rule for which one to trust.
The question
Sections 2.4.1 and 2.4.2 both had the same awkward shape: every metric depended on a threshold, and the threshold was arbitrary. If you want to compare two models rather than two deployment decisions, you need a measure that does not involve a threshold at all.
The intuition
Forget thresholds and look at the ranking. The model produced an ordering of the ten students, and a good model puts passes near the top. In fact here is a threshold-free question with a clean answer: pick one pass and one failure at random. What is the probability that the model scored the pass higher?
That probability is the area under the ROC curve. It is a statement purely about ordering, so it is unaffected by any monotone rescaling of the scores — and it is exactly what you want when the ranking is what will be used, as in search results, credit scoring or triage queues.
The formal treatment
That last identity is the useful one for hand computation and the one that makes AUC interpretable. With 4 positives and 6 negatives there are 24 pairs to check, and the AUC is simply the fraction ordered correctly.
The baselines differ in a way that decides which curve to use. ROC's baseline is the diagonal regardless of prevalence, because both axes are normalised within a class. PR's baseline is the prevalence line, which drops as positives become rarer. So on heavily imbalanced data ROC keeps looking respectable while PR does not, and PR is the more honest picture.
Depth — why ROC flatters an imbalanced problem
Return to the fraud detector of P2.4.2.2: 200 frauds among 100,000 transactions, recall 0.75, specificity 0.99. Its ROC point is (FPR, TPR) = (0.01, 0.75), which sits high and far left — visually excellent, and it would contribute to an AUC well above 0.9.
Its PR point is (recall, precision) = (0.75, 0.1307), which sits near the floor. Both describe the same 998 false alarms. The difference is the denominator: FPR divides those 998 by the 99,800 negatives and gets a reassuring 0.01, while precision divides them by the 1,148 flags and gets a sobering 0.13.
The rule that follows: use ROC when both classes matter and the classes are roughly balanced, and use precision–recall when the positive class is rare and is the one you care about. Report both if you are unsure; they cost nothing extra to compute and they answer different questions.
The worked example
Worked 2.4.3 — build the ROC curve and compute AUC two ways
every threshold, by handWork down the ranked list. Each step admits one more student, so TP rises by 1 for a pass and FP rises by 1 for a failure — the curve steps up on a pass and right on a failure. With 4 positives each up-step is 1/4 and with 6 negatives each right-step is 1/6.
| t | admits | TP | FP | FN | TN | TPR | FPR | precision | step |
|---|---|---|---|---|---|---|---|---|---|
| above all | — | 0 | 0 | 4 | 6 | 0.0000 | 0.0000 | — | |
| 0.92 | S1 pass | 1 | 0 | 3 | 6 | 0.2500 | 0.0000 | 1.0000 | up |
| 0.85 | S2 pass | 2 | 0 | 2 | 6 | 0.5000 | 0.0000 | 1.0000 | up |
| 0.78 | S3 fail | 2 | 1 | 2 | 5 | 0.5000 | 0.1667 | 0.6667 | right |
| 0.66 | S4 pass | 3 | 1 | 1 | 5 | 0.7500 | 0.1667 | 0.7500 | up |
| 0.54 | S5 fail | 3 | 2 | 1 | 4 | 0.7500 | 0.3333 | 0.6000 | right |
| 0.47 | S6 fail | 3 | 3 | 1 | 3 | 0.7500 | 0.5000 | 0.5000 | right |
| 0.35 | S7 pass | 4 | 3 | 0 | 3 | 1.0000 | 0.5000 | 0.5714 | up |
| 0.24 | S8 fail | 4 | 4 | 0 | 2 | 1.0000 | 0.6667 | 0.5000 | right |
| 0.18 | S9 fail | 4 | 5 | 0 | 1 | 1.0000 | 0.8333 | 0.4444 | right |
| 0.09 | S10 fail | 4 | 6 | 0 | 0 | 1.0000 | 1.0000 | 0.4000 | right |
The step column is the shortest description of the curve, and reading it back gives the model's ranking directly: up, up, right, up, right, right, up, right, right, right. Two passes at the very top, then a failure, and the last pass only after three failures — that final "up" at rank 7 is student S7, and it is where the model gave away most of its area.
There are 4 × 6 = 24 (pass, fail) pairs. Count how many the model ordered correctly, by taking each pass and counting the failures ranked below it.
The curve is a staircase, so the area is a sum of rectangles: each right-step of width 1/6 contributes its width times the current TPR height.
The two routes agree because they are the same computation. Each rectangle counts exactly the passes ranked above that particular failure, and summing over failures counts every concordant pair once.
Read the AUC as a sentence: pick a passing student and a failing student at random, and the model gives the pass the higher score 83.3% of the time.
The four discordant pairs are identifiable — S3 above S4, and S3, S5, S6 all above S7.
Naming the discordant pairs is the most useful diagnostic in this section. Every one of the four involves either S3, the failure scored 0.78, or S7, the pass scored 0.35. Fixing the model means understanding those two students, not adjusting a threshold. A threshold cannot repair a ranking error; only a better model can.
The visualization
Both curves, with the operating point you choose
interactive — the threshold moves bothROC — TPR against FPR
Precision–recall
The amber dot is the operating point that a threshold selects. Sliding the threshold moves the dot along the curves; it does not change the curves, because the curves are properties of the model's ranking and the ranking does not depend on where you cut. That separation — the curve is the model, the point is the deployment — is the single most useful idea in this section.
The pitfalls
Where marks are lost
- Using ROC on heavily imbalanced data and concluding the model is good. See the depth box. AUC above 0.9 is compatible with a precision of 0.13.
- Reading AUC as accuracy. It is a ranking probability. A model with AUC 0.95 can have terrible accuracy at every threshold if its probabilities are badly calibrated.
- Comparing AUCs of two models whose curves cross. Equal areas can hide opposite behaviour — one model better at low FPR, the other at high. Compare at the operating region you will actually use, or report partial AUC.
- Interpolating the PR curve linearly. Precision is not linear in recall between adjacent thresholds, so linear interpolation overstates the area. Average precision as defined above does not interpolate, which is why it is preferred.
- Forgetting the PR baseline is the prevalence. An average precision of 0.45 is excellent at 5% prevalence and poor at 40%. Always state the prevalence next to it.
- Computing AUC from hard labels. With only 0/1 predictions there is no ranking, the curve has one interior point, and the "AUC" reduces to balanced accuracy. AUC needs scores.
- Quoting AUC on a tiny test set without an interval. Here it rests on 24 pairs. A single swap of S3 and S4 would move it from 0.8333 to 0.8750.
Practice
P2.4.3.1 (direct) — A model ranks six samples, highest first, with actual labels: pass, fail, pass, pass, fail, fail. Compute the AUC by counting pairs, and give the ROC step sequence.
Cross-check by area: right-steps of width 1/3 occur at TPR heights 1/3, 1, 1 → (1/3)(1/3 + 1 + 1) = (1/3)(7/3) = 7/9. ✓ The two discordant pairs both involve the failure at rank 2, which outranks the passes at ranks 3 and 4.
P2.4.3.2 (variation) — Suppose S3 and S4 in the main test set swap scores, so the ranking becomes pass, pass, pass, fail, fail, fail, pass, fail, fail, fail. Recompute the AUC and average precision.
One swap between adjacent ranks moved AUC by 1/24 = 0.0417 and average precision by 0.0625. That sensitivity is the honest scale of a metric computed from 24 pairs, and it is why an AUC quoted to three decimal places on a ten-row test set is false precision. Note also that the remaining three discordant pairs all involve S7, the pass at rank 7 — that single badly-ranked student now accounts for every error the model makes.
P2.4.3.3 (interpretation) — Model A has AUC 0.91 and average precision 0.34. Model B has AUC 0.88 and average precision 0.51. Prevalence is 3%. Which is better, and what does the disagreement tell you?
Model B, on this evidence. At 3% prevalence the positive class is rare and is presumably the one you care about, so the depth box's rule says trust the PR summary. Average precision 0.51 against a baseline of 0.03 is a seventeen-fold improvement over chance; 0.34 is an eleven-fold improvement. B is substantially the better model where it matters.
What the disagreement tells you is where each model's errors sit. AUC integrates over all thresholds including very permissive ones, and it normalises false positives by the huge negative pool. A has the better global ranking but is making its mistakes at the top of the list — a few high-scoring negatives, which barely dent FPR but wreck precision exactly where you operate. B ranks slightly worse overall while keeping the top of its list clean.
What to do. Compare them at a fixed operating point you would actually deploy: precision at the top 100 alerts, or recall at a fixed alert budget. That is the number the business cares about and neither summary reports it directly. Also check whether the curves cross, since two models with different error profiles usually do, and the crossing point tells you which model wins in which regime.
P2.4.3.4 (synthesis) — Using 2.3.1's weight-scale result, explain why AUC is unchanged by multiplying a logistic model's weights by 4, while accuracy at a fixed threshold might change. Then state what AUC cannot detect.
Multiplying all weights and the intercept by 4 maps each score z to 4z, and the sigmoid is monotone increasing, so each probability σ(z) maps to σ(4z) — a strictly increasing transformation. The ordering of the ten students is therefore identical. AUC depends only on the ordering, so it is exactly unchanged. Average precision, being also purely ordinal, is unchanged too.
Accuracy at a fixed threshold can change, because the probabilities move even though their order does not. A student at p = 0.54 has z = 0.1602, and after scaling z = 0.6408 gives p = 0.6549 — still above 0.5, so in this particular case no prediction flips. But a threshold of 0.6 would have excluded that student before scaling and included them after. Accuracy grades the model plus the threshold; scaling changes the relationship between the two.
What AUC cannot detect is miscalibration. The 4×-scaled model is wildly overconfident — it will report probabilities near 0.99 for students it has seen once — and its AUC is identical to the well-calibrated version's. A model can have AUC 1.0000 and probabilities that are all wrong in magnitude. If the number will be consumed as a probability, in an expected-cost calculation or shown to a person, AUC is not enough and section 2.4.6 is the missing check.
Choosing a Threshold
The default of 0.5 is a convention, not a result. Here is where the number actually comes from.
The question
Every metric so far took the threshold as given. But 0.5 is only optimal under two assumptions that are almost never both true: that the two error types cost the same, and that the model's probabilities are correct. Where does the right threshold come from?
The intuition
You are deciding whether to carry an umbrella. The forecast says 30% rain. You do not need a 50% chance to bring one, because the cost of carrying an unused umbrella is small and the cost of being soaked in a suit is large. Your personal threshold is maybe 15%.
That is the entire theory. The threshold is the probability at which the expected cost of acting equals the expected cost of not acting, and it follows from the costs, not from the model.
The formal treatment
Three properties of this formula are worth internalising. It depends only on the ratio of costs, so you never need absolute currency values — "a miss is ten times worse" is enough. It does not involve the prevalence, because the model's probability p already accounts for the base rate if the model is calibrated. And it requires calibration to be valid, which is why 2.4.6 follows this section rather than preceding it.
When you cannot name the costs
Often nobody will commit to a cost ratio. Three defensible fallbacks, in order of preference:
| Rule | What it optimises | When it is appropriate |
|---|---|---|
| Fix an operating constraint | Best recall subject to precision ≥ 0.8, or to at most 500 alerts per day | Whenever capacity is the real limit — investigators, beds, review time. Usually the most honest option. |
| Maximise Fβ on validation data | A stated preference between the error types | When you can say which error is worse but not by how much. Choosing β is choosing a cost ratio implicitly. |
| Maximise Youden's J = TPR − FPR | The point furthest above the ROC diagonal | Balanced problems where both classes matter equally. Equivalent to C₄ₚ = C₄ₙ weighted by prevalence. |
All three must be evaluated on validation data, never on the test set. The threshold is a hyperparameter and 2.1's rules apply to it without exception.
Depth — class weights versus threshold shifting
There are two ways to make a model care more about the rare class: reweight the training loss so positive examples count more, or leave training alone and lower the decision threshold. They are not equivalent, and the difference matters.
Threshold shifting is applied after the fact, costs one line of code, leaves the model's probabilities intact so they can still be calibrated and reused, and can be re-tuned when costs change without retraining. Class weighting changes what the model learns, which can genuinely help when the rare class is so scarce that the optimiser barely notices it — but it distorts the output probabilities, so a weighted model's 0.5 no longer means "even odds" and calibration must be redone.
The practical default: train unweighted, then tune the threshold. Reach for class weights when the positive class is rare enough that the model's rare-class recall is near zero at every threshold, which means the ranking itself has failed and no cut-off can repair it.
The worked example
Worked 2.4.4 — pick the threshold from a cost ratio
expected cost, all ten thresholdsC₄ₙ = 4 C₄ₚ with the failing students as the class to catch, and find the threshold.The class we want to catch is failure, but the model outputs P(pass). Predicting "will fail" means p < t. A miss now means a failing student the model called a pass — which is a false positive in the file's convention.
Getting this direction wrong is the commonest error in the topic, so check it against intuition before continuing: a high threshold makes "pass" hard to earn, so more students get tutoring, so fewer failing students are missed. That is what a 4× cost on missing a failure demands.
Total cost is 4 × FP + 1 × FN with FP counted as "a true failure predicted pass".
| t | TP | FP | FN | TN | 4·FP | 1·FN | total cost | accuracy |
|---|---|---|---|---|---|---|---|---|
| 0.09 | 4 | 6 | 0 | 0 | 24 | 0 | 24 | 0.4000 |
| 0.20 | 4 | 4 | 0 | 2 | 16 | 0 | 16 | 0.6000 |
| 0.30 | 4 | 3 | 0 | 3 | 12 | 0 | 12 | 0.7000 |
| 0.40 | 3 | 3 | 1 | 3 | 12 | 1 | 13 | 0.6000 |
| 0.50 | 3 | 2 | 1 | 4 | 8 | 1 | 9 | 0.7000 |
| 0.60 | 3 | 1 | 1 | 5 | 4 | 1 | 5 | 0.8000 |
| 0.70 | 2 | 1 | 2 | 5 | 4 | 2 | 6 | 0.7000 |
| 0.80 | 2 | 0 | 2 | 6 | 0 | 2 | 2 | 0.8000 |
| 0.90 | 1 | 0 | 3 | 6 | 0 | 3 | 3 | 0.7000 |
| 0.95 | 0 | 0 | 4 | 6 | 0 | 4 | 4 | 0.6000 |
At that threshold no failing student is called a pass, and two passing students receive tutoring they did not need — two cheap errors instead of any expensive one.
The default
t = 0.50 costs 9 units, more than four times as much. Accuracy at 0.50 and at 0.80 differs by ten points in the opposite direction from the cost.Two features of that table are worth more than the answer. First, the empirical curve is not monotone: cost falls to 5 at t = 0.60, rises to 6 at 0.70, then drops to its minimum of 2 at 0.80. With ten rows the cost function is a jagged step function, so hunting for its lowest point on a small sample can land on a lucky notch. The formula does not have this problem, which is the argument for deriving t* rather than searching for it.
Second, accuracy peaks at 0.8000 at both t = 0.60 and t = 0.80 — two thresholds with costs of 5 and 2. Even when accuracy does discriminate, it discriminates on the wrong question.
Now reverse the costs. Suppose instead that a false alarm is four times worse than a miss, so cost = 1 × FP + 4 × FN and t* = 1/5 = 0.2. The table becomes 6 at t = 0.09, 4 at 0.20, 3 at 0.30, then 7, 6, 9, 8, and 12 at t = 0.90. The minimum has moved to the opposite end. Same model, same ten students, same probabilities — and the best threshold moved from 0.80 to 0.30 purely because the costs changed. There is no such thing as the best threshold for a model.
The visualization
Expected cost against threshold, for a cost ratio you set
interactive — move the ratioThe pitfalls
Where marks are lost
- Leaving the threshold at 0.5 without deciding to. It is a default in a library, not an analysis. Under unequal costs it is simply the wrong number.
- Getting the direction of
t*backwards. A more expensive miss means a lower threshold for the class you are trying to catch. Sanity-check against the umbrella. - Tuning the threshold on the test set. The threshold is a hyperparameter. Worked 2.4.4 used the test set for illustration only; in practice this sweep happens on validation data.
- Applying a cost-derived threshold to uncalibrated probabilities.
t* = 0.1is meaningless if the model's "0.1" actually corresponds to a 30% event rate. Calibrate first, per 2.4.6. - Assuming prevalence enters the formula. It does not, provided the model is calibrated on the deployment population. If prevalence shifts between training and deployment, recalibrate rather than adjusting
t*by hand. - Reporting one threshold's metrics as "the model's performance". Report the curve, then the chosen operating point and why it was chosen.
- Confusing class weighting with threshold shifting. See the depth box; they interact, and doing both without care double-counts the correction.
Practice
P2.4.4.1 (direct) — A bank finds that approving a loan that defaults costs ₹200,000 while declining a loan that would have repaid costs ₹25,000 in lost profit. Give the optimal threshold for the probability of default.
Decline whenever the estimated probability of default exceeds 11.1%. Note the cost ratio is 8:1 and the threshold is 1/9, not 1/8 — the formula is C₄ₚ/(C₄ₚ+C₄ₙ), not C₄ₚ/C₄ₙ. And note how far this is from 0.5: using the default would approve a great many loans with a 30% or 40% chance of default.
P2.4.4.2 (variation) — The same bank must also keep its approval rate above 70% for commercial reasons. Its model's score distribution means t = 0.1111 approves only 55%. What are the options?
The constraint and the cost-optimal threshold are incompatible, so something must give, and naming which is the actual decision.
Accept a higher expected cost. Raise the threshold until 70% are approved and compute the resulting expected cost. That number is the price of the commercial constraint, and it should be stated to whoever imposed it. Often it turns out to be larger than they expected.
Improve the model instead. The conflict exists because the model's ranking is not sharp enough to find 70% of applicants who are genuinely low-risk. A better model — more features, better calibration — moves the whole curve and can satisfy both. This is the only option that does not involve a trade.
Re-examine the costs. ₹200,000 per default may assume no recovery; if collateral recovers half, the ratio changes and t* rises to 25/125 = 0.20, which may approve close to 70% on its own. Cost estimates are usually the least examined input to the whole calculation.
Change the action space. The choice need not be binary. A middle band could receive a smaller loan, a higher rate, or a manual review, which converts an expensive error into a cheaper one. Two thresholds instead of one is frequently the right answer, and the cost formula extends to it directly.
P2.4.4.3 (interpretation) — A team reports: "we tuned the threshold to maximise F1 on the test set and achieved F1 = 0.81." Identify every problem.
Tuning on the test set. The threshold is a hyperparameter, so the test set has been used to make a decision and 0.81 is a validation figure. The honest number is whatever F1 that threshold achieves on data not involved in choosing it, and it will be lower. With ten thresholds tried the optimism is modest; with a fine sweep on a small set it can be several points.
Maximising F1 without justifying it. F1 weights precision and recall equally, which is a claim that the two error types cost the same. If that is true, say so and say why. If it is not, F1 was the wrong objective and the threshold is wrong regardless of how it was tuned. F1 also ignores true negatives entirely, which may or may not be acceptable here.
Reporting one number. F1 = 0.81 does not say what precision and recall were, so it does not say what the model does. It also does not say the prevalence, without which F1 cannot be compared to anything.
What to report instead. The threshold-free summary (AUC or average precision, with the prevalence), the chosen threshold and the reasoning behind it, the full confusion matrix at that threshold on a clean test set, and the metrics derived from it. That is four lines rather than one, and it is what a reader needs to judge the claim.
P2.4.4.4 (synthesis) — Combining this section with 2.4.3, explain why two models with identical AUC can require different thresholds and deliver different expected costs, and what that implies about model selection.
AUC is the area under the whole ROC curve, and many different curve shapes enclose the same area. One model might rise steeply at low FPR and then flatten; another might rise gently throughout. Their AUCs are equal and their curves cross.
The cost-optimal operating point is a single location on the curve, determined by the cost ratio. Formally, the optimal point is where the ROC curve's slope equals (C₄ₚ/C₄ₙ) × (n₋/n₊) — so the cost ratio and the prevalence together select a slope, and you move along the curve until you find it. Two curves of equal area have different slopes at every FPR, so they yield different operating points and different expected costs. The model with the steeper initial rise wins under a high false-positive cost; the other wins under a high miss cost.
The implication is that model selection cannot be separated from the deployment decision. Ranking candidate models by AUC and then choosing a threshold is two steps in the wrong order, because the first step discards the information the second needs. The correct procedure is to fix the cost ratio first, then compare models at their respective cost-optimal points on validation data, then confirm once on the test set. This is the same discipline 2.1 demanded of hyperparameters, applied to the metric itself — and it is why 2.3.7 insisted that the protocol matters more than the model.
Regression Metrics
Unit 2A predicted marks as well as labels. Judging a number needs a different toolkit, and the choice of metric encodes what kind of error you are willing to accept.
The question
A classifier is right or wrong. A regression is wrong by an amount, and there are several defensible ways to add up amounts. Unit 1.3 introduced them for one feature; here they are applied to the two-feature model of 2.2 and to the question of which to report.
The formal treatment
The gap between RMSE and MAE is itself informative: it measures how unevenly your errors are distributed. Equal errors give RMSE = MAE; a few large errors among many small ones pushes RMSE well above MAE. Reporting both, and noting the gap, says more than either alone.
R² deserves one clarification that catches people out. It compares your model against the constant predictor that always guesses the mean. So R² = 0 means "no better than the mean" and R² < 0 is perfectly possible on a test set — it means the model is worse than guessing the mean, which happens more often than you would expect.
The worked example
Worked 2.4.5 — score the marks model six ways
the 2.2 plane, evaluatedmarks = 3 + x₁ + 2x₂ to the eight students. Report MSE, RMSE, MAE, MAPE, R² and adjusted R², and compare against the mean-predicting baseline.| Student | marks y | ŷ | r | r² | |r| | |r/y| | (y−12)² |
|---|---|---|---|---|---|---|---|
| A | 9 | 10 | +1 | 1 | 1 | 0.1111 | 9 |
| B | 8 | 7 | −1 | 1 | 1 | 0.1250 | 16 |
| C | 11 | 11 | 0 | 0 | 0 | 0.0000 | 1 |
| D | 10 | 10 | 0 | 0 | 0 | 0.0000 | 4 |
| E | 14 | 14 | 0 | 0 | 0 | 0.0000 | 4 |
| F | 12 | 13 | +1 | 1 | 1 | 0.0833 | 0 |
| G | 17 | 16 | −1 | 1 | 1 | 0.0588 | 25 |
| H | 15 | 15 | 0 | 0 | 0 | 0.0000 | 9 |
| Σ | 96 | 96 | 0 | 4 | 4 | 0.3782 | 68 |
RMSE 0.7071 exceeds MAE 0.5000 because four students are missed by a full mark and four by nothing at all — unevenly distributed errors.
MAPE of 4.7% is the figure to quote to a non-technical audience; RMSE in marks is the one to quote to anyone who will use the model.
The RMSE-to-MAE ratio here is 0.7071/0.5000 = 1.4142, which is exactly √2. That is the signature of errors being either 0 or 1 in equal numbers, and it is a reminder that these two metrics are answering different questions: MAE says "the average miss is half a mark", RMSE says "the typical miss, weighting big misses more, is 0.71 marks". Neither is more correct.
The pitfalls
Where marks are lost
- Reporting MSE as if it were in the units of the target. It is in squared units. Only RMSE and MAE are comparable to
y. - Using MAPE when the target can be near zero. It explodes, and it is asymmetric — over-prediction is penalised more heavily than under-prediction of the same absolute size. Use MAE or a symmetric variant.
- Treating
R²as bounded below by zero. On a test set it can be negative, which is a meaningful and alarming result. - Comparing
R²across datasets. It depends on the variance of the target, so a hard-to-predict target capsR²regardless of model quality. - Adding features and celebrating a higher
R². It always rises. Use adjustedR²or validation error. - Choosing RMSE by habit when large errors are not disproportionately bad. The metric should match the cost. If a 10-unit error is genuinely ten times as bad as a 1-unit error, MAE is right and RMSE overstates it.
- Never plotting the residuals. A single summary hides structure. Residuals against predicted value will reveal curvature, heteroscedasticity and outliers that no metric reports.
Practice
P2.4.5.1 (direct) — A model predicts 12, 18, 25, 31 where the truth is 10, 20, 24, 34. The target's mean is 22. Compute MSE, RMSE, MAE, MAPE and R².
RMSE 2.1213 against MAE 2.0000 is a narrow gap, so the errors are fairly evenly sized — consistent with residuals of 1, 2, 2 and 3. Note that MAPE's 10.7% is driven mostly by the first point, where an error of 2 on a value of 10 is 20%; the same error on the value of 34 would be under 6%. That asymmetry across the range is MAPE's characteristic weakness.
P2.4.5.2 (interpretation) — A house-price model reports RMSE ₹180,000, MAE ₹62,000 and R² = 0.88. What does the RMSE-to-MAE ratio tell you, and what would you do next?
The ratio is 180/62 = 2.90, which is very large. Since RMSE equals MAE only when all errors are the same size and grows relative to MAE as errors become uneven, a ratio near 3 says the error distribution is dominated by a small number of very large misses while most predictions are good. An R² of 0.88 is consistent with this: the bulk of the variance is captured and a handful of houses are badly wrong.
What to do. Find them. Sort by absolute residual and look at the worst twenty. The likely candidates are luxury properties outside the training range, where a linear model must extrapolate; data errors such as a misplaced decimal in the floor area; or a genuinely distinct segment — commercial conversions, disputed titles — that the features do not describe.
Then decide what the metric should be. If a single ₹2,000,000 error is catastrophic for the business, RMSE is the right objective and those cases need fixing. If the model is used for typical valuations and the rare mansion is handled manually, MAE or a Huber loss from 1.3 is the better objective, and the ₹62,000 MAE is the honest headline figure. Reporting only RMSE would make a good model look poor; reporting only MAE would hide a real risk.
Calibration and Honest Reporting
Whether a probability of 0.8 actually means 80%, and how to report a cross-validated number without overclaiming.
The question
Section 2.4.4 derived a threshold from costs and then admitted the derivation only works if the probabilities are correct. Section 2.4.3 noted that AUC cannot detect whether they are. So: how do you check, and what do you do about it?
And a second question, less glamorous and more often botched. Cross-validation produced five numbers. What single sentence are you entitled to write?
Calibration
A model is calibrated if, among all cases it assigns probability p, a fraction p are actually positive. Take every case scored near 0.7 and about 70% of them should be positives. That is a testable claim, and it is separate from both accuracy and ranking quality.
| bin | n | mean predicted | observed rate | gap |
|---|---|---|---|---|
| [0.00, 0.25) | 3 | 0.1700 | 0.0000 | −0.1700 |
| [0.25, 0.50) | 2 | 0.4100 | 0.5000 | +0.0900 |
| [0.50, 0.75) | 2 | 0.6000 | 0.5000 | −0.1000 |
| [0.75, 1.00] | 3 | 0.8500 | 0.6667 | −0.1833 |
| ECE (weighted mean absolute gap) | 0.1440 | |||
The model is overconfident at the top: among the three students it scored 0.85 on average, only two of three passed, an observed rate of 0.6667. Its Brier score is 0.1786 against a prevalence-predicting baseline of 0.2400, so it is genuinely better than nothing and genuinely miscalibrated. With three cases per bin these gaps are not statistically meaningful, and that limitation is itself the point: calibration cannot be assessed on ten rows, and a reliability diagram from a small test set is a picture of noise.
Two standard repairs, both fitted on held-out data and never on the training set: Platt scaling fits a one-dimensional logistic regression mapping the model's score to a probability, which suits SVMs and works with little data; isotonic regression fits any monotone mapping, which is more flexible and needs more data to avoid overfitting. Both preserve the ranking exactly, so AUC is unchanged — they fix magnitudes, not order.
Depth — which models need calibrating, and why
Logistic regression trained with log loss is calibrated close to automatically, because log loss is a proper scoring rule: it is minimised, uniquely, by reporting the true conditional probability. Training on the right loss gets calibration for free.
Everything else generally needs help. An SVM outputs a signed distance with no probabilistic meaning at all. Naive Bayes is overconfident because correlated features double-count evidence (2.3.6). Random forests are systematically under-confident at the extremes, because averaging many trees pulls predictions toward the middle — a forest rarely outputs 0.99 even when it should. Boosted trees are typically over-confident. Deep networks trained with modern regularization are usually over-confident, sometimes severely.
The practical rule: if the output will be thresholded and nothing else, calibration is optional because the threshold can absorb any monotone distortion. If the output will be multiplied by a cost, compared across models, aggregated, or shown to a human as a probability, calibration is mandatory.
Reporting a cross-validated result
Worked 2.4.6 — five fold scores, one honest sentence
and a paired comparisonSo the defensible sentence is "cross-validated accuracy 0.830, standard deviation 0.065 across five folds" — and if an interval is quoted it spans sixteen percentage points. Writing "83% accurate" full stop implies a precision the experiment does not have.
The rival's mean is 0.8120, so the difference in means is 0.018 — far inside either model's confidence interval. Comparing the intervals would suggest no difference. That comparison is the wrong one, because the folds are shared.
Your model wins every single fold. Because the same folds were used, the fold-to-fold difficulty — which is what produced the 0.0652 spread — cancels out of the comparison entirely, and what remains is a consistent small advantage.
Unpaired, the two look indistinguishable. Paired, the advantage is clear but small.
Both statements are true and they answer different questions: how good is it, versus is it better than that one.
Two cautions before quoting the t. Cross-validation folds are not independent — their training sets overlap heavily — so the paired t-test is anti-conservative and the true significance is weaker than 4.81 suggests. And an advantage of 1.8 percentage points may be real and still not worth having if the winning model is ten times slower or cannot be explained. Statistical significance is not practical significance, and reporting the effect size alongside is what lets a reader tell the difference.
The visualization
Reliability, and what a distortion does to it
interactive — bend the probabilitiesThe distortion control applies a monotone transformation to every probability, sharpening or softening the model's confidence without changing the ranking of a single student. Watch AUC: it stays at 0.833 for every setting, because it cannot see magnitudes. ECE, Brier and log loss all move, because they can. That is the clearest demonstration available that ranking quality and calibration are independent properties, and that a model needs both checked.
The pitfalls
Where marks are lost
- Assuming a high AUC means trustworthy probabilities. AUC is invariant to any monotone rescaling. It says nothing about calibration.
- Calibrating on the training set. The model already fits it, so the reliability diagram will look perfect and the calibration will be worthless. Use a held-out calibration split.
- Reading a reliability diagram from too few points. The table above has three cases per bin. It is illustrative and not evidence.
- Reporting a CV mean without its spread. The spread is half the result, and on small data it is often larger than the difference you are claiming.
- Comparing two models by their separate confidence intervals. Use the paired differences on shared folds; it is far more sensitive, as Worked 2.4.6 shows.
- Quoting a paired
t-test as if the folds were independent. They are not, and the test is anti-conservative. Treat it as a suggestion, not a proof. - Reporting accuracy to four decimal places on a small test set. With ten rows, accuracy can only take eleven values. Precision in the report should match precision in the experiment.
Practice
P2.4.6.1 (direct) — A model assigns probability 0.8 to 50 cases, of which 30 are positive; and 0.3 to 100 cases, of which 40 are positive. Compute the ECE over these two bins and say which direction each is wrong.
The 0.8 bin is overconfident — it claimed 80% and delivered 60%. The 0.3 bin is underconfident — it claimed 30% and delivered 40%. Both errors push predictions toward the extremes, which is the classic signature of a model trained without regularization, or of Naive Bayes double-counting correlated evidence. A monotone recalibration that pulls both bins toward the centre would fix both at once, and it would leave the ranking, and therefore the AUC, exactly as it is.
P2.4.6.2 (interpretation) — A colleague reports "the new model improved accuracy from 0.912 to 0.918, a statistically significant gain (p = 0.04)." What do you ask?
How large is the test set? A 0.6-point gain means about 6 extra correct predictions per thousand. On a 500-row test set it is three cases and could be a single fold's luck. The p-value is only as meaningful as the experiment behind it.
Was the comparison paired, and were the folds shared? A paired test on shared folds is the right instrument, but its p-values are anti-conservative because CV training sets overlap, so p = 0.04 from five folds is weaker evidence than p = 0.04 from independent samples.
How many models were compared to find this one? If twenty variants were tried, one of them clearing p = 0.05 is expected by chance. This is 2.1's selection problem applied to significance tests.
What is the baseline and the prevalence? At 0.912 accuracy, a majority-class baseline of 0.90 would mean both models are barely above trivial, and the entire comparison concerns a sliver of the data. Ask for the confusion matrices.
And what does it cost? Six correct predictions per thousand may be worth a great deal or nothing at all, depending on what the errors cost. Significance is a statement about noise, not about value.
Semi-supervised and Self-supervised Learning
Labels are expensive and raw data is nearly free. What can you do with eight labelled students and four hundred unlabelled ones?
The question
Everything in Unit 2A assumed a labelled training set. In practice labelling is the bottleneck: a radiologist must read each scan, a lawyer must classify each clause, a marker must grade each script. Unlabelled examples, meanwhile, accumulate for free.
So the question is whether unlabelled data carries usable information about a labelling task. It sounds as though it should not — the labels are precisely what is missing. It sometimes does, and understanding exactly when is the substance of this section.
The intuition
You are handed eight photographs labelled cat or dog, and four hundred unlabelled animal photographs. The unlabelled pile tells you nothing directly about which is which. But it tells you a great deal about the shape of the data: that photographs cluster into groups, where the dense regions are, where the empty gaps lie.
If the boundary between cats and dogs runs through one of those empty gaps — which is plausible, since cats and dogs look different — then knowing where the gaps are locates the boundary far more precisely than eight labelled points could. The unlabelled data has not supplied labels; it has supplied geometry, and geometry constrains where a sensible boundary can sit.
When that hope fails — when the classes are thoroughly mixed, or the clusters correspond to something other than the label — unlabelled data does not merely fail to help. It actively hurts, by confidently pulling the boundary into a gap that means nothing.
The formal treatment
The three assumptions
Every semi-supervised method rests on at least one of these, and each is a substantive empirical claim about the data rather than a technicality:
| Assumption | Statement | Fails when |
|---|---|---|
| Smoothness | Points close together are likely to share a label | The label depends on a feature the distance metric ignores — the scaling problem of 2.3.2, again |
| Cluster | Points in the same dense cluster share a label; the boundary lies in a low-density region | Clusters reflect something else entirely — photographs cluster by lighting, not by species |
| Manifold | The data lies on a low-dimensional surface inside the high-dimensional space | The data genuinely fills its space, which is rare for natural data and common for tabular data |
Transductive and inductive
The four standard methods
Co-training splits the features into two views that are each sufficient for the task — a web page's text and its inbound link text, say — and trains one model per view. Each model's confident predictions become labelled data for the other. Because the two views make different mistakes, one model can correct the other, which self-training with a single model cannot do.
Label propagation builds a graph with one node per point and edges weighted by similarity, then lets labels diffuse from the labelled nodes through the graph until the assignment stabilises. It is inherently transductive and it implements the smoothness assumption directly.
Consistency regularization is the idea behind modern methods. Add a term to the loss requiring the model to give an unlabelled point the same prediction under small perturbations — a crop, a noise injection, a dropout mask:
Self-supervised learning
A different and now dominant idea: invent a supervised task whose labels come free from the data's own structure, learn a representation by solving it, then fine-tune on the small labelled set.
| Task | Free label | What the model must learn |
|---|---|---|
| Masked token prediction | The hidden word itself | Syntax, semantics, factual association — this is how language models are trained |
| Next-token prediction | The following word | Everything the above requires, plus discourse structure |
| Rotation prediction | The rotation you applied | Object orientation, and therefore object identity |
| Colourisation | The original colours | That grass is green and skin is not |
| Contrastive (SimCLR, MoCo) | Which two crops came from the same image | Representations invariant to nuisance variation but sensitive to content |
The contrastive family deserves emphasis because it is the conceptual bridge to Unit 5. The objective is to pull together the representations of two augmented views of the same image and push apart views of different images. No human label is involved anywhere, and the resulting representation, fine-tuned on 1% of ImageNet's labels, rivals fully supervised training. That result is the reason "pre-train then fine-tune" is now the default recipe across the field.
Depth — when unlabelled data makes things worse
Self-training has a failure mode that is worth being able to describe precisely: confirmation bias. The model's confident errors become training labels, which reinforce the error, which raises confidence, which produces more of the same errors. The loop is self-sealing and the model's own confidence gives no warning, because confidence is exactly what is being corrupted.
Concretely, suppose the initial model is systematically wrong about one region of feature space. Every unlabelled point in that region is pseudo-labelled wrongly and with high confidence. After retraining, that region is now supported by hundreds of training points and the model will never revisit it. A single labelled example would have prevented it.
Three defences, all of them cheap. Keep the true labels weighted much more heavily than the pseudo-labels. Raise the confidence threshold so that only near-certain predictions are committed, accepting slower progress. And always evaluate on a held-out labelled set, never on the pseudo-labels themselves — accuracy measured against pseudo-labels rises monotonically to 1.0 while true accuracy falls, which is the single most misleading curve in this area. If unlabelled data is not measurably helping on real labels, stop using it.
The worked example
Worked 2.5 — one round of self-training on the spine's model
who is confident enough?p = σ(0.5s − 3) where s = x₁ + x₂. Forty new students arrive with features but no marks. Using a confidence threshold of 0.9, which of them can be pseudo-labelled?So only students with total effort at or above 10.3944, or at or below 1.6056, can be pseudo-labelled. Since x₁ and x₂ are integers, that means s ≥ 11 or s ≤ 1.
| s | 2 | 4 | 6 | 8 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|
| p | 0.1192 | 0.2689 | 0.5000 | 0.7311 | 0.8808 | 0.9241 | 0.9526 |
| usable? | no | no | no | no | no | yes | yes |
The original eight students span s = 3 to s = 9, so none of them would clear the bar. Only unusually extreme new students would.
The eight original students, spanning s = 3 to 9, all sit in the uncertain band.
With 8 labelled and 40 unlabelled, the labelled share is 8/48 = 16.7%, and this model's confidence is too flat for pseudo-labelling to add much.
The reason is the flatness of the sigmoid. The fitted weights are small — 0.5 per unit of s — so probabilities change slowly and confidence above 0.9 requires being far from the boundary. Recall from 2A section 2.3.1 that this small weight is what makes the model well calibrated on eight rows. A model trained to convergence on separable data would have driven ‖w‖ large, reported p > 0.99 for most students, and pseudo-labelled everything with total confidence — while being no more accurate.
That is the trap in a sentence: self-training's confidence threshold is only meaningful if the model is calibrated, so the models most eager to pseudo-label are exactly the ones least entitled to. Section 2.4.6 is therefore a prerequisite for this section, not an appendix to it. Before running self-training, check the reliability diagram; if the model is overconfident, its confidence threshold is not filtering anything.
The visualization
Self-training, round by round — including when it goes wrong
interactive — step through the loopForty unlabelled students are drawn as small grey dots. The truth used to score them contains a pocket of high-effort students who nonetheless failed — the kind of structure a single sigmoid in s cannot represent at all, since it would need the probability to go down and then up again.
Two things to watch, and both are the point of the section. True accuracy never rises above its round-0 value of 0.850, at any confidence bar. Self-training commits up to forty pseudo-labels and buys nothing, because the unlabelled data cannot supply a shape that is missing from the hypothesis space — no quantity of extra points makes a monotone curve non-monotone. And the wrong-pseudo-label count climbs as the bar falls, from 3 at a bar of 0.99 to 6 at 0.90 and below. Those six are exactly the pocket, committed as truth and then defended by every subsequent refit.
That is the honest shape of the failure. The model does not announce it: its confidence rises while its accuracy sits still, and if you had measured against the pseudo-labels rather than against held-out truth you would have seen a number climbing toward 1.0 the whole time.
The pitfalls
Where marks are lost
- Assuming unlabelled data can only help. It can hurt, and self-training is the method most prone to it. The assumptions in the table are empirical claims that need checking.
- Evaluating against pseudo-labels. That number rises to 1.0 by construction and means nothing. Always hold out real labels.
- Confusing semi-supervised with unsupervised. Semi-supervised uses both labelled and unlabelled data. Unsupervised (Unit 3) uses no labels at all and answers a different question.
- Confusing transductive with inductive. Label propagation labels the points you gave it and produces no function you can apply to a new point.
- Using an uncalibrated model's confidence as a threshold. Worked 2.5's closing point. Check calibration first.
- Weighting pseudo-labels equally with real labels. Forty pseudo-labels will then drown eight real ones, and the real ones were the only reliable information you had.
- Expecting self-supervised pre-training to help on small tabular data. Its wins are in vision, language and audio, where the manifold assumption holds strongly. On a few thousand rows of tabular data, gradient boosting from 2.3.5 remains the thing to beat.
Practice
P2.5.1 (direct) — Using p = σ(0.5s − 3), find the threshold on s for a confidence requirement of 0.95 instead of 0.9.
Raising the bar from 0.9 to 0.95 moved the requirement from s ≥ 11 to s ≥ 12, and made the negative side essentially unreachable since s = 0 means a student who did nothing at all. Each additional nine of confidence costs about ln(10)/0.5 = 4.6 units of s here, so with weights this small a high confidence threshold rejects almost everything. The relationship between weight magnitude and how much data clears a confidence bar is worth noticing: it is why overconfident models pseudo-label freely.
P2.5.2 (variation) — You have 8 labelled and 40 unlabelled students. Self-training accepts 12 pseudo-labels in round 1, of which 3 are wrong. Should you weight pseudo-labels at 1.0, and what is the effective composition of the training set either way?
No, weight them down. At full weight, 15% of the training signal is actively false and the real labels are outvoted three to two. The three wrong pseudo-labels are also not randomly distributed — they will be clustered in whatever region the initial model misunderstands, so their local influence is far greater than 15%.
A weight of 0.25 keeps the real labels dominant while still letting the unlabelled data shape the boundary. The number itself should be chosen by validation on held-out real labels, like any hyperparameter, and if no weight produces an improvement then this dataset does not satisfy the assumptions and self-training should be abandoned. A 3-in-12 error rate on the most confident predictions is already a warning sign that the model's confidence is not calibrated.
P2.5.3 (interpretation) — A team runs self-training for 10 rounds. Accuracy measured on the pseudo-labelled pool rises from 0.82 to 0.99. They declare success. What has actually happened?
Nothing has been measured. The pseudo-labels were produced by the model, so measuring the model against them measures self-consistency, not correctness. After retraining on its own outputs the model necessarily agrees with them, and that agreement approaches 1.0 whether or not a single label is right. The curve they are celebrating is a tautology.
What has probably happened underneath is the confirmation-bias loop. Round 1's confident errors entered the training set, subsequent rounds gained support for them, and by round 10 the model is emphatically wrong in whatever regions it started out wrong. True accuracy may well have fallen from its round-0 value.
What to do. Set aside a labelled test set before starting and evaluate on it after every round; that curve is the only one that means anything, and self-training should be stopped at its peak rather than at convergence. Also compare against the round-0 model trained on labelled data alone, because if self-training cannot beat that baseline it has no justification. And inspect the pseudo-labels by hand — a sample of thirty is enough to reveal a systematically mislabelled region.
P2.5.4 (synthesis) — Using 2.3.2's scaling result and 2.4.6's calibration material, explain why semi-supervised learning is more fragile than supervised learning, and name the one check that catches most of its failures.
It depends on the geometry of the feature space, which supervised learning does not. The cluster and smoothness assumptions are both statements about distance, and 2.3.2 established that distance in raw feature units is essentially arbitrary — recording practice in minutes rather than hours reordered every neighbour and flipped k-NN's prediction. A label-propagation graph or a consistency-regularization neighbourhood built on unscaled features encodes the same arbitrary geometry, and it will propagate labels along whichever axis happens to have the largest numbers. Supervised learning with a linear model is immune to this, because a coefficient simply absorbs the rescaling.
It also depends on confidence being meaningful, which 2.4.6 showed is not automatic. Self-training's threshold assumes that "0.95" means a 95% chance of being right. For an uncalibrated model — a boosted tree, a Naive Bayes classifier, a network trained to convergence — it may mean 70%, in which case a threshold of 0.95 admits errors at three times the intended rate and the safeguard is doing nothing.
The one check. Hold out labelled data and measure on it after every round. It catches confirmation bias, it catches a violated cluster assumption, it catches miscalibrated confidence, and it catches the case where the whole approach was inapplicable — because all four of those failures show up as true accuracy that fails to improve or actively declines. This is 2.1's discipline with no modification at all: the only number you can trust is the one measured on data that did not influence the model.
Responsible AI
Fairness, interpretability and privacy — including one result that says you cannot have everything you want, and a four-line proof of it.
The question
Every model in this unit was judged by a number. But a model that decides who gets a loan, a job interview, or extra tutoring is doing something to people, and "it scored 0.83" does not tell you whether it is doing it acceptably.
Three questions that no accuracy figure answers. Does the model work equally well for everyone it is applied to? Can anyone say why it decided what it decided? And what has it learned about individuals that it should not repeat?
The intuition
Suppose a tutoring recommendation system is applied to two cohorts — students from schools with strong maths preparation and students from schools without. The model was trained on historical data in which the second group passed less often, for reasons that have nothing to do with their capability.
The model learns that pattern, because learning patterns is what it does. Applied at a single threshold, it recommends tutoring to fewer of the second group, and among those it does flag, a smaller proportion actually needed it. Nobody wrote a discriminatory rule. The rule emerged from the data, which recorded the world as it was.
You could try to fix it by flagging the same proportion of each group. That closes one gap and, as we are about to prove, opens another. There is no setting that closes all of them at once, and pretending otherwise is the central confusion in this area.
The formal treatment — fairness
Let A be a group attribute, Y the true outcome, Ŷ the prediction, R the model's score.
| Definition | Requires | In words |
|---|---|---|
| Demographic parity (statistical parity) | P(Ŷ=1 | A=a) equal for all a | Flag the same proportion of each group. Ignores the true outcome entirely. |
| Equal opportunity | P(Ŷ=1 | Y=1, A=a) equal | Equal recall. Among those who genuinely qualify, the same share are found in each group. |
| Equalised odds | Equal TPR and equal FPR | Stronger. Both error rates match across groups. |
| Predictive parity | P(Y=1 | Ŷ=1, A=a) equal | Equal precision. A flag means the same thing whichever group you are in. |
| Calibration by group | P(Y=1 | R=r, A=a) equal | A score of 0.7 means 70% for everyone. The strongest version of predictive parity. |
Two further notions cut across these. Fairness through unawareness means simply not using the protected attribute as a feature, and it is close to worthless: correlated features — postcode, school, name — reconstruct it, so the model discriminates just as effectively while being harder to audit. And individual fairness demands that similar individuals receive similar predictions, which is appealing and founders on defining "similar", since that definition is where the whole disagreement lives.
The worked example
Worked 2.6a — the same model, audited by group
four metrics, two groups| Group | TP | FP | FN | TN | n | actual positives |
|---|---|---|---|---|---|---|
| P | 54 | 18 | 6 | 42 | 120 | 60 |
| U | 12 | 16 | 8 | 44 | 80 | 20 |
Note the base rates before computing anything: group P has 60 positives in 120, a prevalence of 0.5000; group U has 20 in 80, a prevalence of 0.2500. That difference is the source of everything that follows.
| Metric | Group P | Group U | difference | ratio U/P | fairness definition it tests |
|---|---|---|---|---|---|
| base rate | 0.5000 | 0.2500 | +0.2500 | 0.5000 | — a property of the world |
| selection rate | 0.6000 | 0.3500 | +0.2500 | 0.5833 | demographic parity — violated |
| TPR / recall | 0.9000 | 0.6000 | +0.3000 | 0.6667 | equal opportunity — violated |
| FPR | 0.3000 | 0.2667 | +0.0333 | 0.8889 | equalised odds — nearly met on this half |
| PPV / precision | 0.7500 | 0.4286 | +0.3214 | 0.5714 | predictive parity — violated |
| accuracy | 0.8000 | 0.7000 | +0.1000 | 0.8750 | — and this is the one usually reported |
The recall gap of 0.3000 is the most concrete harm: 40% of group U's students who needed tutoring did not get it, against 10% of group P's.
The 80% rule sometimes used in employment law asks whether the selection ratio exceeds 0.80; here it is 0.5833, which would fail that test.
Notice which single number a normal evaluation would have produced. Pooling both groups gives 66 TP, 34 FP, 14 FN, 86 TN out of 200, an accuracy of 0.7600 — a perfectly respectable figure that reports none of the above. A fairness audit is not a different kind of metric; it is the same metrics, disaggregated. That is the cheapest and most reliable step available, and the reason it is skipped is almost always that nobody thought to group the rows.
The impossibility result
Worked 2.6b — try to fix it, and watch a different gap open
the proof, in four linesGroup P selects 72 of 120, so group U must select 0.6000 × 80 = 48 instead of 28. Lower U's threshold until 20 more students are flagged. Take the best possible case, where those 20 include all 8 remaining true positives:
| Gap (P − U) | before | after | verdict |
|---|---|---|---|
| selection rate | +0.2500 | 0.0000 | closed — this was the goal |
| TPR | +0.3000 | −0.1000 | closed and overshot |
| FPR | +0.0333 | −0.1667 | was nearly equal, now reversed and five times larger |
| PPV | +0.3214 | +0.3333 | wider than before |
And this was the optimistic case. If the 20 extra selections had included fewer of the true positives, U's TPR would have risen less and its PPV fallen further.
The obstruction is algebraic, not a limitation of this particular model. Write p for a group's prevalence and expand precision by Bayes' theorem:
This is the Kleinberg–Mullainathan–Raghavan and Chouldechova result, and line 3 is the whole proof.
The only escapes are a perfect classifier, or equal base rates — neither of which is available.
What follows is not despair but a requirement to choose, and to say so. Equal opportunity is the usual choice when a false negative denies someone a benefit they qualified for — tutoring, a loan, a screening referral — because equal recall means the qualified are found at the same rate. Predictive parity is preferred when the score is handed to a human decision-maker, because it makes a flag mean the same thing regardless of group. Demographic parity is appropriate when the recorded outcome Y is itself untrustworthy: if historical pass rates reflect unequal opportunity rather than unequal capability, then matching them faithfully is reproducing an injustice, and equalising selection rates is the more defensible target.
That last case deserves emphasis, because it is the one the algebra cannot see. The impossibility theorem treats Y as ground truth. When Y is a measurement of a biased process — arrest records, past hiring decisions, historical marks from unequal schools — optimising against it is not neutral, and no fairness metric computed from Y will reveal the problem. That is a question about the data, and it has to be answered before the metrics are worth computing.
The visualization
Two groups, two thresholds, and the gap that will not close
interactive — try to make it fairTwo independent thresholds give you two degrees of freedom and there are three gaps to close, so the arithmetic is against you before you start. Try it: equalise selection rates and the precision gap widens. Equalise recall and the selection gap remains. The counter will reach 2 on a lucky setting and never 3, and the reason is line 3 of the proof rather than any shortcoming of the controls.
Interpretability
Section 2.3.7 treated interpretability as a model-selection criterion. Here it is a requirement, and there are two distinct things people mean by it.
| Method | What it gives | Cost and caveat |
|---|---|---|
| Permutation importance | Global: the drop in validation score when one feature is shuffled | Model-agnostic and honest. Correlated features share credit arbitrarily, per 2.3.4's depth box. |
| Partial dependence | Global: average prediction as one feature varies | Averages away interactions, so it can look flat where the effect is real but conditional. |
| SHAP | Local and global: each feature's additive contribution to one prediction | Grounded in cooperative game theory, with the appealing property that the contributions sum exactly to the prediction. Expensive; exact only for trees. |
| LIME | Local: a simple model fitted in the neighbourhood of one point | Cheap and unstable — two runs can disagree, because the neighbourhood is sampled. |
| Counterfactual | Local: the smallest change that would flip the decision | The most actionable form — "submit two more assignments" — but only if the named change is something the person can actually do. |
A caution that is easy to state and often ignored: a post-hoc explanation is a model of a model. SHAP values for a boosted forest are not the forest's reasoning; they are the output of a second procedure that approximates it. If the explanation must be relied upon — legally, medically — then an inherently interpretable model is the safer choice, and 2.3.7's cheat grid says which those are. The gap in accuracy between a well-regularized logistic regression and a tuned boosting ensemble is frequently smaller than people assume, and on a problem where the reasoning must be defensible it is often a price worth paying.
Privacy
A trained model is a function of its training data, and functions leak.
Anonymisation by removing names is not sufficient and has failed repeatedly in practice, because combinations of ordinary attributes — postcode, birth date, sex — identify people uniquely. Differential privacy is the rigorous alternative: it adds calibrated noise so that the output distribution is nearly unchanged whether or not any single individual is present, with a parameter ε bounding how much any one person can influence the result. It gives a real guarantee and it costs accuracy, and the trade is set by ε. Federated learning attacks the problem differently, training across devices that never transmit raw data, only model updates — though updates themselves leak, so it is usually combined with differential privacy rather than relied on alone.
Depth — documentation as a deliverable
Two artefacts have become standard practice and both are worth knowing by name. A model card documents a trained model: its intended use, the populations it was evaluated on, disaggregated performance across groups exactly as in Worked 2.6a, known limitations, and the uses it is not suitable for. A datasheet documents a dataset: how it was collected, who is represented and who is not, what was labelled and by whom, and what it should not be used for.
The reason these matter is that most deployment failures are not modelling errors. They are a model applied to a population it was never evaluated on — and that mismatch is invisible unless someone wrote down which population it was evaluated on. A model card is the cheapest available intervention in this whole section, and unlike differential privacy it costs no accuracy at all.
The pitfalls
Where marks, and rather more than marks, are lost
- Claiming a model is fair because it does not use the protected attribute. Fairness through unawareness. Correlated features reconstruct the attribute and remove your ability to audit for it.
- Believing all fairness criteria can be satisfied at once. Worked 2.6b is the proof that they cannot. Choose, justify, and document the choice.
- Reporting only aggregate performance. Worked 2.6a's pooled accuracy of 0.7600 concealed a recall gap of 0.30. Always disaggregate.
- Treating the recorded label as ground truth. If
Yis the output of a biased process, every metric computed from it inherits the bias, and the impossibility theorem will not warn you. - Presenting a SHAP value as the model's reason. It is an approximation produced by a second algorithm. Say so.
- Assuming anonymisation protects individuals. Quasi-identifiers re-identify. Differential privacy is the option with an actual guarantee.
- Auditing once, at launch. Populations shift, and a model fair at deployment can drift. This is monitoring, not a checklist item.
- Treating this section as the ethics appendix. Every choice in 2.4 — which metric, which threshold, whose costs went into
C₄ₚandC₄ₙ— was already a decision about who bears the errors. The technical and the ethical parts of this unit are the same material.
Practice
P2.6.1 (direct) — Group X: TP 30, FP 20, FN 10, TN 40. Group Y: TP 15, FP 5, FN 15, TN 65. Compute selection rate, TPR and PPV for each and identify which fairness criteria are violated.
Demographic parity: violated badly — X is flagged at two and a half times Y's rate. Equal opportunity: violated — X's recall is 0.75 against Y's 0.50, so qualified members of Y are half again as likely to be missed. Equalised odds: violated on both components. Predictive parity: violated, but in the opposite direction — a flag for group Y is more reliable (0.75) than a flag for group X (0.60).
That reversal is the diagnostic worth noticing. The model is conservative with group Y: it flags rarely, so the flags it does raise are trustworthy, and it misses many qualified people. Closing the recall gap by lowering Y's threshold would flag more of group Y and reduce their precision below X's — the same trade as Worked 2.6b. Whether that is an improvement depends entirely on whether being missed or being wrongly flagged is the greater harm here.
P2.6.2 (variation) — Verify the identity PPV = p·TPR / (p·TPR + (1−p)·FPR) for group Y above, then use it to find the FPR group Y would need for its PPV to match group X's 0.6000, holding TPR at 0.5000.
So matching X's precision requires doubling group Y's false positive rate, from 0.0714 to 0.1429 — making the model deliberately worse on group Y in order to make the two groups' precisions agree. That is a real option and it is what predictive parity demands here, and it illustrates why fairness constraints are not free: every one of them is enforced by degrading some metric somewhere.
The alternative reading is that precision parity is the wrong target on this problem. If the harm is being missed, equal opportunity is what matters, and the fix is to raise group Y's recall by lowering its threshold — which also raises its FPR, and lowers its precision below X's. Every route out of this involves choosing which group absorbs which error.
P2.6.3 (interpretation) — A hiring model is audited and found to have equal accuracy across all groups. The vendor presents this as evidence of fairness. Respond.
Equal accuracy is nearly uninformative here, and it is not one of the five criteria for a reason. Accuracy pools true positives with true negatives, so two groups can have identical accuracy with completely different error profiles. Worked 2.6a's numbers make the point: had group U's accuracy happened to equal group P's, the recall gap of 0.30 would still have been there. Ask for the disaggregated confusion matrices, which is four numbers per group.
Accuracy also flatters whichever group has the more extreme base rate, per 2.4.2's depth box. A group with few qualified applicants gets high accuracy from rejecting nearly everyone, so equal accuracy across groups with different base rates may indicate that the model is doing something quite different in each.
What to request. Selection rate, TPR, FPR and PPV per group, with counts so the intervals can be judged. The intended fairness criterion, stated in advance, with the reasoning. Whether the label Y is "was hired" or "was successful in the role" — because the first records past hiring decisions and optimising against it reproduces them, which is the untrustworthy-label case. And a model card documenting which populations the evaluation covered, since a group that was too small to evaluate is a group with no evidence at all, not a group with no problem.
P2.6.4 (synthesis) — Connect this section to 2.4.4. A model is deployed with a threshold derived from a cost ratio. Whose costs were they, and what does the impossibility result imply about that derivation?
Whose costs. The formula t* = C₄ₚ/(C₄ₚ + C₄ₙ) takes two numbers and returns a threshold, and it is silent about where the numbers came from. In practice they are the operator's costs: the bank's loss on a default, the hospital's cost of a follow-up test, the university's cost of a tutoring place. The person the decision is applied to also bears a cost — a refused loan, an unnecessary biopsy, a missed intervention — and that cost appears nowhere in the derivation unless someone deliberately puts it there. A cost ratio is a statement about whose errors matter, presented as arithmetic.
What the impossibility result adds. One threshold derived from one cost ratio produces the disaggregated picture of Worked 2.6a: different selection rates, recalls and precisions per group, because the groups have different base rates. So the cost-optimal threshold is automatically unfair on at least two of the three criteria. You can choose per-group thresholds to close one gap, but line 3 of the proof says you cannot close them all, and per-group thresholds are themselves legally and ethically contested since they treat people differently by group attribute explicitly.
The synthesis. There is no threshold that is simultaneously cost-optimal and fair on every criterion, so the choice must be made openly rather than discovered. The defensible practice is to state the cost ratio and whose costs it represents, state which fairness criterion is being prioritised and why, report the disaggregated metrics at the chosen threshold, and record all of it in a model card. That is not a way of solving the tension. It is a way of ensuring that whoever inherits the system can see the tension and revisit the decision — which, given that the alternative is a single accuracy figure, is a substantial improvement.
Cheat Sheet
Every formula in this file, plus the numbers from the ten test students so you can check your arithmetic against a known case.
2.4.1 The four cells
TP flagged, correct · FP flagged, wrong
FN missed · TN cleared, correct
accuracy = (TP+TN)/n
recall = TP/(TP+FN) — actual positives below
precision = TP/(TP+FP) — predicted positives below
specificity = TN/(TN+FP) · FPR = 1 − specificity
Recall reads a column; precision reads a row.
2.4.1 Robust summaries
balanced acc = (TPR + TNR)/2 — chance is 0.5000 always
MCC = (TP·TN − FP·FN) / √((TP+FP)(TP+FN)(TN+FP)(TN+FN))
κ = (pₒ − pₑ)/(1 − pₑ)
MCC, κ, accuracy and balanced accuracy are symmetric — relabelling the positive class leaves them unchanged.
Precision, recall and F1 are not.
2.4.2 F-scores
F1 = 2PR/(P+R) = 2TP/(2TP+FP+FN)
Fβ = (1+β²)PR/(β²P + R)
Larger β favours RECALL. β→0 gives precision, β→∞ gives recall.
F1 contains no TN term at all.
F1 depends on prevalence, so it is not comparable across datasets.
2.4.2 Imbalance
Always quote the majority-class baseline next to accuracy.
1000 patients, 10 sick, always-healthy model:
accuracy 0.9900, recall 0, balanced acc 0.5000
A real model at TP 8, FP 90, FN 2, TN 900:
accuracy 0.9080 — worse, and the model to deploy.
2.4.3 ROC and AUC
Plot (FPR, TPR) over every threshold. Up-step on a positive, right-step on a negative.
AUC = P(random positive scores above random negative)
= concordant pairs / (n₊ · n₋)
Random = 0.5000, and the diagonal is the baseline whatever the prevalence.
Invariant to any monotone rescaling of the scores.
2.4.3 PR curve
Plot (recall, precision). Baseline is a horizontal line at the prevalence.
AP = Σ(Rₖ − Rₖ₋₁)Pₖ
Use PR when positives are rare and are the class you care about; use ROC when both classes matter.
Fraud example: ROC point (0.01, 0.75) looks superb, precision is 0.1307. Same 998 false alarms.
2.4.4 Threshold
t* = C₄ₚ / (C₄ₚ + C₄ₙ)
Depends only on the cost ratio, not on prevalence, and requires calibration to be valid.
Equal costs → 0.5 · miss 9× worse → 0.1 · alarm 4× worse → 0.8
Optimal ROC slope = (C₄ₚ/C₄ₙ)(n₋/n₊)
The threshold is a hyperparameter: tune it on validation, never on test.
2.4.5 Regression
MSE squared units · RMSE = √MSE · MAE
MAPE = (100/n)Σ|r/y| — blows up near y = 0, asymmetric
R² = 1 − SSE/SST, can be negative on test data
adj R² = 1 − (1−R²)(n−1)/(n−d−1)
RMSE ≥ MAE always; the gap measures how uneven the errors are.
2.4.6 Calibration
ECE = Σ(nᵇ/n)|mean predictedᵇ − observedᵇ|
Brier = (1/n)Σ(p − y)², baseline = predict the prevalence
Log loss and Brier are proper scoring rules; AUC is not and cannot see calibration.
Platt scaling and isotonic regression fix magnitudes and preserve the ranking, so AUC never moves.
Fit them on held-out data.
2.4.6 Reporting
SE = s/√k · 95% CI uses t = 2.776 at 4 df
Report the mean and the spread.
Compare two models by paired differences on shared folds, not by overlapping intervals.
CV folds are not independent, so a paired t is anti-conservative.
2.5 Semi-supervised
Assumptions: smoothness, cluster, manifold — each an empirical claim.
Transductive labels the given points; inductive yields a reusable function.
Self-training → confirmation bias. Co-training needs two sufficient views. Consistency regularization commits to no pseudo-label.
Never evaluate against pseudo-labels. Hold out real ones.
Confidence thresholds require calibration to mean anything.
2.6 Fairness
Demographic parity equal selection rate
Equal opportunity equal TPR
Equalised odds equal TPR and FPR
Predictive parity equal PPV
PPV = p·TPR / (p·TPR + (1−p)·FPR)
Unequal prevalence ⇒ equal TPR and FPR force unequal PPV. Choose one criterion, justify it, document it.
Fairness through unawareness does not work.
The ten test students, end to end
Scores 0.92, 0.85, 0.78, 0.66, 0.54, 0.47, 0.35, 0.24, 0.18, 0.09 with actual labels pass, pass, fail, pass, fail, fail, pass, fail, fail, fail. Every number below is derived in this file from that one line.
| Quantity | Value | Section |
|---|---|---|
| Prevalence | 0.4000 | 2.4.0 |
| Confusion matrix at t = 0.50 | TP 3, FP 2, FN 1, TN 4 | 2.4.1 |
| Accuracy at t = 0.70, 0.50, 0.30 | 0.7000 at all three | 2.4.1 |
| Recall at t = 0.70, 0.50, 0.30 | 0.5000 / 0.7500 / 1.0000 | 2.4.1 |
| Precision at t = 0.70, 0.50, 0.30 | 0.6667 / 0.6000 / 0.5714 | 2.4.1 |
| MCC at t = 0.50 | 10/√600 = 0.4082 | 2.4.1 |
| Cohen's κ at t = 0.50 | 0.4000, with pₑ = 0.5000 | 2.4.1 |
| F1 at t = 0.70, 0.50, 0.30 | 0.5714 / 0.6667 / 0.7273 | 2.4.2 |
| F₂ at t = 0.30 | 0.8696 | 2.4.2 |
| F₀.₅ at every threshold | 0.6250 | 2.4.2 |
| ROC step sequence | up up right up right right up right right right | 2.4.3 |
| AUC | 20/24 = 0.8333 | 2.4.3 |
| Average precision | 0.8304, baseline 0.4000 | 2.4.3 |
| Cost-optimal threshold, miss 4× worse | t* = 0.8, cost 2 units | 2.4.4 |
| Cost at the default t = 0.5 | 9 units | 2.4.4 |
| ECE over four bins | 0.1440 | 2.4.6 |
| Brier score | 0.1786, baseline 0.2400 | 2.4.6 |
| Log loss | 0.5204 | 2.4.6 |
| Marks model RMSE / MAE / R² | 0.7071 / 0.5000 / 0.9412 | 2.4.5 |
| Fairness audit, recall gap | 0.9000 vs 0.6000 | 2.6 |
| Same audit, pooled accuracy | 0.7600 — hides everything | 2.6 |
Mixed Self-Test
Ten questions, unlabelled by section. Attempt all before opening any solution.
Q1. A classifier on 500 samples gives TP = 60, FP = 40, FN = 15, TN = 385. Compute accuracy, precision, recall, specificity, F1, balanced accuracy, MCC and the majority-class baseline. Is the model worth deploying?
Probably yes, but the accuracy figure is nearly worthless. 0.8900 against a baseline of 0.8500 is a gain of four points, not eighty-nine. The real evidence is elsewhere: balanced accuracy 0.8529 against a chance value of 0.5000, and MCC 0.6301 against 0, both say the model has substantial genuine skill that accuracy conceals.
The operational question is whether 40 false alarms is an acceptable price for finding 60 of the 75 positives. Precision 0.6000 means three in five flags are real. If a flag triggers a cheap check, deploy. If it triggers something costly or harmful, raise the threshold and recompute.
Q2. A screening model has precision 0.25 and recall 0.80. Compute F0.5, F1, F2 and F3. Which would you report and why?
The four values run from 0.2899 to 0.6557 on the identical model, which is the point: an F-score without its β is not a measurement. Each one is pulled toward whichever component it favours, and precision here is the weak one at 0.25.
Report F2 or F3, and say why. This is a screening model, so a missed case is far worse than a false alarm and the metric should encode that. Better still, report precision and recall separately alongside it — 0.25 and 0.80 tell a reader everything, and a single F-score tells them nothing without the pair. Choosing β after seeing the numbers, to make the model look good, is the failure mode to avoid.
Q3. A model ranks eight samples, highest first, with labels: pass, fail, pass, pass, fail, pass, fail, fail. Compute the AUC by counting pairs and the average precision. Give the ROC step sequence.
Cross-check the AUC by area: right-steps of width 1/4 occur at TPR heights 0.25, 0.75, 1.00, 1.00, so the area is (1/4)(0.25 + 0.75 + 1.00 + 1.00) = (1/4)(3) = 0.7500. ✓ The four discordant pairs all involve the negative at rank 2, which outranks three positives — a single badly-scored negative accounts for every error.
Q4. Missing a fraudulent transaction costs 12 times as much as investigating a legitimate one. Give the optimal threshold on the probability of fraud. Then give it for the reverse case, where a false alarm is 3 times worse than a miss.
Investigate anything above a 7.7% chance of fraud. That is a long way from 0.5 and it is exactly what a 12:1 cost ratio demands — you are willing to open twelve investigations to catch one fraud, because the thirteenth would break even.
Note that the answer is 1/13, not 1/12: the formula divides by the sum of the costs. Note also that neither answer involves the prevalence, however rare fraud is, provided the model's probabilities are calibrated. If they are not, both numbers are meaningless and 2.4.6 comes first.
Q5. A model predicts 5, 9, 14, 20 where the truth is 6, 7, 15, 18. Compute MSE, RMSE, MAE, MAPE and R².
RMSE 1.5811 against MAE 1.5000 is a narrow gap, consistent with errors of only 1 and 2 — evenly sized, no outliers. MAPE's 15.75% is dominated by the second point, where an error of 2 on a true value of 7 is 28.6%; the same error on the value of 18 is 11%. That is MAPE's characteristic distortion and the reason it should not be the headline figure when the target spans a wide range.
Q6. A model assigns probability 0.9 to 40 cases of which 28 are positive, and 0.6 to 60 cases of which 39 are positive. Compute the ECE and say which bin is worse and in what direction.
The 0.9 bin is much worse, and it is overconfident: the model claimed 90% and delivered 70%. The 0.6 bin is very slightly underconfident, claiming 60% and delivering 65%, which is a gap of 0.05 and well within noise on 60 cases.
So the pattern is confidence inflated specifically at the top end, which is the signature of an overfitted or unregularized model — and the most consequential place to be wrong, since high-confidence predictions are the ones acted on automatically. A monotone recalibration would pull the 0.9 bin down toward 0.7 while barely touching the other, and it would leave the AUC exactly where it is.
Q7. A model is audited across two groups. Group A: TP 36, FP 24, FN 4, TN 36. Group B: TP 9, FP 6, FN 21, TN 64. Compute base rate, selection rate, TPR, FPR and PPV for each. Which fairness criteria hold?
Predictive parity holds exactly — both groups have PPV 0.6000, so a flag means precisely the same thing whichever group you belong to. Everything else fails, and badly. Demographic parity: 0.6000 against 0.1500, a four-fold difference. Equal opportunity: 0.9000 against 0.3000, so a qualified member of group B is three times less likely to be found than a qualified member of group A. Equalised odds fails on both components.
This is the impossibility theorem in its most uncomfortable form. A vendor could truthfully report "the model is calibrated identically for both groups, and a flag is equally reliable for everyone" while 70% of group B's qualified members are being missed. Predictive parity was satisfied because group B's threshold is effectively so high, and the algebra of PPV = p·TPR/(p·TPR + (1−p)·FPR) shows how: B's lower prevalence is offset by its far lower FPR, landing on the same PPV. Verify it: 0.3(0.3)/[0.3(0.3) + 0.7(0.0857)] = 0.09/0.15 = 0.6000. ✓
Which criterion you should have picked depends on the harm. If the flag grants a benefit, equal opportunity is the one that matters and this model is indefensible.
Q8. Five-fold cross-validation gives 0.71, 0.79, 0.68, 0.75, 0.82. Write the honest one-sentence summary, including a 95% interval. Then say what you would need to claim a rival model at 0.77 is worse.
The honest sentence: "five-fold cross-validated accuracy 0.750, standard deviation 0.057 across folds, 95% interval 0.679 to 0.821."
To claim the rival is worse you need its per-fold scores on the identical folds. A rival mean of 0.77 is inside this model's interval, so an unpaired comparison can conclude nothing. But if the folds are shared, compute the five paired differences and test their mean against zero — fold-to-fold difficulty cancels and the test becomes far more sensitive, as Worked 2.4.6 showed with a mean difference of just 0.018 reaching t = 4.81. Note the direction here, though: 0.77 exceeds 0.75, so the rival is ahead on the means and the burden is on you.
Q9. A logistic model gives p = σ(2s − 8). Self-training accepts pseudo-labels at confidence 0.9 or above. Find the range of s that is accepted, and compare with the model of Worked 2.5 where the weight was 0.5 rather than 2.
Four times the weight gives one quarter the uncertain band, since the band width is 2 ln 9 / w. So this model pseudo-labels almost everything, while the flatter model of Worked 2.5 pseudo-labelled almost nothing.
And that is the danger, not the benefit. A large weight vector means the model has been driven to high confidence — on separable data, per 2A section 2.3.1, to arbitrarily high confidence — without necessarily being more accurate. Its confidence threshold has stopped filtering anything, so every prediction including the wrong ones is committed as a pseudo-label, and the confirmation-bias loop runs at full speed. Before trusting a confidence threshold, check the reliability diagram; the model that most wants to pseudo-label is the one least entitled to.
Q10. A model on 5,000 transactions with 100 frauds achieves recall 0.60 and specificity 0.97. Compute the full matrix, accuracy, precision, F1 and MCC, and compare with the do-nothing baseline. Then say what single change you would make.
The model's accuracy of 0.9626 is below the do-nothing baseline of 0.9800, so any accuracy-driven selection would reject it. Balanced accuracy 0.7850 and MCC 0.4006 say it has real, moderate skill — it finds 60 of 100 frauds. This is exactly the pattern of 2.4.2's hospital depth box.
The single change: choose the threshold from the cost ratio rather than leaving it at 0.5. Everything above describes one arbitrary operating point on a curve. If a missed fraud costs 12 times an unnecessary investigation, then t* = 1/13 = 0.0769, and at that threshold recall will be far above 0.60 at the price of more of the 147 false alarms — which is the trade the costs say to make. Report the AUC and average precision for the model, then the confusion matrix at the chosen threshold, and quote the prevalence beside both.
Worth noting what the specificity of 0.97 conceals: it sounds excellent and produces 147 false alarms, because 3% of 4,900 is a large number. When negatives dominate, specificity is the wrong lens and precision is the right one.
Where This Goes Next
Unit 2 is finished. Everything after it is a new hypothesis space evaluated by the machinery of this file.
What Unit 2 established, in one paragraph
Six model families, one small dataset, and the finding that all six fit it perfectly while disagreeing about every point in between — so the choice of family is your assumption, not the data's conclusion. Then a protocol for choosing honestly: separate the data, tune on validation, look at the test set once. Then the metrics, which showed that a single accuracy figure can hold still at 0.7000 while the classifier changes from mediocre to good. Then the threshold, which comes from costs rather than convention. And finally the observation that those costs are somebody's, that the errors land on people, and that the same metrics disaggregated by group are the whole of a fairness audit.
| From here | Reappears as |
|---|---|
| 2.4.1–2.4.2 Confusion matrix, precision and recall | The evaluation of every classifier in Units 4 and 5, where per-class recall on a confusion matrix is how you find out which of a hundred classes the network cannot see. Also the internal-validation measures of clustering (3.2), which face the same problem without labels. |
| 2.4.3 ROC, AUC and average precision | The standard reporting for deep classifiers and detectors; mean average precision is the headline metric for object detection in Unit 5. |
| 2.4.4 Cost-derived thresholds | The action-selection problem of reinforcement learning (Unit 6), where a policy is exactly a rule for converting estimated value into a choice under asymmetric consequences. |
| 2.4.5 Regression metrics | The loss functions of Units 4 and 5 directly — MSE is the training objective for regression networks and for autoencoder reconstruction. |
| 2.4.6 Calibration and honest reporting | A live problem in deep learning, where networks are reliably overconfident; temperature scaling is Platt scaling under another name. The CV reporting discipline applies to every experiment in Units 3 to 6. |
| 2.5 Semi- and self-supervised learning | Unit 5's pre-training paradigm. Masked and next-token prediction are the pretext tasks that produce language models; contrastive learning is the vision equivalent. This section is the conceptual entry point to the second half of the course. |
| 2.6 Responsible AI | Deepens as models become less interpretable. Unit 5's networks make the interpretability material harder and more necessary; the fairness algebra is unchanged, because it never depended on the model. |
Before you move on
Seven things you should be able to do from a blank page. Build a confusion matrix at a stated threshold and derive eight metrics from it. Compute Fβ and say which way β leans. Sweep a threshold to produce an ROC curve and get the AUC by counting concordant pairs. Derive a threshold from a cost ratio and check the direction against intuition. Compute RMSE, MAE and R² and explain what their gaps mean. Summarise five fold scores with a mean, a spread and a paired comparison. And audit a model across two groups, compute the three gaps, and state why they cannot all be zero.
If any is shaky, that section's practice ladder is the fastest repair. Unit 3 assumes the first three.
Further reading
- Géron, Hands-On Machine Learning, 3rd ed., ch. 3 — the prescribed textbook's treatment of classification metrics, with the precision–recall trade-off and ROC worked in code. The closest match to sections 2.4.1 to 2.4.3.
- Hastie, Tibshirani and Friedman, The Elements of Statistical Learning, ch. 7 — the rigorous account of model assessment, cross-validation and the optimism of the training error. Section 7.10 on cross-validation is the reference for 2.4.6's reporting discipline.
- Barocas, Hardt and Narayanan, Fairness and Machine Learning — freely available online and the standard text for section 2.6. Chapter 3 contains the impossibility results with full proofs and a careful discussion of when each criterion is appropriate.
- Chouldechova (2017) and Kleinberg, Mullainathan and Raghavan (2016) — the two short papers that established the incompatibility of Worked 2.6b independently. Both are readable in an afternoon and the algebra is the four lines given here.
- Guo et al., "On Calibration of Modern Neural Networks" (2017) — the paper that made calibration a mainstream concern, and the source of temperature scaling. Short, and directly relevant to Unit 5.
- Mitchell et al., "Model Cards for Model Reporting" (2019) — the documentation proposal referenced in 2.6's depth box. Worth reading as a template rather than a paper.
Test set: ten students with predicted pass probabilities and known outcomes, prevalence 0.4. Fairness audit: two cohorts of 120 and 80 with base rates 0.50 and 0.25. Every numerical value in this file was computed rather than estimated.
Previous: Unit 2A — Supervised Learning: Models · Next: Unit 3 — Unsupervised Learning