Machine learning from zero · Lesson 1.2 · 3 of 33 lessons ready · 10 min
Data, features, labels and splits
In short
A dataset is a table of examples, features and labels. Why the test set must stay hidden, and why its size decides how much a score can be trusted.
Warm-up Two questions from earlier lessons. A minute, and it never blocks the lesson.
If a teacher gives a class the exact questions that will appear in the final exam, and everyone scores full marks, what has the exam measured? Memory of those questions, nothing more. Machine learning faces the same problem every single time, and the way it solves it is surprisingly simple: keep some of the questions locked in a drawer.
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: Noticeably: the worst and the best split are several percentage points apart
With 30% in the test set the score ranges from 90.1% to 96.5% (6.4 points), although the model and the data are the same; only which biopsies landed in the test set changes. A single test score is not the whole truth.
Try this
- Set the test-share slider to a small value and then move the seed slider through several positions. Watch how much the test accuracy changes even though the model and the data stay the same.
- Now set the test-share slider to a large value and repeat the seed experiment. Does the test accuracy jump around more or less than before?
- Keep the seed fixed and move the test-share slider from one end to the other. Notice how the number of training rows shrinks as the test set grows.
- Find the seed that gives the best test accuracy — and then ask yourself whether you would be allowed to report that number.
Now that you've tried it, let's see what was actually going on.
The idea in plain words
Almost every dataset in this course is a table. Each row is one example: one tumour, one patient, one passenger, one wine. Each column is a feature: a measured property such as a radius, a blood pressure, an age or an alcohol content. One special column holds the label — the answer we want the model to predict, such as "malignant" or "survived". A model is a rule that maps the features of a row to its label.
Before any learning happens, the rows are shuffled and divided. The bigger part, the training set, is what the model learns from. The smaller part, the test set, is locked away and used once, at the end, to estimate how the model will do on rows it has never seen. It plays the role of the questions in the drawer.
Think of a chef developing a new soup. She tastes it constantly while cooking — that is training. But to know whether customers will like it, she serves it to a few people who have never tasted it before and have no reason to be polite. Their verdict is the test score. If she only asked herself, she would always think the soup was perfect.
Why it works
The test set is useful only because the model never saw it. As long as the training and test rows come from the same source and were split at random, the test rows behave like future cases, and the test accuracy is a fair estimate of future accuracy.
But it is only an estimate, and here is the part beginners rarely hear. The test score depends on which rows happened to land in the test set. Shuffle the data with a different random seed and you get a different test set, and a different score — with exactly the same model and the same data. With a small test set the score can jump around noticeably, because a handful of unusual rows has a big effect on the percentage. Statistics gives a rough size for this wobble. For an accuracy p measured on n test rows, the standard error is about
SE ≈ √(p · (1 − p) / n)
so four times as many test rows only halves the wobble. This is why a single test score is never the whole truth.
There is also a trade-off. Every row you put into the test set is a row the model cannot learn from. A huge test set gives a reliable grade for a model that learned from too little; a tiny test set gives a well-trained model an unreliable grade. Common choices put somewhere between a fifth and a third of the rows in the test set, and the next lessons will show cleverer ways around the dilemma.
Common mistake
The most tempting error is trying many splits and keeping the one with the nicest test score. The test set has then been used to make a decision, and the reported score is optimistic. A quieter version of the same error is called data leakage: information from the test rows sneaks into training, for example when you compute averages for scaling or filling missing values on the whole table before splitting. The rule is strict: split first, then do everything else using the training rows only.
With a clean split in hand we can finally build a real model. In the next lesson we fit the simplest one there is — a straight line through a cloud of points.
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 dataset is a table: rows are examples, columns are features, one column is the label.
- Split before anything else; the model learns from the training set and is graded once on the test set.
- A test score is an estimate: a different random split gives a different number, especially with few test rows.
- Picking the split with the best score, or preparing data on the whole table, leaks the test set into training.
Going further: formula, code, practice
The math
A test accuracy is an average of n right-or-wrong outcomes. If the true accuracy is p, the score you measure varies from split to split with standard error SE ≈ √(p · (1 − p) / n).
nis the number of test rows, not the size of the whole table.SEshrinks with√n: four times as many test rows halve it.- It is largest at
p = 0.5and shrinks aspapproaches 0 or 1. - About two thirds of the scores fall within one
SEofp, and about 95% within two. - This
SEcovers the choice of test rows only. It says nothing about a shift between the data you have and the data you will meet later.
In code (Python)
The lab's setup: logistic regression on the 10 "mean" features, 30% of the biopsies in the test set (171 rows), 20 different splits:
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_breast_cancer(return_X_y=True, as_frame=True)
X = X.filter(like="mean ") # the 10 "mean" features, as in the lab
accs = []
for seed in range(20): # same model, 20 different splits
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, stratify=y, random_state=seed)
model = make_pipeline(StandardScaler(), LogisticRegression()).fit(Xtr, ytr)
accs.append(model.score(Xte, yte))
n, p = len(yte), float(np.mean(accs))
print(f"test rows: {n}")
print(f"test accuracy: min {min(accs):.1%}, max {max(accs):.1%}")
print(f"standard error: {np.sqrt(p * (1 - p) / n):.1%} (n={n}), {np.sqrt(p * (1 - p) / (4 * n)):.1%} (n={4 * n})")
Output
test rows: 171
test accuracy: min 90.6%, max 97.1%
standard error: 1.8% (n=171), 0.9% (n=684)
scikit-learn shuffles differently from the lab, so the minimum and maximum differ slightly from the lab's 90.1% and 96.5%. The 684 is hypothetical: it needs more rows than the 569 in the data, so it only shows the formula. The message is the same: the score moves by several points with the model and data unchanged, and quadrupling the test rows halves the standard error.
Download the notebook (.ipynb). Open it in Jupyter or upload it to Google Colab; it fetches any missing data itself.
For practitioners
- Split first, then fit scalers and imputers on the training rows only. A
Pipelinedoes this for you and keeps the test rows out of every fitted step. - Fix
random_stateso a result can be repeated, but choose it once, before looking at scores. Trying seeds until one looks good is peeking at the test set. - For classification pass
stratify=y, so a rare class does not vanish from a small test set. - Rows that belong together must stay together. Several rows from one patient should all go to the same side, and data with a time order should be split by time, not at random. Otherwise the test set leaks.
- Report a score together with its test size, and for small data repeat the split or use cross-validation (lesson 8) to show the spread.
Was this helpful?
Thanks! This helps us improve the Atlas.
Go deeper in the Atlas
Encyclopedia entries on the ideas in this lesson: