Machine learning from zero · Lesson 1.3 · 4 of 33 lessons ready · 12 min
Baselines: what do you compare your model with?
In short
Before praising a model, compute the score without learning: the top class or the mean. When the sick are rare, “always healthy” scores high and finds no one.
Warm-up Two questions from earlier lessons. A minute, and it never blocks the lesson.
In lesson 0.1 the tree got 95.1% of the penguins right and guessing got 43.7%. That second number is the baseline: the score of an answer that learns nothing. Without it you cannot tell whether a model has learned anything. Today you will see how to compute it in two tasks and when accuracy alone fools you. The data: 569 breast tumour biopsies and 442 patients with diabetes.
Choose an answer and how sure you are.
Answer to unlock the lab.
Interactive lab
This interactive lab runs in a browser with JavaScript enabled. The text around it describes what the lab shows.
Show the answer
Correct answer: About 99%, more than the learned rule, and it finds none at all
107 of 108 biopsies is 99.1% accuracy, and the malignant one slips through. The learned one-threshold rule scores 90.7% on this test, less, but it does find that malignant biopsy. On the full test, with 64 malignant, “always benign” gets only 62.6%.
Try this
- Start with the biopsies and all 64 malignant ones. By how much does the learned rule beat “always benign”?
- Move the slider right until there are 5 malignant biopsies, then 1. What happens to the accuracy of “always benign”, and what happens to the number of malignant biopsies found?
- Switch to diabetes. Compare the error of the line on BMI and of the model with 10 measurements with the error of the mean alone.
Once you have checked it in the lab, let us name what you see.
The idea in plain words
A baseline is the simplest answer you can give without learning. In classification it is the most common class: of the 398 learning biopsies 250 are benign, so the answer is always “benign”. In regression it is the mean: every patient gets the same predicted disease progression, the average of the learning patients.
A model makes sense only when it clearly beats the baseline on the same test data. On the biopsies the rule with one measurement and one threshold gets 91.2% against 62.6%. In diabetes the model with 10 measurements has an error of 2827 against 5076 for the mean, 44.3% lower. A line on BMI alone lowers the error by only 19.3%.
There is a weaker baseline too: guessing in proportion, that is “benign” with a chance equal to the share of benign biopsies among the learning ones. On average it gets 53.2%, less than “always benign”. That is why the most common class is the baseline to use: random guessing is easier to beat than real understanding.
Jak to policzono
- Biopsies: Breast Cancer Wisconsin (Diagnostic), UCI, licence CC BY 4.0. 569 biopsies (357 benign, 212 malignant), 10 measurements of the cell nuclei.
- Diabetes: the Diabetes dataset (Efron et al., 2004) shipped with scikit-learn; the authors gave no licence. 442 patients, 10 measurements, disease progression a year later.
- Split 70/30, the same as
train_test_split(test_size=0.3, random_state=1)in scikit-learn; biopsies stratified. The test has 171 biopsies and 133 patients. - Rule: a decision tree with one question (CART). Regression model: least squares.
Why it works
The accuracy of “always the most common class” is simply that class’s share of the test. On the full test 107 of 171 biopsies are benign, hence 62.6%. Keep 1 malignant biopsy and the benign ones are 107 of 108, hence 99.1%. The baseline’s accuracy says nothing about the biopsies. It only says how rare the other class is.
That is why with a rare class accuracy no longer separates a good model from a useless one. With 5 malignant biopsies in the test “always benign” gets 95.5% and the rule 91.1%, although only the rule finds all 5. This is not one lucky split: on 100 different splits “always benign” beats the rule on accuracy in 82. What helps is a second number next to accuracy: how many cases of the rare class the model actually found.
In regression the mean is the best constant answer: no other single number gives a lower mean squared error on the learning data. Any model that has measurements should beat it, and here it always does. On 100 splits the line on BMI and the model with 10 measurements have a lower error than the mean every time, on average 33.7% and 48.5% lower.
Common mistake
True or false: “90% accuracy is a lot”. False, or rather: the number alone does not tell you. When 1 person in 100 is sick, the test “always healthy” has 99% accuracy and finds no one. A model with 90% would then be worse than nothing on accuracy, yet it could be very valuable if it finds the sick. Always report the baseline next to the score and check how many cases of the rare class the model found.
Where the analogy breaks down: a baseline is a floor, not a goal. Beating it by a hair usually means nothing, because another split of the data can turn the result around.
Quiz
Three questions to check yourself. Pick an answer, or open the answer under a question. Keyboard: arrow keys choose, Enter or Space confirms.
Key takeaways
- A baseline is the score without learning: the most common class in classification, the mean in regression.
- You compare a model with the baseline on the same test data, not with zero.
- When a class is rare, “always the common class” has high accuracy and finds no one; also report how many rare cases the model found.
- Check the lead on many splits, because one can come out well by chance.
Going further: formula, code, practice
The math
The accuracy of the answer “always class k” is that class’s share of the test: accuracy = n_k / n. On the full test 107 / 171 ≈ 0.626, with one malignant biopsy 107 / 108 ≈ 0.991.
Guessing “benign” with probability p (the share of benign among the learning biopsies, 250 / 398 ≈ 0.628) is right on average p · q + (1 − p) · (1 − q) of the time, where q is the share of benign biopsies in the test. On the full test that is about 0.532.
In regression a constant answer c has the error MSE(c) = (1/n) · Σ (yᵢ − c)². Its derivative −(2/n) · Σ (yᵢ − c) is zero at c = ȳ, so the mean gives the lowest error of all constants. The relative improvement is 1 − MSE(model) / MSE(mean): for 10 measurements 1 − 2827 / 5076 ≈ 0.443.
In code (Python)
The same experiment in scikit-learn: the baseline and the one-threshold rule on the biopsies with 64, 5 and 1 malignant biopsies in the test, the comparison over 100 splits, then the mean, the line on BMI and the model with 10 measurements on diabetes.
import numpy as np
from sklearn.datasets import load_breast_cancer, load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LinearRegression
X, y = load_breast_cancer(return_X_y=True)
X = X[:, :10] # the 10 "mean" measurements, as in the lab; y: 0 = malignant, 1 = benign
def biopsies(seed, keep_malignant):
tr, te = train_test_split(np.arange(len(y)), test_size=0.3, stratify=y, random_state=seed)
te = np.sort(te) # test rows in file order, as in the lab
major = np.bincount(y[tr]).argmax() # baseline: the most common class among the learning biopsies
rule = DecisionTreeClassifier(max_depth=1, random_state=0).fit(X[tr], y[tr]) # one measurement, one threshold
rows = np.r_[te[y[te] == 1], te[y[te] == 0][:keep_malignant]] # every benign + the first m malignant
pred = rule.predict(X[rows])
return (y[rows] == major).mean(), ((major == 0) & (y[rows] == 0)).sum(), (pred == y[rows]).mean(), ((pred == 0) & (y[rows] == 0)).sum()
for m in (64, 5, 1):
base, base_found, acc, found = biopsies(1, m)
print(f"malignant {m}: always benign {base:.3f} (finds {base_found}), rule {acc:.3f} (finds {found})")
wins = sum(biopsies(s, 5)[0] > biopsies(s, 5)[2] for s in range(100))
print(f"100 splits, 5 malignant: always benign beats the rule in {wins}")
Xd, yd = load_diabetes(return_X_y=True)
def diabetes(seed):
a, b, c, e = train_test_split(Xd, yd, test_size=0.3, random_state=seed)
mse = lambda p: ((e - p) ** 2).mean()
return mse(c.mean()), mse(LinearRegression().fit(a[:, [2]], c).predict(b[:, [2]])), mse(LinearRegression().fit(a, c).predict(b))
mean, bmi, full = diabetes(1)
print(f"diabetes: mean {mean:.0f}, BMI {bmi:.0f} ({1 - bmi / mean:.1%} lower), all 10 {full:.0f} ({1 - full / mean:.1%} lower)")
r = np.array([diabetes(s) for s in range(100)])
print(f"100 splits: BMI beats the mean in {(r[:, 1] < r[:, 0]).sum()}, all 10 in {(r[:, 2] < r[:, 0]).sum()}; error lower by {1 - r[:, 1].mean() / r[:, 0].mean():.1%} and {1 - r[:, 2].mean() / r[:, 0].mean():.1%} on average")
Output
malignant 64: always benign 0.626 (finds 0), rule 0.912 (finds 59)
malignant 5: always benign 0.955 (finds 0), rule 0.911 (finds 5)
malignant 1: always benign 0.991 (finds 0), rule 0.907 (finds 1)
100 splits, 5 malignant: always benign beats the rule in 82
diabetes: mean 5076, BMI 4096 (19.3% lower), all 10 2827 (44.3% lower)
100 splits: BMI beats the mean in 100, all 10 in 100; error lower by 33.7% and 48.5% on average
On split 1 the numbers are the same as in the lab. The lab’s 10-measurement model works on data rounded to two decimal places, so its error can differ from this code by a fraction, but it rounds to the same 2827.
Download the notebook (.ipynb). Open it in Jupyter or upload it to Google Colab; it fetches any missing data itself.
For practitioners
- In scikit-learn the baseline comes from
DummyClassifier(strategy="most_frequent")andDummyRegressor(strategy="mean"). Compute it on the same split as the model. - With imbalanced classes report the rare class’s recall or the balanced accuracy next to accuracy; “always the common class” has a balanced accuracy of 50%.
- A stronger baseline is often a simple one-measurement rule or the model the company already uses. A new model has to beat the best of them.
- When the lead over the baseline is small, check it on many splits or with cross-validation before you announce it.
Was this helpful?
Thanks! This helps us improve the Atlas.
Go deeper in the Atlas
Encyclopedia entries on the ideas in this lesson: