Hello! Welcome to your next lesson in our module on the Fundamentals of Model Validation.
In the last lesson, we established the critical importance of splitting data into training, validation, and test sets. We learned that the validation set is our "mock exam," used for tuning hyperparameters and selecting models. However, we ended with a key question: what if our single validation set is, by chance, unrepresentative of the overall data? A "lucky" split could make a poor model look good, and an "unlucky" one could make a great model look bad.
Today, we'll solve that problem. Your learning outcome is to perform k-fold cross-validation to get a robust estimate of model performance. This technique is a cornerstone of reliable model evaluation and is essential for building the strong, practical foundation you're aiming for.
1. The Problem: High Variance in Performance Estimates
As we discussed, a single train-validation split can lead to a performance score that varies significantly depending on which data points happen to land in the validation set. This is not ideal. We want to be confident that our model's performance score is stable and reliable, not just an artifact of a random split.
Let's start with a video that beautifully illustrates this exact problem.
Selecting the best model in scikit-learn using cross-validation
The video 'Selecting the best model in scikit-learn using cross-validation' from Data School clearly demonstrates why a single train-test split can be misleading. It shows how changing the random_state of a split results in different accuracy scores for the same model.
Please watch from 02:50 to 05:53. Pay close attention to how the testing accuracy changes when the random_state is modified. This highlights the 'high variance estimate' problem that cross-validation solves.
This variability is what we need to overcome. We need a method that gives us a more trustworthy estimate of our model's ability to generalize to unseen data.
2. The Solution: K-Fold Cross-Validation
The solution is to not rely on a single split, but to systematically create multiple validation splits and average the results. This is the core idea behind k-fold cross-validation.
The process works as follows:
- Split: The entire training dataset is divided into 'k' equal-sized segments, or "folds". A common choice for k is 5 or 10.
- Iterate: The process runs for 'k' iterations. In each iteration:
- One fold is held out as a temporary validation set.
- The model is trained on the remaining k-1 folds.
- The model's performance is evaluated on the held-out validation fold.
- Average: After k iterations, we will have k different performance scores. The average of these scores is taken to be the final cross-validated performance of the model.
This approach ensures that every single data point in your training set gets to be in a validation set exactly once, and used for training k-1 times.
The following diagram provides a clear visual of this workflow. A crucial point to note is that k-fold cross-validation is performed on the training data only. The final test set remains untouched until the very end.

By averaging the scores from multiple folds, we smooth out the variations from any single "unlucky" or "lucky" split. This gives us a much more robust and reliable estimate of the model's performance.

3. Implementing K-Fold Cross-Validation in Python
Now let's move from theory to practice. Since you're comfortable with Python, you'll find that scikit-learn makes implementing cross-validation straightforward. We'll explore two ways to do this: the simple, high-level function and the more detailed, "under-the-hood" approach.
The Easy Way: cross_val_score
For most of your work, you'll use the cross_val_score function. It handles the entire k-fold process—splitting, iterating, training, and scoring—in a single line of code.
Let's watch a video that demonstrates this in action.
Machine Learning Tutorial Python 12 - K Fold Cross Validation
The video 'Machine Learning Tutorial Python 12 - K Fold Cross Validation' by codebasics provides a great hands-on walkthrough. We'll first focus on the easy way to perform cross-validation.
Watch the segment from 19:19 to 21:41. This section introduces and demonstrates the cross_val_score function, showing how it simplifies the entire process we just discussed.
As you saw, cross_val_score is incredibly efficient. Here is the core logic in a code block, using the example from the official scikit-learn documentation.
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
# Load a sample dataset
X, y = load_iris(return_X_y=True)
# Create a model instance
clf = SVC(kernel='linear', C=1, random_state=42)
# Perform 5-fold cross-validation
# cv=5 tells the function to use 5 folds
# The function returns an array of scores, one for each fold
scores = cross_val_score(clf, X, y, cv=5)
print(f"Scores for each fold: {scores}")
# Output: Scores for each fold: [0.966... 1. ... 0.966... 0.966... 1. ...]
print(f"Average accuracy: {scores.mean():.2f}")
# Output: Average accuracy: 0.98
print(f"Standard deviation of accuracy: {scores.std():.2f}")
# Output: Standard deviation of accuracy: 0.02
The output gives us not only the average performance (0.98) but also the standard deviation (0.02), which tells us how much the performance varied across the folds. A low standard deviation gives us more confidence in the average score.
The "Under the Hood" View: KFold and StratifiedKFold
To deepen your practical understanding, it's useful to see how you could implement cross-validation manually. This reveals the underlying mechanics that cross_val_score abstracts away. scikit-learn provides iterators like KFold and StratifiedKFold for this purpose.
StratifiedKFold is a variation of KFold that is particularly important for classification tasks. It ensures that each fold has approximately the same percentage of samples of each target class as the complete set. This is crucial for imbalanced datasets. cross_val_score automatically uses StratifiedKFold for classification models.
Let's watch the part of the codebasics video that builds this process from scratch.
Machine Learning Tutorial Python 12 - K Fold Cross Validation
Now, let's look at the manual implementation to see what cross_val_score is doing for us.
Watch the segment from 08:06 to 19:19. The instructor demonstrates how to use the StratifiedKFold object to manually loop through the data, create train/test indices for each fold, and collect scores. This will give you a solid mental model of the process.
Seeing the manual loop with StratifiedKFold makes it clear that cross_val_score is a powerful and convenient helper function for a well-defined, iterative process.
4. Practical Considerations
When using k-fold cross-validation, there are a few practical points to keep in mind.
A Comprehensive Guide to K-Fold Cross Validation
For a concise summary of these points, let's refer to the DataCamp article 'A Comprehensive Guide to K-Fold Cross Validation'.
Please read the sections 'What Does ‘K’ Represent in K-Fold Cross-Validation?' and 'Key Considerations When Using K-Fold Cross-Validation'. These sections provide excellent advice on choosing 'K' and the importance of shuffling.
Here's a summary of the key takeaways from the article:
- Choosing
k:k=5andk=10are the most common choices. They offer a good balance between getting a reliable estimate and the computational cost of training the modelktimes. - Shuffling: If your data has some inherent order (e.g., sorted by class), it's crucial to shuffle it before splitting into folds. Both
KFold(shuffle=True)andcross_val_scorehandle this. This ensures the folds are representative of the overall data distribution. For time-series data, however, you would not shuffle, as the temporal order is meaningful. - Reproducibility: Always set the
random_stateparameter when using shuffling. This guarantees that you get the exact same splits every time you run your code, making your results reproducible.
Conclusion
Today you've added a powerful and essential tool to your model validation toolkit. You've moved beyond a single, potentially fragile validation split to a robust method for estimating model performance.
Key Takeaways:
- A single train-validation split can produce a high-variance performance estimate, meaning the score can change significantly based on the random split.
- K-fold cross-validation solves this by creating
kdifferent train/validation splits and averaging the performance scores, resulting in a more reliable and robust estimate. - The
cross_val_scorefunction inscikit-learnis the most convenient way to perform k-fold cross-validation. - For classification, stratified k-fold is used to ensure each fold maintains the original class distribution.
- Common practice suggests using
k=5ork=10and always setting arandom_statefor reproducibility.
Preview of the next lesson:
With a robust method for evaluating performance in hand, we are now equipped to diagnose some of the most fundamental issues in machine learning. In the next lesson, we will formally define bias and variance and see how they relate to the concepts of underfitting and overfitting. You'll learn how to use the validation scores we generated today to determine if your model is too simple (high bias) or too complex (high variance).