Unit 5 · Tutorial 06
Class Imbalance and Thresholds
Logistic regression gives you a probability. Turning that probability into a decision is where most real classification problems are won or lost — and the default threshold of 0.5 is frequently the wrong choice. This tutorial covers why, what to measure instead of accuracy, and how to set a threshold that matches what actually matters.
01 Learning objectives
By the end of this tutorial you will be able to
- Define class imbalance and explain why it breaks the accuracy metric.
- Construct and interpret a confusion matrix, and derive precision, recall, specificity and F1 from it.
- Explain the precision-recall trade-off and describe how it changes as the threshold moves.
- Compare ROC curves and precision-recall curves, and explain when the latter is more informative.
- Choose a threshold using cost-sensitive reasoning, and compute the expected cost of a decision rule.
- Describe the main approaches to handling imbalance during training: class weights, resampling and their consequences for calibration.
- Recognise when a model's probabilities are miscalibrated, and explain how to fix it.
Position in the unit
This tutorial completes the logistic regression story by addressing the gap between T-03 (which set the threshold aside) and T-05 (which interpreted the model on three scales). It also previews Unit 6, where the evaluation metrics introduced here are developed systematically for all classifiers. T-07 then returns to the fitting problem and introduces regularisation, which is particularly important when classes are imbalanced.
02 Motivating example
A payments company is building a model to detect fraudulent transactions. From historical records, roughly 1% of transactions are fraudulent. The company has a million transactions a month, and each fraud that goes undetected costs around $800 in losses and investigation. Each legitimate transaction that is wrongly flagged costs about $50 in customer friction and manual review.
A data scientist fits a logistic regression and reports a headline result:
"The model achieves 99% accuracy."
This sounds impressive. It is also almost completely meaningless. Consider a model that predicts "not fraud" for every single transaction. It never investigates anything, never inconveniences a legitimate customer, and its accuracy is 99% — exactly the same as the model just described. The two models are not remotely equivalent, but accuracy cannot tell them apart.
Worse, when the data scientist moves the threshold from the default 0.5 to a value that actually catches most frauds, accuracy falls. At the threshold that minimises the company's total costs, the model's accuracy drops to around 97%. A naive evaluation would reject the model that saves the most money.
This is the central problem of class imbalance: the metric that everyone reaches for first — accuracy — is precisely the one that cannot answer the question that matters. The rest of this tutorial develops the tools that can.
The imbalance trap
Class imbalance is not just about rare events. It is about the mismatch between what the metric rewards and what the decision-maker cares about. Accuracy rewards a model for agreeing with the majority class; a decision-maker cares about the costs of being wrong in each direction. When the classes are imbalanced, these two objectives diverge sharply.
03 Concept explanation
3.1 What class imbalance is
A dataset is imbalanced when the classes are not represented in roughly equal proportions. There is no precise threshold, but the practical impact of imbalance grows as the minority class becomes rarer:
| Positive rate | Severity | Typical examples |
|---|---|---|
| 10–50% | Mild | Customer churn, loan default, disease prevalence in a clinic |
| 1–10% | Moderate | Fraud detection, click-through prediction, rare adverse events |
| 0.1–1% | Severe | Network intrusion, manufacturing defects, rare disease screening |
| < 0.1% | Extreme | Catastrophic equipment failure, certain types of fraud, terrorist watchlists |
Imbalance is not itself a problem — many important problems are inherently rare. It becomes a problem when it is ignored, because the standard toolkit of metrics, loss functions and default thresholds is designed for balanced data.
3.2 Why accuracy fails
Accuracy is the proportion of predictions that are correct. With a positive rate of 1%, a model that predicts "negative" for every case gets 99% accuracy. A model that catches half the frauds and makes modest numbers of false alarms will do worse on accuracy, even though it is far more useful.
Formally, accuracy conflates two very different kinds of error. Predicting negative for a fraudulent transaction is a false negative, and it is extremely costly. Predicting positive for a legitimate transaction is a false positive, and it is less costly. Accuracy treats both as equal, which is rarely what a decision-maker wants.
The accuracy paradox
Under severe imbalance, the highest-accuracy model is often the one that does the least. A trivial model that always predicts the majority class will beat almost any useful classifier on accuracy. This is not a corner case — it is the default outcome whenever the classes are imbalanced and the metric is accuracy.
3.3 The confusion matrix
The right starting point is the confusion matrix, which cross-tabulates the actual class against the predicted class. With a binary outcome, there are four cells:
| Predicted positive | Predicted negative | |
|---|---|---|
| Actual positive | True positive (TP) Correct detection |
False negative (FN) Missed case |
| Actual negative | False positive (FP) False alarm |
True negative (TN) Correct rejection |
Every metric discussed in this tutorial is derived from these four counts. The
total number of cases is n = TP + FP + FN + TN, and the number of
actual positives is TP + FN.
3.4 Precision, recall and F1
Two metrics measure the two different kinds of success, and they are the foundation of everything else:
Precision = TP / (TP + FP)
Recall = TP / (TP + FN)
Precision answers: of all the cases we flagged as positive, how many actually were? It measures the purity of the positive predictions — the cost of false alarms.
Recall (also called sensitivity or true positive rate) answers: of all the actual positives, how many did we catch? It measures the coverage of the positive class — the cost of missed cases.
These are the two quantities that matter under imbalance. Notice that both have the count of actual positives or predicted positives in the denominator, which means neither is dominated by the majority class.
Two further metrics are useful:
Specificity = TN / (TN + FP) (true negative rate)
F1 = 2 · (Precision · Recall) / (Precision + Recall)
Specificity is the complement of the false positive rate — the proportion of true negatives correctly identified. The F1 score is the harmonic mean of precision and recall, which is high only when both are reasonably high.
Why the harmonic mean?
The ordinary arithmetic mean of precision and recall can be high even if one of them is near zero — for example, precision 0.99 and recall 0.01 have an arithmetic mean of 0.50, which sounds acceptable but is useless. The harmonic mean is dominated by the smaller of the two values, so it only scores well when both are non-trivial. This is why F1 is the standard single-number summary for imbalanced classification.
A generalisation, the F-beta score, allows you to weight one metric more than the other:
F_β = (1 + β²) · (Precision · Recall) / (β² · Precision + Recall)
Setting β = 1 gives F1. Setting β = 2 weights recall
twice as heavily as precision — appropriate when missing cases is worse than
false alarms. Setting β = 0.5 does the reverse.
3.5 The precision-recall trade-off
Precision and recall are in tension. As you lower the threshold, you classify more cases as positive. This catches more true positives (recall rises), but it also catches more false positives (precision falls). Raising the threshold reverses the effect.
You cannot generally have both high precision and high recall. The question is not which is "better" in the abstract but which is more important for the problem at hand — and how much of the other you are willing to sacrifice.
This trade-off is a property of the threshold, not of the model. As T-03 established, moving the threshold changes the decision boundary without changing the model, the probabilities or the ranking of cases. The model produces one set of probabilities; the threshold produces one point on the precision-recall curve.
3.6 ROC curves and PR curves
Plotting the trade-off across all possible thresholds gives a curve. Two conventions are common.
The ROC curve plots the true positive rate (recall) against the
false positive rate (FPR = FP / (FP + TN)
The precision-recall curve plots precision against recall. Its area (PR-AUC) is a different summary, and it behaves differently under imbalance.
| Aspect | ROC curve | PR curve |
|---|---|---|
| Axes | TPR vs. FPR | Precision vs. recall |
| Baseline | Diagonal (AUC = 0.5) | Horizontal line at the prevalence |
| Sensitive to imbalance? | Relatively insensitive | Highly sensitive |
| Preferred when | Classes balanced; both errors matter | Positive class rare; precision matters |
| Common pitfall | Looks good even when precision is poor | Noisier with very few positives |
The critical difference is in the denominators. The false positive rate divides
by FP + TN, which is enormous when the negative class dominates.
Even thousands of false positives produce a small FPR, so the ROC curve looks
excellent. Precision divides by TP + FP — the number of actual
positive predictions — which is small, so the same thousands of false positives
cause precision to collapse.
This is why the ROC curve can be misleading under severe imbalance, and why the PR curve is usually the better choice when the positive class is rare.
3.7 Choosing a threshold
There is no universal threshold. The right threshold depends on what you are trying to achieve. Five common objectives:
| Strategy | Objective | Use case |
|---|---|---|
| Maximise F1 | Balance precision and recall | No explicit cost information; want a defensible default |
| Maximise F_β | Weight one metric more | Recall matters more (screening) or less (spam filtering) |
| Target recall | Fixed minimum recall | Regulatory or clinical requirement: "catch at least 90% of cases" |
| Target precision | Fixed minimum precision | Operational constraint: "no more than 5% false alarm rate" |
| Minimise expected cost | Weighted sum of errors | When the costs of FP and FN are known or estimable |
The last strategy — minimising expected cost — is the most principled when cost information is available, and it is the one we will develop in detail in Section 05.
3.8 Cost-sensitive threshold selection
Suppose a false negative costs C_FN and a false positive costs
C_FP. The expected cost of a decision rule at threshold t
is:
Cost(t) = C_FN · FN(t) + C_FP · FP(t)
The optimal threshold is the one that minimises this expression. Crucially, the optimal threshold does not depend on the model alone — it depends on the ratio of the two costs.
When C_FN is much larger than C_FP — as in fraud
detection or cancer screening — the optimal threshold is low, and the model
flags many cases as positive. When C_FP is larger — as in spam
filtering, where wrongly blocking a legitimate email is worse than letting spam
through — the optimal threshold is high.
The base-rate interaction
The cost-optimal threshold also depends on the prevalence of the positive class. When the positive class is rare, even a low threshold produces few positive predictions, and the trade-off between precision and recall shifts. This is why the same cost ratio can lead to very different thresholds in different settings.
3.9 Handling imbalance during training: class weights
Threshold selection is applied after fitting. But imbalance also affects the fitting process itself. With severe imbalance, the maximum-likelihood estimate is dominated by the majority class, because the log-likelihood sums over all observations and the majority class contributes most of the terms.
One remedy is to weight the classes so that the minority class contributes more to the loss. In scikit-learn:
LogisticRegression(class_weight='balanced')
The 'balanced' option sets weights inversely proportional to class
frequencies:
w_j = n_samples / (n_classes · n_samples_j)
For a dataset with 1% positives, this gives the positive class roughly 50 times the weight of the negative class. The fitted coefficients are then pulled towards better performance on the minority class.
Three things to note about class weights. First, they change the coefficients, so they change the probabilities too. Second, the resulting probabilities are no longer calibrated to the original prevalence — they behave as if the classes were balanced. Third, the effect on the final decision is similar to lowering the threshold: both make the model more willing to predict positive. The two approaches are related, but not identical, and the choice depends on what you want to control.
3.10 Resampling
An alternative to weighting is to change the data itself, by resampling.
Undersampling discards examples from the majority class, bringing the class proportions closer together. It is simple and reduces training time, but it throws away information — potentially important information, since the majority class is where most of the data lives.
Oversampling duplicates examples from the minority class. It retains all the data, but duplicated examples can cause the model to overfit to the specific cases that happen to be in the minority class.
SMOTE (Synthetic Minority Over-sampling Technique) takes a middle path: it generates new synthetic minority examples by interpolating between existing ones. This avoids exact duplication while enriching the minority region of feature space.
Resampling must respect the data split
Resampling must be applied to the training set only. If you
resample before splitting, synthetic or duplicated examples will leak into the
test set, and your evaluation will be optimistic and wrong. Use
imblearn.pipeline.Pipeline rather than
sklearn.pipeline.Pipeline when combining resampling with
cross-validation.
3.11 Calibration
Class weights and resampling both distort the predicted probabilities. A model
trained with balanced weights on data that is actually 1% positive will output
probabilities that behave as if the prevalence were 50%. If you then interpret
p = 0.7 as "a 70% chance of fraud," you will be badly wrong.
This matters whenever the probability itself is used for a decision — expected value calculations, risk scoring, or anything where "how likely" matters, not just "which class." It does not matter if you only care about ranking.
Two standard corrections exist:
- Platt scaling fits a logistic regression to the model's scores on a held-out calibration set, mapping them to calibrated probabilities.
- Isotonic regression fits a monotonic step function, which is more flexible than Platt scaling but requires more data.
Both require a held-out set that was not used for training, and both are
available in scikit-learn via CalibratedClassifierCV.
A related issue arises even without resampling: logistic regression's probabilities are not guaranteed to be well calibrated, especially with regularisation or limited data. Always check calibration if the probabilities will be used directly.
3.12 A checklist
When you face a classification problem with imbalanced classes, work through these steps in order.
What proportion of cases are positive? This determines how severe the imbalance is.
At the default threshold, count TP, FP, FN and TN. Never report accuracy alone.
These are the metrics that survive imbalance. Report them with the threshold they were computed at.
Look at the shape across all thresholds. The ROC curve is optional; the PR curve is essential.
What does a false positive cost? What does a false negative cost? Even rough estimates are better than none.
Minimise expected cost, or target a specific recall or precision if costs are unavailable.
If the model is not learning the minority class at all, weighting or resampling can help.
If you use the probabilities for anything other than ranking, verify they mean what they say.
The threshold, the costs and the metrics are decisions. Write them down.
04 Visual illustration
Figure 1 shows the confusion matrix for the fraud model at the default threshold of 0.5. Every metric in this tutorial is derived from the four cells in this diagram.
Figure 2 plots precision and recall as the threshold moves from 0.9 (high, conservative) down to 0.1 (low, aggressive). The curve shows the fundamental trade-off: you cannot increase recall without sacrificing precision.
The gap between the curve and the baseline is what the model adds. Because the baseline is so low — only 1% — even the poor precision at low thresholds represents real signal. This is why PR curves are essential under severe imbalance: they make the model's actual contribution visible, which the ROC curve does not.
05 Worked example
We work through the fraud model in full, Computing every metric at every threshold, and then selecting a threshold by expected cost.
Step 1 · Build the threshold table
The model produces a probability for each of the 100,000 transactions. There are 1,000 actual frauds and 99,000 legitimate transactions. Moving the threshold from 0.9 down to 0.1 produces the following counts:
| t | TP | FP | FN | TN | Precision | Recall | F1 | Accuracy |
|---|---|---|---|---|---|---|---|---|
| 0.9 | 200 | 100 | 800 | 98,900 | 0.667 | 0.200 | 0.308 | 0.9910 |
| 0.8 | 300 | 200 | 700 | 98,800 | 0.600 | 0.300 | 0.400 | 0.9910 |
| 0.7 | 400 | 300 | 600 | 98,700 | 0.571 | 0.400 | 0.471 | 0.9910 |
| 0.6 | 480 | 500 | 520 | 98,500 | 0.490 | 0.480 | 0.485 | 0.9898 |
| 0.5 | 550 | 800 | 450 | 98,200 | 0.407 | 0.550 | 0.468 | 0.9875 |
| 0.4 | 650 | 1,400 | 350 | 97,600 | 0.317 | 0.650 | 0.426 | 0.9825 |
| 0.3 | 750 | 2,500 | 250 | 96,500 | 0.231 | 0.750 | 0.353 | 0.9725 |
| 0.2 | 850 | 4,500 | 150 | 94,500 | 0.159 | 0.850 | 0.268 | 0.9535 |
| 0.1 | 950 | 9,000 | 50 | 90,000 | 0.096 | 0.950 | 0.174 | 0.9095 |
Read this table carefully — it contains most of the tutorial's argument.
- Accuracy falls as the threshold drops. The highest accuracy (0.9910) occurs at the highest thresholds, where the model predicts positive for almost nothing. The trivial all-negative classifier also achieves 0.99. Accuracy is useless here.
-
F1 peaks at an intermediate threshold. It is maximised at
t = 0.6, not at the defaultt = 0.5. The model's "best" threshold by F1 is not the one scikit-learn would give you by default. - Precision and recall trade off smoothly. Doubling recall from 0.30 to 0.60 costs about half the precision — exactly the pattern Figure 2 illustrates.
Step 2 · Estimate the costs
The company estimates:
- Cost of a missed fraud:
C_FN = $800 - Cost of a false alarm:
C_FP = $50
The false negative is 16 times as expensive as the false positive. This ratio will drive the threshold choice.
Step 3 · Compute the expected cost at each threshold
Cost(t) = 800 · FN(t) + 50 · FP(t)
| t | FN | FP | 800·FN | 50·FP | Total cost |
|---|---|---|---|---|---|
| 0.9 | 800 | 100 | $640,000 | $5,000 | $645,000 |
| 0.8 | 700 | 200 | $560,000 | $10,000 | $570,000 |
| 0.7 | 600 | 300 | $480,000 | $15,000 | $495,000 |
| 0.6 | 520 | 500 | $416,000 | $25,000 | $441,000 |
| 0.5 | 450 | 800 | $360,000 | $40,000 | $400,000 |
| 0.4 | 350 | 1,400 | $280,000 | $70,000 | $350,000 |
| 0.3 | 250 | 2,500 | $200,000 | $125,000 | $325,000 |
| 0.2 | 150 | 4,500 | $120,000 | $225,000 | $345,000 |
| 0.1 | 50 | 9,000 | $40,000 | $450,000 | $490,000 |
The minimum cost is at t = 0.3, with a total of
$325,000. This is the threshold the company should use.
Notice the shape of the cost curve. It falls from $645,000 at the highest
threshold, reaches a minimum at 0.3, then rises again. The rise at the bottom
is caused by the explosion in false positives — at t = 0.1, the
model flags 9,000 legitimate transactions, and the cost of those false alarms
($450,000) exceeds the savings in missed fraud.
Step 4 · Compare with the default and with doing nothing
Three reference points put the result in context:
| Strategy | Frauds caught | False alarms | Total cost |
|---|---|---|---|
| Do nothing (all negative) | 0 | 0 | $800,000 |
| Default threshold 0.5 | 550 | 800 | $400,000 |
| Cost-optimal threshold 0.3 | 750 | 2,500 | $325,000 |
The cost-optimal threshold saves $475,000 compared with doing nothing, and a further $75,000 compared with the default. The accuracy at the optimal threshold — 0.9725 — is lower than the accuracy of the do-nothing baseline (0.99). And yet the cost-optimal model is dramatically better by the metric that actually matters.
The lesson in one sentence
When the costs of the two kinds of error differ, the metric that ignores those costs — accuracy — will point you to the wrong model. Use the costs, not the accuracy.
Step 5 · What changes if the costs change
Suppose the company reduces the cost of a missed fraud to $200 — perhaps
because it changes its liability policy. The new cost function is
200·FN + 50·FP:
| t | 200·FN + 50·FP |
|---|---|
| 0.9 | $165,000 |
| 0.7 | $135,000 |
| 0.5 | $130,000 |
| 0.4 | $140,000 |
| 0.3 | $175,000 |
The optimal threshold moves up, from 0.3 to 0.5. When false negatives are less costly, the company should flag fewer transactions.
This is the key operational insight: the optimal threshold is a moving target, and it moves whenever the cost structure changes. It belongs in the model's configuration, not in its training. Recalculating it is cheap; retraining is not.
06 Interactive activity
Activity · Build the threshold table yourself
In this activity you will fit a logistic regression to an imbalanced dataset, compute the full threshold table, and choose a threshold by expected cost. The goal is to build fluency with the confusion matrix and the metrics derived from it.
-
Generate an imbalanced dataset with
make_classificationand a positive rate of about 2%. Split it into training and test sets. -
Fit a logistic regression on the training set, using
penalty=Noneto avoid confounding the exercise with regularisation. Predict probabilities on the test set. -
For each threshold in
[0.1, 0.2, …, 0.9], compute the confusion matrix on the test set and report precision, recall, F1 and accuracy. - Plot the precision-recall curve and mark each threshold.
-
Now choose costs. Suppose
C_FN = 100andC_FP = 10. Compute the expected cost at each threshold and identify the minimum. -
Repeat with
C_FN = 100andC_FP = 50. How does the optimal threshold change? -
Refit the model with
class_weight='balanced'. How do the coefficients change? How does the PR curve change? Does the optimal threshold change?
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score
# Imbalanced data: 2% positive
X, y = make_classification(n_samples=20000, n_features=6, n_informative=4,
n_redundant=0, weights=[0.98, 0.02],
class_sep=1.0, flip_y=0.01, random_state=0)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3,
stratify=y, random_state=0)
clf = LogisticRegression(penalty=None, max_iter=5000).fit(X_tr, y_tr)
probs = clf.predict_proba(X_te)[:, 1]
thresholds = np.arange(0.05, 0.96, 0.05)
rows = []
for t in thresholds:
preds = (probs >= t).astype(int)
tn, fp, fn, tp = confusion_matrix(y_te, preds).ravel()
rows.append({
"t": t,
"TP": tp, "FP": fp, "FN": fn, "TN": tn,
"precision": precision_score(y_te, preds, zero_division=0),
"recall": recall_score(y_te, preds, zero_division=0),
"f1": f1_score(y_te, preds, zero_division=0),
})
import pandas as pd
df = pd.DataFrame(rows)
print(df.round(3))
# Cost-optimal threshold
C_FN, C_FP = 100, 10
df["cost"] = C_FN * df["FN"] + C_FP * df["FP"]
best = df.loc[df["cost"].idxmin()]
print(f"\nCost-optimal threshold: {best['t']:.2f}, cost = ${best['cost']:,.0f}")
# PR curve
fig, ax = plt.subplots(figsize=(7.5, 5))
ax.plot(df["recall"], df["precision"], marker="o", linewidth=2.2,
color="#1f4e8c")
prevalence = y_te.mean()
ax.axhline(prevalence, color="#9b2c1c", linestyle="--",
label=f"baseline (prevalence = {prevalence:.3f})")
ax.set_xlabel("recall")
ax.set_ylabel("precision")
ax.set_title("Precision-recall curve")
ax.legend()
ax.grid(alpha=0.25)
plt.tight_layout()
plt.show()
Two results usually surprise students. First, the precision-recall curve may not
be monotonic — with a small test set and few positives, precision can be noisy.
Second, refitting with class_weight='balanced' tends to shift the
whole curve up and to the right, but the shape is similar. The weights
change the probabilities, not the ranking — and since the PR curve only depends
on the ranking, the curve is essentially the same curve with a different
threshold mapping.
07 Self-check questions
Answer each question before revealing the solution.
Question 1
A model achieves 99% accuracy on a dataset with 1% positives. Is this a good model? What additional information would you need?
Show answer
99% accuracy is exactly what the trivial all-negative classifier would achieve. The metric alone tells you nothing about whether the model detects any positives at all.
You would need the confusion matrix — specifically the number of true positives and false negatives — and the precision, recall and F1. You would also need to know the threshold at which these were computed, and whether that threshold is appropriate for the application.
Question 2
A model has precision 0.30 and recall 0.80. Compute F1. Interpret the result.
Show answer
F1 = 2(0.30)(0.80) / (0.30 + 0.80) = 0.48 / 1.10 = 0.436.
The model catches 80% of the true positives, but only 30% of the cases it flags are actually positive. The F1 score of 0.436 reflects the imbalance between the two metrics — it is pulled down substantially by the low precision.
Question 3
Why is the ROC curve potentially misleading under severe class imbalance?
Show answer
The false positive rate has FP + TN in the denominator.
When the negative class is very large, TN dominates this
sum, so even thousands of false positives produce a small FPR. The ROC
curve therefore looks excellent even when precision is very poor.
The PR curve avoids this because precision has TP + FP in
the denominator — the actual number of positive predictions — which is
small. The same false positives that barely affect FPR cause precision
to collapse visibly.
Question 4
A false negative costs $1,000 and a false positive costs $100. Should the threshold be higher or lower than 0.5? Explain.
Show answer
Lower. When a false negative is much more costly than a false positive, the model should be more willing to predict positive — it should accept more false alarms in exchange for catching more true positives.
A rough rule of thumb: the optimal threshold is close to
C_FP / (C_FP + C_FN) when calibrated probabilities are
available. Here that would be 100 / 1100 ≈ 0.09, suggesting
a very low threshold. In practice the exact value depends on the full
distribution of probabilities.
Question 5
What is the difference between class weighting and threshold adjustment? Do they achieve the same thing?
Show answer
Class weighting changes the fitting procedure. It alters the loss function so that the minority class contributes more, which changes the fitted coefficients and the probabilities.
Threshold adjustment changes the decision rule, applied after fitting. It leaves the coefficients and probabilities unchanged.
They are not equivalent. Class weighting can change which features are emphasised and can improve the model's ability to separate the classes — particularly when the minority class is so rare that the unweighted fit ignores it. Threshold adjustment can only move the operating point along the existing PR curve.
In practice, if the unweighted model already produces useful rankings, threshold adjustment is sufficient. If it does not, class weighting is the more substantial intervention.
Question 6
Why does resampling distort predicted probabilities, and what can you do about it?
Show answer
Resampling changes the class proportions in the training data. The model learns to predict probabilities as though the new proportions were the true prevalence. If you undersample negatives to achieve 1:1 balance when the true prevalence is 1%, the model will output probabilities around 0.5 for cases that are actually quite unlikely.
The standard remedy is calibration: fit a mapping from
the model's raw scores to calibrated probabilities using a held-out
calibration set. Platt scaling (a logistic regression on the scores) and
isotonic regression (a monotonic step function) are the two standard
methods, both available via CalibratedClassifierCV in
scikit-learn.
Note that if you only care about the ranking — for example, if you are going to select the top 1% of cases by score — calibration is not necessary. It matters only when the probability value itself is used.
08 Practice exercises
Work these by hand where possible, then verify computationally.
- A test set has 500 positives and 9,500 negatives. A model predicts positive for 1,000 cases, of which 300 are true positives. Compute the confusion matrix, precision, recall, specificity and F1.
- A model has precision 0.25 and recall 0.60. Compute F1. Compute F2 (which weights recall twice as heavily). Which metric is higher, and why?
- A dataset has 0.5% positive rate. A model with perfect ranking and a threshold of 0.5 achieves precision 0.15 and recall 0.90. Explain why the precision is so low even though the ranking is perfect.
-
A model produces the following counts at three thresholds:
t = 0.7: TP = 200, FP = 100, FN = 800, TN = 98,900t = 0.5: TP = 500, FP = 900, FN = 500, TN = 98,100t = 0.3: TP = 800, FP = 3,000, FN = 200, TN = 96,000
-
Using the same counts as exercise 4, compute expected cost at each threshold
for
C_FN = $500andC_FP = $20. Which threshold minimises cost? -
For the same counts, compute expected cost for
C_FN = $100andC_FP = $50. How does the optimal threshold change? - A model achieves ROC-AUC = 0.95 and PR-AUC = 0.10. Interpret both numbers. Which one should you report to a stakeholder concerned about false alarms?
-
A model is trained with
class_weight='balanced'on data with a 2% positive rate. It predictsp = 0.6for a particular case. Should this be interpreted as a 60% chance of a positive outcome? Explain.
09 Problem sets
These problems require reasoning about the trade-offs rather than computation.
Problem 1 · Choosing a metric for a screening programme
A public health agency is deploying a screening model for a rare but treatable condition. The prevalence is 0.3%. Follow-up testing is expensive and somewhat invasive; missing a case is potentially fatal. The agency asks you to recommend a metric and a threshold. Which would you choose, and how would you justify it to a lay audience?
Problem 2 · The cost of tuning the threshold
A company has been using the default threshold of 0.5 for two years. A new analyst recommends lowering it to 0.3, citing a 19% reduction in expected cost. The engineering team objects that changing the threshold requires re-validating the system, retraining the support staff and updating documentation. How would you weigh the technical benefit against the operational cost? Is threshold tuning ever too expensive to justify?
Problem 3 · Imbalance and fairness
A fraud detection model achieves 90% recall overall, but only 60% recall on transactions from one particular region. The region has a much lower transaction volume, so its contribution to the training data is small. Is this a class imbalance problem, a fairness problem, or both? What would you do?
Problem 4 · Why the ROC curve looks good
A model on a 1%-positive dataset achieves ROC-AUC = 0.98 and PR-AUC = 0.15. Compute the ROC-AUC and PR-AUC for a random classifier on the same data. Explain why the two areas behave so differently, and discuss which is the more honest summary.
Problem 5 · Class weights vs. resampling
A colleague argues that class weights and oversampling achieve the same thing because both "make the minority class count more." Is this true? Discuss the differences, including their effect on fitted coefficients, on the probability scale, and on computational cost.
Problem 6 · When accuracy is the right metric
Despite everything in this tutorial, there are situations where accuracy is the appropriate metric for an imbalanced problem. Construct at least one such scenario, and explain what makes it different from the fraud detection example.
10 Discussion and projects
Discussion questions
- The cost-optimal threshold is a single number that encodes a value judgement — how much a false negative is worth relative to a false positive. Who should be responsible for setting that judgement in a medical screening programme? In a fraud detection system?
- A model with a fixed threshold produces the same decision rule for every case. Would it ever be better to vary the threshold by context — for example, using a lower threshold for high-risk customers? What are the fairness implications of doing so?
- Class weighting, resampling and threshold adjustment all change the trade-off between precision and recall. Are these three approaches interchangeable, or does each have a distinct role? Give an example where one is clearly the right choice.
- The accuracy metric fails under imbalance because it treats both kinds of error equally. Is there any analogous failure for precision, recall or F1? What assumptions does each of these metrics make about what matters?
Mini-project · Full evaluation of an imbalanced classifier
In this project you will take an imbalanced dataset of your choice and produce a complete evaluation, including a recommendation for a specific threshold and an honest discussion of the limitations. This is the kind of analysis that would accompany a real deployment decision.
Any binary classification problem with fewer than 10% positives. Public datasets with imbalanced classes are widely available.
Compute the accuracy, precision, recall and F1 of the trivial all-negative and all-positive classifiers. These are your reference points.
Use the default settings, then repeat with class_weight='balanced'. Compare coefficients.
Compute the full confusion matrix, precision, recall and F1 at every threshold from 0.05 to 0.95.
Produce a PR curve and an ROC curve on the same data. Compare the two.
Research or estimate realistic costs for false positives and false negatives in your domain.
Justify your choice on the basis of the costs and the PR curve.
Include the recommended threshold, the expected cost at that threshold, the expected cost at the default threshold, and the limitations of your analysis.
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import (confusion_matrix, precision_score,
recall_score, f1_score, roc_auc_score,
average_precision_score)
from sklearn.calibration import CalibratedClassifierCV
# Fit the model
clf = LogisticRegression(penalty=None, max_iter=5000).fit(X_tr, y_tr)
probs = clf.predict_proba(X_te)[:, 1]
# Overall discrimination
print(f"ROC-AUC: {roc_auc_score(y_te, probs):.3f}")
print(f"PR-AUC: {average_precision_score(y_te, probs):.3f}")
# Threshold sweep with all metrics
rows = []
for t in np.arange(0.05, 0.96, 0.05):
preds = (probs >= t).astype(int)
tn, fp, fn, tp = confusion_matrix(y_te, preds).ravel()
rows.append({
"t": round(t, 2),
"TP": tp, "FP": fp, "FN": fn, "TN": tn,
"precision": precision_score(y_te, preds, zero_division=0),
"recall": recall_score(y_te, preds, zero_division=0),
"f1": f1_score(y_te, preds, zero_division=0),
"accuracy": (tp + tn) / len(y_te),
})
df = pd.DataFrame(rows)
print(df.round(3).to_string(index=False))
# Calibrate the model for probability interpretation
calibrated = CalibratedClassifierCV(clf, method="isotonic", cv=5)
calibrated.fit(X_tr, y_tr)
cal_probs = calibrated.predict_proba(X_te)[:, 1]
print(f"\nRaw mean probability: {probs.mean():.4f}")
print(f"Calibrated mean probability: {cal_probs.mean():.4f}")
print(f"Actual prevalence: {y_te.mean():.4f}")
The final block is worth running even if you do not plan to deploy a model. It prints three numbers: the mean predicted probability from the raw model, the mean predicted probability from the calibrated model, and the true prevalence in the test set. A well-calibrated model will have a mean prediction close to the true prevalence. A model that has been trained with resampling or class weights will usually have a mean prediction far above the true prevalence — a clear signal that the probabilities need correction before they are used for anything other than ranking.
11 Summary
This tutorial addressed the gap between a probability and a decision — the point at which most classification projects succeed or fail.
- Class imbalance breaks accuracy. With a rare positive class, the trivial all-negative classifier achieves high accuracy while doing nothing useful. Accuracy cannot distinguish between a good model and a useless one.
- The confusion matrix is the foundation. Every useful metric derives from the four counts: TP, FP, FN and TN. Report it before reporting any summary number.
- Precision and recall measure the two kinds of success. Precision is the purity of positive predictions (the cost of false alarms); recall is the coverage of the positive class (the cost of missed cases).
- F1 balances the two. It is the harmonic mean, which is dominated by the smaller of precision and recall — so it is high only when both are reasonably high. The F-beta score allows weighting one more heavily.
- Precision and recall trade off. Lowering the threshold raises recall and lowers precision; raising the threshold does the reverse. This is a property of the decision rule, not the model.
- PR curves are better than ROC curves under severe imbalance. The ROC curve's false positive rate is diluted by the large negative class, while precision is not. When the positive class is rare, plot the PR curve.
- Thresholds should be chosen by cost, not by convention. When the costs of the two errors differ — which is almost always — the optimal threshold is not 0.5. Compute the expected cost at each threshold and pick the minimum.
- Class weights and resampling change the fitting, not just the decision. They can improve the model's ability to separate the classes, but they distort the predicted probabilities.
-
Calibration matters when probabilities are used directly.
If you need
p = 0.7to mean "70% chance," check and correct the calibration. If you only need the ranking, calibration is unnecessary. - The threshold is a decision, not a model parameter. It should be documented, reviewed when the cost structure changes, and owned by whoever is accountable for the consequences.
Before moving to T-07
You should be able to build a threshold table from a set of predictions, compute precision, recall and F1 at each threshold, plot the PR curve, and select a threshold by minimising expected cost. You should also be able to explain, without referring to any formula, why accuracy is the wrong metric for imbalanced data and why the ROC curve can be misleading.
12 Further reading
Core
- Provost & Fawcett — Data Science for Business, Chapter 7. The clearest treatment of the threshold as a business decision, with extensive discussion of cost-benefit analysis and the precision-recall trade-off.
- He & Garcia — "Learning from Imbalanced Data" (IEEE TKDE, 2009). A comprehensive survey of the field, covering metrics, resampling methods and algorithmic approaches to imbalance.
- Saito & Rehmsmeier — "The Precision-Recall Plot Is More Informative than the ROC Plot When Evaluating Binary Classifiers on Imbalanced Datasets" (PLOS ONE, 2015). The definitive empirical demonstration of why PR curves are preferable under imbalance, with clear figures.
Supplementary
-
Chawla, Bowyer, Hall & Kegelmeyer — "SMOTE: Synthetic Minority Over-sampling Technique" (JAIR, 2002).
The original SMOTE paper. Read it for the motivation and the algorithm; use
the
imblearnimplementation in practice. - King & Zeng — "Logistic Regression in Rare Events Data" (Political Analysis, 2001). A widely cited treatment of the specific difficulties of fitting logistic regression when the positive class is rare, including the bias in the estimated intercept.
- Niculescu-Mizil & Caruana — "Predicting Good Probabilities with Supervised Learning" (ICML, 2005). An empirical study of calibration across model families, including logistic regression, SVMs and boosted trees. Useful background for the calibration section.
On metrics and evaluation
- Fawcett — "An Introduction to ROC Analysis" (Pattern Recognition Letters, 2006). The classic tutorial on ROC curves. Read it alongside Saito & Rehmsmeier for a balanced view.
- Brodersen, Ong, Stephan & Buhmann — "The Balanced Accuracy and Its Posterior Distribution" (ICPR, 2010). Introduces balanced accuracy and explains why it is a better default than raw accuracy under imbalance.
- Chicco & Jurman — "The Advantages of the Matthews Correlation Coefficient (MCC) over F1 Score and Accuracy in Binary Classification Evaluation" (BMC Genomics, 2020). Makes the case for MCC as a single-number summary that is robust to imbalance and to class swapping.