Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 38

GridSearchCV for Hyperparameter Tuning

Recommended resources

Hello! Welcome to our second lesson on Model Tuning and Selection.

In our previous lesson, we established the crucial difference between model parameters (learned from data) and hyperparameters (set before training). You learned that choosing the right hyperparameters is key to controlling a model's complexity and achieving the best possible performance. This naturally leads to a practical question: how do we find these "best" values?

Today, we'll answer that question. Our goal is to learn how to tune model hyperparameters systematically using GridSearchCV. Instead of manually testing combinations through trial and error, you will learn to use a powerful tool from scikit-learn that automates this entire process, ensuring you find the optimal settings in a robust and reproducible way. This is a fundamental skill for any data scientist building high-performing models.

1. The Challenge of Manual Tuning

Imagine you want to tune a K-Nearest Neighbors (KNN) model. You need to choose the best value for n_neighbors. You could try a value of 3, train the model, evaluate it, then try 5, train, evaluate, and so on. Now, what if you also wanted to tune the weights hyperparameter ('uniform' vs. 'distance')? You'd have to test every combination:

  • n_neighbors=3, weights='uniform'
  • n_neighbors=3, weights='distance'
  • n_neighbors=5, weights='uniform'
  • ...and so on.

You could write for loops to automate this, but it quickly becomes messy and error-prone, especially if you add more hyperparameters. This manual approach also makes it hard to get a reliable performance estimate.

To see just how cumbersome this is, let's watch a short segment of a video that demonstrates this manual process before introducing a better way.

Machine Learning Tutorial Python - 16: Hyper parameter Tuning (GridSearchCV)

The video 'Machine Learning Tutorial Python - 16: Hyper parameter Tuning (GridSearchCV)' from the channel codebasics starts by showing the exact problem we're discussing: trying to tune an SVM model manually using for loops.

Watch from 01:52 to 04:53. Pay close attention to how the presenter uses k-fold cross-validation within loops to test different values for the kernel and C hyperparameters. Notice how this code would become complicated if a third or fourth hyperparameter were added.

As you can see, this manual method isn't scalable. We need a more systematic and automated solution. That solution is GridSearchCV.


2. How GridSearchCV Works

GridSearchCV stands for Grid Search Cross-Validation. The name perfectly describes what it does: it searches over a "grid" of hyperparameters using cross-validation.

Here’s the process broken down:

  1. Define a "Grid" of Hyperparameters: You specify which hyperparameters you want to tune and which values you want to test for each. This is defined in a Python dictionary, where keys are the hyperparameter names and values are lists of the values to try. This dictionary forms your search "grid".

  2. Exhaustive Search: GridSearchCV then methodically tries every single possible combination of the hyperparameter values you defined.

  3. Cross-Validation: For each combination, it evaluates the model's performance using k-fold cross-validation. This means it doesn't just train and test once, but multiple times on different splits of your training data, giving you a much more robust estimate of that combination's performance.

  4. Identify the Best: After testing all combinations, GridSearchCV simply identifies the combination of hyperparameters that produced the best average cross-validation score.

To get a deeper understanding of this process, please read the following article.

Tuning Random Forest with Grid Search

The article 'Tuning Random Forest with Grid Search' from the Train in Data blog provides an excellent conceptual explanation of how Grid Search operates.

Read the sections titled 'Grid Search' and 'Cross-validation'. Focus on understanding what a parameter grid is and how the total number of model fits is calculated (number of combinations × number of CV folds).

The key takeaway is that GridSearchCV automates the tedious, brute-force search process while integrating the robust evaluation method of cross-validation.


3. Implementing GridSearchCV with Scikit-Learn

Now let's move from theory to practice. Using GridSearchCV in scikit-learn involves four main steps. The following video demonstrates this entire workflow.

Machine Learning Tutorial Python - 16: Hyper parameter Tuning (GridSearchCV)

Let's return to the codebasics video. Having established the problem with manual tuning, the presenter now shows how to solve it elegantly using GridSearchCV.

Watch from 04:53 to 07:18. Observe the four key steps: importing GridSearchCV, defining the parameter grid dictionary, instantiating GridSearchCV with the model and the grid, and finally, calling .fit().

Let's solidify this with our own code example. We'll tune a KNeighborsClassifier on a simple dataset.

import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris




# Load a sample dataset
iris = load_iris()
X, y = iris.data, iris.target




# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)




# 1. Instantiate the model you want to tune
knn = KNeighborsClassifier()




# 2. Define the parameter grid
# The keys are the hyperparameter names as strings
# The values are the lists of settings to try
param_grid = {
    'n_neighbors': [3, 5, 7, 9, 11],
    'weights': ['uniform', 'distance'],
    'metric': ['euclidean', 'manhattan']
}




# 3. Instantiate GridSearchCV
# estimator: the model to tune
# param_grid: the grid of hyperparameters
# cv: the number of cross-validation folds
# scoring: the metric to optimize (e.g., 'accuracy', 'roc_auc')
# n_jobs=-1: use all available CPU cores to speed up computation
grid_search = GridSearchCV(
    estimator=knn, 
    param_grid=param_grid, 
    cv=5, 
    scoring='accuracy',
    n_jobs=-1
)




# 4. Fit the GridSearchCV object to the training data
# This will start the search process
print("Starting Grid Search...")
grid_search.fit(X_train, y_train)
print("Grid Search complete.")

In this example, GridSearchCV will test 5 (n_neighbors) * 2 (weights) * 2 (metric) = 20 different hyperparameter combinations. Since we set cv=5, it will train and evaluate a model 20 * 5 = 100 times to find the best settings.


4. Interpreting the Results

Once the .fit() process is complete, the GridSearchCV object contains all the information we need. The most important attributes are:

  • grid_search.best_params_: A dictionary containing the hyperparameter combination that gave the best score.
  • grid_search.best_score_: The average cross-validation score achieved by the best parameters.
  • grid_search.best_estimator_: A model object that has been automatically refit on the entire training set using the best parameters found. This is the final, tuned model that you will use for predictions.
  • grid_search.cv_results_: A dictionary with detailed results from every single run. This is very useful for deeper analysis.

Let's see how to access and analyze these results.

Machine Learning Tutorial Python - 16: Hyper parameter Tuning (GridSearchCV)

The final part of the codebasics video shows exactly how to extract the most useful information from the fitted GridSearchCV object.

Watch from 07:18 to 10:14. Notice how you can easily access the best score and parameters. Pay special attention to how cv_results_ is loaded into a pandas DataFrame, which makes it much easier to inspect and compare the performance of different combinations.

Let's apply this to our code example:




# Print the best parameters found
print("Best Hyperparameters:", grid_search.best_params_)




# Print the best cross-validation score
print(f"Best CV Score: {grid_search.best_score_:.4f}")




# The best_estimator_ is the final model, ready for prediction
best_knn = grid_search.best_estimator_
test_accuracy = best_knn.score(X_test, y_test)
print(f"Test Set Accuracy with Best Model: {test_accuracy:.4f}")




# For deeper analysis, convert cv_results_ to a DataFrame
results_df = pd.DataFrame(grid_search.cv_results_)
print("\nGrid Search Results (first 5 rows):")



# Display relevant columns
print(results_df[['param_n_neighbors', 'param_weights', 'param_metric', 'mean_test_score']].head())

Visualizing the results from cv_results_ can also be very insightful. A heatmap, for example, can show how two hyperparameters interact to affect performance.

Grid Search Mean Test Scores Heatmap
This heatmap visualizes the results of a Grid Search. Each cell's color represents the model's mean test score for a specific combination of two hyperparameters ('C' and 'Kernel'). This allows for quick identification of high-performing regions in the hyperparameter space.

Conclusion

Congratulations! You've just learned one of the most fundamental and widely used techniques for model optimization. Automating the search for the best hyperparameters is a huge step forward in building powerful and reliable machine learning models.

Key Takeaways:

  • GridSearchCV automates hyperparameter tuning by exhaustively searching through a predefined grid of values.
  • It uses k-fold cross-validation to get a robust performance score for each hyperparameter combination.
  • The process involves four steps: instantiate the model, define the param_grid, instantiate GridSearchCV, and call .fit().
  • After fitting, you can access the optimal settings and the final tuned model through the .best_params_ and .best_estimator_ attributes.

Preview of the next lesson:
GridSearchCV is powerful but can be computationally very expensive, especially with a large number of hyperparameters or values. What if you can't afford to try every single combination? In the next lesson, we will explore RandomizedSearchCV, a more efficient method that samples a fixed number of combinations from the grid, often finding a very good model in a fraction of the time.