Skip to course content
Free PyTorch course

Advanced Deep Learning with PyTorch

Unit 12.04: Error analysis and responsible-use boundary

The threshold is a decision about which mistake you prefer. Making it explicitly is part of the deliverable.

Choosing where to cut

Lowering the threshold catches more true positives and produces more false alarms. Raising it does the reverse. There is no neutral setting — 0.5 is simply the choice you make by not choosing.

When a missed case costs more than a false alarm, favour recall:

import json

import torch
from torch import nn
from sklearn.metrics import confusion_matrix

torch.manual_seed(0)
X = torch.randn(700, 5)
y = ((X[:, 0] + X[:, 1]) > 0).float().unsqueeze(1)
Xtr, ytr, Xte, yte = X[:550], y[:550], X[550:], y[550:]

model = nn.Sequential(nn.Linear(5, 32), nn.ReLU(), nn.Linear(32, 1))
opt = torch.optim.Adam(model.parameters(), lr=0.01)
for _ in range(400):
    opt.zero_grad()
    nn.BCEWithLogitsLoss()(model(Xtr), ytr).backward()
    opt.step()

with torch.no_grad():
    probs = torch.sigmoid(model(Xte)).squeeze(1)

# The threshold is a decision, not a default. Missing a at-risk learner costs
# more than contacting one unnecessarily, so favour recall.
print(f"{'threshold':>10} {'recall':>8} {'precision':>10} {'flagged':>8}")
for t in (0.3, 0.5, 0.7):
    pred = (probs > t).float()
    tn, fp, fn_, tp = confusion_matrix(yte.numpy().ravel(), pred.numpy().ravel()).ravel()
    recall = tp / (tp + fn_) if tp + fn_ else 0
    precision = tp / (tp + fp) if tp + fp else 0
    print(f"{t:>10} {recall:>8.3f} {precision:>10.3f} {int(pred.sum()):>8}")

print(json.dumps({
    "chosen_threshold": 0.3,
    "why": "a missed at-risk learner costs more than an unnecessary contact",
    "must_not_be_used_for": ["grading", "admission", "any automated decision without review"],
    "human_in_the_loop": "every flag is reviewed before contact",
}, indent=2))

The table shows recall and precision moving in opposite directions as the threshold changes, with the number flagged alongside — because that column is the operational cost of the decision.

The why field records the reasoning, so a future reader can challenge the trade-off rather than guessing at it.

The mistake this prevents

Reporting a single accuracy at the default threshold. It hides the trade-off entirely and implies a choice was made on evidence when none was made at all.

Takeaway

State the threshold, the reason for it, and what the model must not be used to decide.