Cross-Validation in scikit-learn
The concept you have just studied is the same whether you carry it out by hand or with a library. The next step is seeing how this procedure is carried out in scikit-learn, the Python library that provides a ready-made implementation of cross-validation.
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…
Why One Split Can Mislead
When you build a model, you want to know how well it will perform on data it has never seen. A common first step is to divide your data into a training set, which is used to build the model, and a test set, which is used to measure its accuracy. The trouble is that this measurement depends on which rows happened to land in the test set. A different random split could produce a noticeably different accuracy number. A single split therefore gives you one estimate that may be lucky or unlucky.
Cross-validation addresses this weakness by evaluating the model many times on different splits of the same data. The key idea is that every row in the dataset gets a turn in the test set. No single arrangement of rows decides the final score. Because the evaluation covers the whole dataset across several splits, the resulting picture of performance is more reliable than what any one split can provide. The word generalization points to the goal: you care about how the model will behave on new data, and cross-validation estimates that from the data you already have.
Partitioning Rows into Folds
The most commonly used version is k-fold cross-validation, where k is a number you choose, usually 5 or 10. The first step is always the same: the data is partitioned into k parts of approximately equal size. Each part is called a fold. In five-fold cross-validation the data becomes five folds. In the simplest arrangement, the first fifth of the data forms the first fold, the second fifth forms the second fold, and so on.
The word approximately matters. When the number of rows does not divide evenly by k, the folds cannot all be exactly the same size, so they will be as close as possible. The diagram below uses a small ten-row dataset split into five folds of two rows each. The rows are numbered from 0 to 9 for illustration only.
Rotating the Test Fold
Once the folds exist, a sequence of models is trained, and each model follows the same pattern. One fold is set aside as the test set, and the model is built using the data in all the other folds. The accuracy is then evaluated on the held-out fold and recorded. The next model uses a different fold as its test set, and the process repeats until every fold has been the test set exactly once.
Counting models and tests in the ten-row example
A dataset has 10 rows and is split into 5 folds. How many rows are in each test fold, how many rows are used for training in each round, and how many models are trained in total?
- 1Fold size
10 rows divided into 5 folds gives 2 rows per fold.
- 2Training rows per round
In each round one fold of 2 rows is held out, so the remaining 4 folds contain 8 rows used to build the model.
- 3Rounds
Each fold takes one turn as the test set, so there are 5 rounds.
- 4Models trained
Each round builds one model, so 5 models are trained.
- 5Coverage check
Across the 5 rounds, each of the 10 rows is tested exactly once, so no row is left untested and none is tested twice.
Each round tests 2 rows and trains on 8; five models are trained and every row is tested exactly once.
What do you think happens?
If you run five-fold cross-validation, how many models are trained and how many accuracy values are collected?
Reveal answer
Five models and five accuracy values
Five-fold cross-validation trains one model per fold, and each model produces one accuracy value on its held-out fold, so the counts match.
Calling cross_val_score
In scikit-learn you do not have to write the splitting loop yourself. The function cross_val_score, which lives in the model_selection module, performs the repeated work and returns one score per split. The code below loads a small dataset and evaluates a LogisticRegression model with five folds. The dataset is an illustrative choice; any feature matrix and label array would work the same way.
- 1Lines 1 to 3 import the dataset loader, the model class, and the evaluation function.
- 2Line 5 loads features and labels as two arrays.
- 3Line 6 creates an unfitted model object; the function will make fitted copies of it internally.
- 4Line 8 runs five rounds and returns an array of five scores.
- 5The final line prints the length of the array, which equals the number of folds.
cross_val_scoreis imported from themodel_selectionmodule- X is the feature matrix the model learns from
- y holds the ground-truth labels each prediction is compared against
- cv=5 requests five rounds, one per fold
The first three inputs map directly onto the three things needed to judge a model. The model is the estimator you want to evaluate. The data is the feature matrix the model learns from. The labels are the correct answers that each prediction is compared against. Because the function receives an unfitted model object rather than a trained one, it can create the fitted copies it needs for each split. The cv argument then decides how many of these rounds run.
Changing the cv Parameter
The parameter cv sets the number of folds, and the function runs that many rounds and returns that many scores. The idea is the same at any value of k; only the number of rounds changes. A larger k means more folds, so each fold is smaller and more models are trained. A smaller k means fewer, larger folds. The source describes choosing k as a trade-off: a higher number of folds can give a more robust estimate because the score is averaged over more rounds. The source gives no rule for the best value, so treat k as a choice you make and report.
| Quantity | cv = 5 | cv = 10 |
|---|---|---|
| Number of folds | 5 | 10 |
| Approximate fold size | n divided by 5 | n divided by 10 |
| Models trained | 5 | 10 |
| Length of the score array | 5 | 10 |
| Rows tested per round | About one fifth | About one tenth |
How the output changes when cv goes from 5 to 10, where n is the number of rows in the dataset
Reading the Mean and Spread
A list of fold scores is hard to act on by itself. A common way to summarize cross-validation accuracy is to take the mean, which gives one number estimating average performance. The mean is the sum of the individual scores divided by how many there are.
The source reads the worked result as meaning the model is expected to be around 96 percent accurate on average. The mean gives a single expectation to report, while the individual scores still hold more detail. The mean, however, hides how much the scores differ from one another. In the source's five-score worked example, the scores range from 100 percent down to 90 percent. The source notes that this relatively high variance between folds could mean the model depends heavily on which folds were used for training. It also notes that the same spread could simply be a consequence of the small size of the dataset. The scores alone cannot tell these two explanations apart, so a wide spread is a prompt for further investigation rather than a conclusion.
Common Misunderstandings
Common mistake Believing one cross-validation run is the same as one train-test split
Why it failsA single split produces one estimate that depends on which rows landed in the test set. Cross-validation tests every row once across several rounds, so its picture of performance covers the whole dataset.
Do this insteadThink of cross-validation as a set of splits whose results are combined, not as one split.
Common mistake Assuming the test fold is never used in training
What it looks likeIn round 1 of five-fold cross-validation, fold 1 is held out, but folds 2 to 5 are used to build the model.
Why it failsThe held-out fold is excluded only for that round. Across rounds, every fold serves as training data for some models and as test data for one.
Do this insteadWithin a single round the test fold is excluded; the roles rotate in later rounds.
Common mistake Treating the mean as the only result worth reporting
Why it failsThe mean hides how far apart the fold scores are. The source notes that a high spread may reflect dependence on which folds were used, or simply a small dataset.
Do this insteadReport the mean and read the spread between the individual scores alongside it.
Common mistake Assuming every fold has exactly the same number of rows
What it looks likeTen rows split into four folds cannot all have the same size, because 10 does not divide evenly by 4.
Why it failsThe source says folds are of approximately equal size, and when the row count does not divide evenly by k, they will be as close as possible.
Do this insteadExpect folds to differ by at most a row when the data does not divide evenly.
Common mistake Treating a wide spread as proof that the model is poor, when the source says it could also reflect a small dataset
Common mistake Forgetting that the default number of folds depends on the library version, so the cv argument should be set explicitly
Practice: Predict Before You Run
Keep the same model and data from the earlier code, but change cv from 5 to 3. Before running anything, predict how many models will be trained, how many values will be in the score array, and whether each test fold will hold more or fewer rows than before. Then run the code and check your predictions.
Hints
- Each fold gets one round, so the number of rounds equals cv.
- Fewer folds means each fold is larger, because the same rows are split into fewer parts.
- Print the length of the score array and compare it with your predicted number of models.
Key Takeaways
- A single train-test split gives one estimate that may be lucky or unlucky, while cross-validation evaluates the model on several splits so that every row is tested once.
- In k-fold cross-validation the data is partitioned into approximately equal folds, each fold takes one turn as the test set, and one model and one accuracy value are produced per fold.
- In
cross_val_scorethe model, data, and target arguments supply the estimator, the feature matrix, and the ground-truth labels, while cv sets the number of rounds and scores. - The mean of the fold scores estimates average performance, but the spread between individual scores should be read alongside it, since a wide spread may reflect dependence on the training folds or a small dataset.
- Choose k deliberately and report it, because the source describes k as a trade-off with no fixed best value.