Evaluating Classifiers with Cross-Validation
The accuracy collapses not because the classifier is weak but because the test data and the training data share no classes.
Try it: K-Fold Cross-Validation and Model Selection
How hold-out and k-fold cross-validation choose among candidate models: each fold takes a turn as the validation set, the fold errors are averaged, the lowest average picks the model, and only then is the untouched test set used once — while tuning on the test set would report an optimistic number.
How it works
- Set 10 test points aside; they take no part in any choice.
- Optionally shuffle the 20 development points (seeded), then cut them into k folds (hold-out: one chunk validates, the rest trains).
- For every round, train each candidate polynomial on the other folds and measure its validation MSE on the held-out fold.
- Average each candidate's fold errors (with repeated shuffling: average the p run scores; p × k fits per candidate).
- Select the candidate with the lowest average, retrain it on all development points, and evaluate it once on the test set.
- For contrast, show which candidate the test set itself would have picked — that figure is leaked and optimistic.
Default run (12 steps): 20 development points (sorted by x as they arrived) and 10 test points set aside. Candidates: polynomial degree 0, 1, 2, 3, 4, 5, 6. Plan: 5-fold cross-validation, shuffled with seed 1 → 5 fits per candidate (p × k = 1 × 5), 35 in total. … 5-fold cross-validation picks degree 3 (score 0.0768); its honest test MSE is 0.0889. Picking by test error would report degree 4 at 0.0868 — a leaked, optimistic figure.
Simplified: One fixed toy dataset (20 development + 10 test points from sin(2πx) with noise) and polynomial least squares of degree 0–6 as the candidate models. Shuffling uses a seeded mulberry32 Fisher–Yates; folds are contiguous chunks like scikit-learn's KFold. Hold-out uses the first of k chunks as the validation set.
Loading the simulation…
A Belief About Splitting That Breaks
Many people first meet k-fold cross-validation with a reasonable-sounding belief: if you cut a dataset into k pieces, each piece is a fair miniature of the whole. Under that belief, only the number of folds matters, and the order of the rows is a detail you can ignore. This article tests that belief on the iris dataset, which has three classes of flower, and shows where it breaks.
What do you think happens?
The iris target labels are stored in order: all class 0 samples first, then all class 1, then all class 2. You run three-fold cross-validation by taking the first third of the rows as fold 1, the middle third as fold 2, and the last third as fold 3. What accuracy do you expect the classifier to report?
Reveal answer
Accuracy drops to zero percent.
Each test fold contains a class the training set has never seen, so the classifier cannot predict it correctly. The failure comes from how the rows were divided, not from the model. Because a good classifier can do far better than zero on iris, a procedure that reports zero is not telling you anything useful about the classifier.
Splitting Label-Ordered Rows
The belief fails most dangerously when the rows are not in random order. Many datasets are stored grouped by label, so all the samples of one class sit together, followed by all the samples of the next class. When you split such a dataset into consecutive chunks, each chunk may contain only a slice of the classes rather than a sample of all of them.
The simple strategy of taking the first third, the second third, and the last third treats row position as if it carried no information. But in a label-ordered dataset, position is the label. Splitting by position turns the label ordering into a fold structure: each fold inherits whatever classes happen to occupy its position. The folds end up holding very different mixtures of classes, and in the iris case each fold is a single class, so no fold can represent the whole dataset.
Trace what this means for evaluation. When fold 1 is the test set, the training set contains only classes 1 and 2, so the classifier has never seen class 0. Every test sample belongs to a class absent from training, so every prediction is wrong. The same thing happens in the other rounds. The accuracy collapses not because the classifier is weak but because the test data and the training data share no classes.
What Stratification Guarantees
Stratified k-fold cross-validation fixes this by building each fold so that the proportions between classes match the proportions in the full dataset. Under standard splitting on ordered labels, each fold is one class. Under stratified splitting, each fold is built so that its class proportions match those of the full dataset. The difference is not in how many folds exist or how many samples each fold holds. It is in what each fold is allowed to contain.
The key word is proportions. Stratification does not promise that every fold has the same number of samples, and it does not change the rule that each fold takes a turn as the test set. It promises that whatever mix of classes exists in the full dataset is reproduced, as closely as the counts allow, inside every fold. The source describes the same idea with a 90 and 10 percent split: in each fold, 90 percent of the samples belong to class A and 10 percent belong to class B.
The next example uses a dataset we construct for illustration. It has 100 samples, 90 of class A and 10 of class B, stored with all class A rows first. Five folds means 20 samples per fold. The diagram below compares the class counts in three of the five folds under plain consecutive splitting and under stratified splitting.
Under consecutive splitting, folds 1 through 4 hold only class A, so a test fold among them contains no class B examples at all. Fold 5 holds the class B samples and no class B samples appear elsewhere in its position. Under stratified splitting, every fold holds 18 class A and 2 class B samples, which is the same 90 to 10 ratio as the whole dataset. Now every test fold gives some information about how the classifier handles class B.
Working Out Expected Class Counts
You can predict the class counts in each fold before running any code. If a class has $n_c$ samples in the full dataset and you use $k$ folds, stratification aims for each fold to hold about $\frac{n_c}{k}$ samples of that class. The counts only match exactly when $n_c$ divides evenly by $k$; otherwise the fold sizes differ by at most one sample, as closely as the counts allow.
Expected Counts for the 90 and 10 Dataset
A dataset has 100 samples: 90 of class A and 10 of class B. Stratified five-fold cross-validation is used. How many samples of each class should each fold contain, and how many samples in total?
- 1Count the samples per class
The full dataset has $n_A = 90$ samples of class A and $n_B = 10$ samples of class B, for 100 in total.
- 2Divide each class count by the number of folds
With $k = 5$ folds, class A gives $\frac{90}{5} = 18$ samples per fold, and class B gives $\frac{10}{5} = 2$ samples per fold.
- 3Check the total fold size
Each fold holds $18 + 2 = 20$ samples, which equals $\frac{100}{5}$, so the folds are equal in size as well.
- 4Check the proportion
In each fold, $\frac{18}{20} = 0.9$ of the samples are class A and $\frac{2}{20} = 0.1$ are class B, matching the 90 to 10 ratio of the full dataset.
Each fold should contain 18 samples of class A and 2 samples of class B, for 20 samples in total.
Rotating the Test Fold Across Rounds
Stratified and standard k-fold share the same rotation. In each of k rounds, one fold serves as the test set and the remaining folds form the training set. Each fold, used in turn as the test set, produces one estimate, and the estimates are combined. Because every fold takes exactly one turn as the test set, every sample is tested exactly once.
Stratification changes what is inside each fold, not this rotation. If the test fold in round 2 is stratified, it carries its share of every class, so the estimate from that round reflects all classes. This is why the combined result is more trustworthy: each round's estimate comes from a test set that represents the dataset.
Mistakes When Reading Fold Estimates
The following mistakes come up often when people first apply cross-validation to classifiers.
Common mistake Assuming the number of folds is the only thing that matters
What it looks likeRunning three-fold cross-validation on label-ordered iris rows and expecting three fair estimates.
Why it failsThe row order decides which classes land in each fold. Two datasets with the same number of folds can produce very different test sets.
Do this insteadCheck the label ordering, and use stratified k-fold when the rows are not in random order.
Common mistake Treating a zero or very low score as a verdict on the model
What it looks likeReporting zero accuracy on iris with consecutive folds and concluding the classifier is useless.
Why it failsThe zero came from the split, since the test folds contain classes the training folds never saw. A capable classifier can do far better on the same data.
Do this insteadWhen a score looks implausible, inspect the class counts in each fold before changing the model.
Common mistake Ignoring rare classes in a test fold
What it looks likeUsing a consecutive fold among the first four folds of the 90 and 10 dataset as the test set, which contains no class B samples.
Why it failsThat estimate says nothing about class B, which is the minority class the classifier may struggle with.
Do this insteadUse stratified folds so every test set includes a share of each class.
Common mistake Expecting stratification to make every fold the same size
Standard k-Fold Versus Stratified k-Fold
For evaluating a classifier, stratified k-fold usually gives more reliable estimates of generalization performance, especially when some classes are rare. Standard k-fold has a different default role in scikit-learn. The comparison below summarizes the two strategies.
| Aspect | Standard k-fold | Stratified k-fold |
|---|---|---|
| What each fold receives | A consecutive or position-based chunk of rows | A share of every class matching the full dataset ratio |
| Effect on label-ordered data | Can place a single class in each fold | Each fold keeps the class proportions of the whole dataset |
| Typical use | Regression, where the target is continuous | Classification, where the target is a set of classes |
| Reliability for classifiers | Can be unreliable when classes are rare or ordered | Usually more reliable, especially for rare classes |
Standard and stratified k-fold compared for classification evaluation
Scikit-learn uses standard k-fold cross-validation by default for regression. The source notes that one could try to make each fold representative of the different values a regression target takes, but this is not a commonly used strategy and would surprise most users. Stratification is defined in terms of class labels, so it applies to classification, where it is the usual choice for evaluating a classifier.
Practice: Counts for a Different Ratio
A dataset has 60 samples: 40 of class X and 20 of class Y. You use stratified four-fold cross-validation. How many samples of each class should each fold contain, how many samples are in each fold in total, and what fraction of each fold is class X?
Hints
- Divide the class X count by the number of folds to get its per-fold count.
- Do the same for class Y, then add the two per-fold counts to get the fold size.
- Divide the class X per-fold count by the fold size to get the fraction.
Key Takeaways
- Splitting label-ordered rows into consecutive folds can place a single class in each fold, so training and test sets may share no classes and accuracy can collapse, as in the three-fold iris example.
- Stratified k-fold builds each fold so that its class proportions match the full dataset, though it does not guarantee identical fold sizes.
- Expected per-fold class counts follow from dividing each class count by the number of folds, as in 90 class A and 10 class B split into five folds giving 18 and 2 per fold.
- Stratified k-fold is usually preferred for evaluating classifiers, especially with rare classes, while scikit-learn uses standard k-fold by default for regression.