Concepts / Evaluating Classifiers with Cross-Validation

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.

  • Programming
Interactive lab

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

  1. Set 10 test points aside; they take no part in any choice.
  2. Optionally shuffle the 20 development points (seeded), then cut them into k folds (hold-out: one chunk validates, the rest trains).
  3. For every round, train each candidate polynomial on the other folds and measure its validation MSE on the held-out fold.
  4. Average each candidate's fold errors (with repeated shuffling: average the p run scores; p × k fits per candidate).
  5. Select the candidate with the lowest average, retrain it on all development points, and evaluate it once on the test set.
  6. 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.

Educational simulation

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?

  • Close to the accuracy you would get from a random split

  • Somewhat lower than usual, but still clearly above zero

  • Accuracy drops to zero percent

Reveal answer
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.

Fold 1class 0 onlyFold 2class 1 onlyFold 3class 2 only
When rows sorted by class label are cut into three consecutive chunks, which class lands in each fold? Each fold holds exactly one class.

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.

Fold 120 A, 0 BFold 118 A, 2 BFold 420 A, 0 BFold 418 A, 2 BFold 510 A, 10 BFold 518 A, 2 B
How do the class counts in each fold change when moving from consecutive splitting to stratified splitting? Each fold now mirrors the 90 to 10 class ratio.

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.

Worked example

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?

  1. 1
    Count 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.

  2. 2
    Divide 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.

  3. 3
    Check 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.

  4. 4
    Check 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.

Result

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.

Round 1test: fold 1; train: folds2 and 3Round 2test: fold 2; train: folds1 and 3Round 3test: fold 3; train: folds1 and 2next roundnext round
In each of the three rounds, which fold is the test set and which folds form the training set? Every fold is the test set 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 like

    Running three-fold cross-validation on label-ordered iris rows and expecting three fair estimates.

    Why it fails

    The 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 instead

    Check 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 like

    Reporting zero accuracy on iris with consecutive folds and concluding the classifier is useless.

    Why it fails

    The 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 instead

    When 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 like

    Using 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 fails

    That estimate says nothing about class B, which is the minority class the classifier may struggle with.

    Do this instead

    Use 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.

AspectStandard k-foldStratified k-fold
What each fold receivesA consecutive or position-based chunk of rowsA share of every class matching the full dataset ratio
Effect on label-ordered dataCan place a single class in each foldEach fold keeps the class proportions of the whole dataset
Typical useRegression, where the target is continuousClassification, where the target is a set of classes
Reliability for classifiersCan be unreliable when classes are rare or orderedUsually 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

MEDIUM

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.

Related concepts

More concepts starting with E