Everyone Can Learn Program
中文 Start learning
Specialty · AILesson 5 of 6Free to read

Measuring a model · AI Foundations

Your model is 95% accurate. Is it any good?

Course contents

Why you need it

A single score can hide a useless model. If only a few cases are the ones you care about, such as fraud or a disease, a model that always says "no" looks excellent and catches nothing. Choosing the right measure, and checking it on unseen data, is how you tell a real model from one that only looks good.

The intuition

Imagine 5 frauds in 100 transactions. A model that always predicts "not fraud" is right 95 times: accuracy 95%, frauds caught 0.

Split the results into four boxes, the confusion matrix (1 = fraud, the "positive" class):

predicted 1predicted 0
actual 1true positive (TP)false negative (FN)
actual 0false positive (FP)true negative (TN)

Two questions then matter:

  • Precision = TP / (TP + FP): of the cases we flagged, how many were real?
  • Recall = TP / (TP + FN): of the real cases, how many did we catch?

They pull against each other. Flag everything and recall is perfect but precision is terrible. F1 = 2 × P × R / (P + R) combines them into one number that's only high when both are.

Finally, overfitting: a model can learn its training rows by heart, noise and all. The sign is a big gap, such as 99% on training data and 60% on the test set.

Definition

Accuracy

The share of all predictions that were right. Misleading when one class is rare.

Precision

Of the cases predicted positive, the share that really were: TP / (TP + FP).

Recall

Of the real positive cases, the share the model found: TP / (TP + FN).

Overfitting

Learning the training data so closely, noise included, that the model does worse on new data.

Examples

The accuracy trap

Try it yourself

Always saying "no" scores 95% and catches nothing.

actual = [0] * 95 + [1] * 5
always_no = [0] * 100
correct = sum(1 for a, p in zip(actual, always_no) if a == p)
print("accuracy:", correct / len(actual))
caught = sum(1 for a, p in zip(actual, always_no) if a == 1 and p == 1)
print("fraud caught:", caught, "of", actual.count(1))
Output
accuracy: 0.95
fraud caught: 0 of 5
Step by step
  1. L195 normal transactions, 5 frauds (made-up data).
  2. L495 of 100 right.accuracy: 0.95
  3. L6Recall is 0: not one fraud found.fraud caught: 0 of 5

Confusion matrix

Try it yourself

Count the four boxes, then precision and recall.

actual    = [1, 1, 1, 0, 0, 0, 0, 1, 0, 0]
predicted = [1, 0, 1, 1, 0, 0, 0, 1, 0, 1]
pairs = list(zip(actual, predicted))
tp = pairs.count((1, 1))
fp = pairs.count((0, 1))
fn = pairs.count((1, 0))
tn = pairs.count((0, 0))
print("TP", tp, "FP", fp, "FN", fn, "TN", tn)
print("precision", tp / (tp + fp))
print("recall", tp / (tp + fn))
Output
TP 3 FP 2 FN 1 TN 4
precision 0.6
recall 0.75
Step by step
  1. L3Each pair is (actual, predicted).
  2. L5(0, 1): we said yes, it was no.
  3. L93 of the 5 we flagged were real.precision 0.6
  4. L10We caught 3 of the 4 real ones.recall 0.75

A model that memorises

Try it yourself

Perfect on its training rows, a coin flip on new ones.

train = {(1, 1): "red", (2, 1): "red", (8, 8): "blue", (9, 8): "blue"}
test = {(1, 2): "red", (8, 9): "blue"}

def memoriser(point):
    return train.get(point, "red")

def accuracy(model, data):
    return sum(model(p) == label for p, label in data.items()) / len(data)

print("train", accuracy(memoriser, train))
print("test", accuracy(memoriser, test))
Output
train 1.0
test 0.5
Step by step
  1. L4Look the point up; if it's new, just guess red.
  2. L10Every training point is in the table.train 1.0
  3. L11(8, 9) is clearly blue, but it's not in the table.test 0.5

Common mistakes

Reporting only accuracy

With a rare class, accuracy is high even for a useless model. Report precision and recall for the class you care about.

Dividing by zero

A model that never predicts positive has TP + FP = 0. Decide what precision means then (usually 0) instead of crashing.

Tuning on the test set

If you try 50 settings and keep the best test score, the test set has become training data. Use a separate validation set for tuning.

Quick quiz

1. What does this print?

actual    = [1, 0, 1, 1]
predicted = [1, 1, 0, 1]
tp = sum(1 for a, p in zip(actual, predicted) if a == 1 and p == 1)
fp = sum(1 for a, p in zip(actual, predicted) if a == 0 and p == 1)
print(round(tp / (tp + fp), 2))
  1. A
    0.67
  2. B
    0.5
  3. C
    0.75
Show the answer

Answer: A

TP = 2, FP = 1: precision 2 / 3 ≈ 0.67.

2. A spam filter must almost never send a real email to spam. Which number matters most?

  1. APrecision of the "spam" label
  2. BRecall of the "spam" label
  3. CAccuracy on the training emails
Show the answer

Answer: A

Precision asks: of the emails we called spam, how many really were? A false positive is a lost real email.

3. Training accuracy is 99%, test accuracy is 60%. What's going on?

  1. AOverfitting
  2. BThe learning rate is too small
  3. CThe test set is too easy
Show the answer

Answer: A

The model learned the training rows, not the pattern.

Practice

3 exercises in three steps: predict what a program prints, change a program to meet a new requirement, then write one from scratch. Your code runs in the browser and is checked the moment you submit.

  1. PredictCount the boxes

    Type exactly what this prints.

  2. ModifyFix recall

    recall uses the wrong box. Fix it to TP / (TP + FN). When there are no real positives at all (TP + FN is 0), return 0.0.

  3. WriteA full report

    Write report(actual, predicted) (lists of 0 and 1) that returns a dictionary with "precision", "recall" and "f1", each rounded to 3 decimals.

    • any measure whose bottom part is 0 is 0.0
    • F1 = 2 × P × R / (P + R), from the unrounded P and R
    report([1, 1, 1, 0, 0, 0, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0, 0, 1, 0, 1])
    # {'precision': 0.6, 'recall': 0.75, 'f1': 0.667}

Practise this lesson

Open the interactive lesson to edit and run these examples and solve the exercises with instant feedback. Free to start, no sign-up.

Interactive lessons open in order. If you have not done the earlier ones yet, you start at the course map.

Terms in this lesson

TermChineseDefinition
Accuracy准确率The share of predictions that were right.
Confusion matrix混淆矩阵Counts of TP, FP, FN and TN.
Precision精确率TP / (TP + FP): how many flagged cases were real.
Recall召回率TP / (TP + FN): how many real cases were found.
Overfitting过拟合Doing well on training data and badly on new data.