Skip to main content

Welcome to a Grasp lesson

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

Lesson 45

Hyperparameter Tuning with GridSearchCV and RandomizedSearchCV

Recommended resources

In our last lesson, you saw how gradient boosting, particularly XGBoost, creates powerful models by sequentially correcting errors. We mentioned that the performance of these models heavily depends on their hyperparameters, such as learning_rate and max_depth. Manually tweaking these values can be tedious and ineffective.

This lesson will equip you with a systematic approach to this crucial step in the machine learning workflow. You will learn how to automate the search for the best hyperparameter settings using two powerful techniques from scikit-learn: GridSearchCV and RandomizedSearchCV. Mastering this will allow you to unlock the full potential of the models you build.

1. The Challenge of Finding the Best Parameters

A machine learning model like Random Forest or XGBoost can have dozens of hyperparameters. Finding the right combination is critical:

  • A max_depth that is too high can lead to overfitting.
  • A learning_rate that is too low can make training unnecessarily slow, while one that is too high might prevent the model from converging to a good solution.
  • The optimal value for one hyperparameter often depends on the values of others.

Searching for the best combination one parameter at a time is inefficient because you might miss a great model that requires changing multiple parameters at once. To do this properly, we need a more structured approach. A common, yet manual, way to start is by using a for loop to test a range of values for a single hyperparameter, using cross-validation to get a robust performance estimate for each value.

The following video provides a great review of this manual process, which sets the stage for the automated tools we'll cover next.

How to find the best model parameters in scikit-learn

The video "How to find the best model parameters in scikit-learn" from the Data School channel clearly demonstrates the manual approach to parameter tuning.

Watch from the review. This section recaps k-fold cross-validation and shows how to use a for loop to test different values for the n_neighbors parameter in a KNN model. This code is exactly what we are about to automate.

As you can see, this works for one parameter, but it becomes cumbersome when you want to tune multiple parameters simultaneously. This is where GridSearchCV comes in.


2. Grid Search: The Exhaustive Method

GridSearchCV automates the process of searching through a specified grid of hyperparameter values. It exhaustively tries every possible combination, evaluates each one using cross-validation, and tells you which combination performed the best.

The process is straightforward:

  1. Define a "parameter grid": This is a Python dictionary where keys are the hyperparameter names (e.g., 'n_estimators') and values are lists of the settings you want to try (e.g., [100, 200, 300]).
  2. Instantiate GridSearchCV: You provide it with the model, the parameter grid, and the cross-validation (cv) configuration.
  3. Fit the data: GridSearchCV then runs all the experiments for you.

Let's see how this works in practice.

How to find the best model parameters in scikit-learn

Continuing with the same Data School video, let's see how GridSearchCV automates the for loop.

Watch these two segments: GridSearchCV explained: This part introduces GridSearchCV, explains how to set up the parameter grid, and shows how to access the results using the .best_score_ and .best_params_ attributes. Tuning multiple parameters: This demonstrates how to expand the grid to search over multiple hyperparameters at once, highlighting the exhaustive nature of the search.

The main strength of GridSearchCV is its thoroughness—it guarantees to find the best combination within your specified grid. However, this comes at a significant computational cost. If you have 3 hyperparameters with 10 values each, GridSearchCV will train and evaluate models. If you're using 5-fold cross-validation, that's 5,000 model fits! This "combinatorial explosion" can make Grid Search impractical for models with many hyperparameters or for large datasets.


3. Random Search: The Efficient Alternative

Is it always necessary to try every combination? Research and practice have shown that for many models, only a few hyperparameters have a major impact on performance. RandomizedSearchCV leverages this insight by testing a fixed number of random combinations from the hyperparameter space.

This approach has two key advantages:

  1. Speed: You directly control the computational cost via the n_iter parameter, which sets the number of combinations to try, regardless of how large the search space is.
  2. Effectiveness: By sampling across the entire range of values, it has a better chance of discovering good values for the most important parameters, rather than exhaustively testing many values for unimportant ones.
This image illustrates the difference between Grid Search and Random Search. Grid Search (left) methodically tests every point on a predefined grid. Random Search (right) samples a smaller number of random points from the same space, allowing for a more flexible and often more efficient exploration.

Let's see how to implement RandomizedSearchCV and why it's so effective.

How to find the best model parameters in scikit-learn

Let's go back to the Data School video one last time to learn about this efficient alternative.

Watch the section on RandomizedSearchCV. Pay attention to how it allows you to define parameter distributions (though for discrete values, it looks the same as a grid) and how you control the number of trials with the n_iter parameter.

Because of its efficiency, RandomizedSearchCV is often the preferred method, especially during the initial stages of model exploration or when dealing with complex models like XGBoost that have many tuning parameters.

For a deeper dive into the comparison and a practical code implementation, the following article is a great resource.

Grid Search vs Random Search: Which One Should You ...

This article from the trainindata blog provides a clear breakdown and comparison of the two methods.

Read through the sections titled Understanding Grid Search and Random Search and Grid Search and Random Search: Application. The code examples for both GridSearchCV and RandomizedSearchCV are particularly useful. Notice the calculation of how many times the model is fit, which makes the computational cost difference very concrete.


4. Practical Tuning Workflow

Let's put this all together into a practical workflow. We will tune the XGBClassifier we learned about in the previous lesson. A common strategy is to start with a RandomizedSearchCV to quickly narrow down a promising region of the hyperparameter space, and then potentially follow up with a more focused GridSearchCV around the best values found.

Here's how you can apply RandomizedSearchCV to an XGBoost model.

import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, RandomizedSearchCV
from xgboost import XGBClassifier
from scipy.stats import randint, uniform




# 1. Load and prepare data
data = load_breast_cancer()
X = data.data
y = data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)




# 2. Initialize the model
xgb = XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)




# 3. Define the parameter distribution
# We use distributions from scipy.stats for continuous parameters
param_dist = {
    'n_estimators': randint(50, 500),
    'learning_rate': uniform(0.01, 0.3),
    'max_depth': randint(3, 10),
    'subsample': uniform(0.6, 0.4), # Range is [loc, loc + scale] so 0.6 to 1.0
    'colsample_bytree': uniform(0.6, 0.4) # 0.6 to 1.0
}




# 4. Instantiate RandomizedSearchCV
# n_iter sets the number of random combinations to try.
# cv is the number of cross-validation folds.
# n_jobs=-1 uses all available CPU cores.
random_search = RandomizedSearchCV(
    estimator=xgb, 
    param_distributions=param_dist, 
    n_iter=50,  # Try 50 different combinations
    cv=5, 
    verbose=1, 
    random_state=42, 
    n_jobs=-1
)




# 5. Fit the search to the data
random_search.fit(X_train, y_train)




# 6. Inspect the results
print("Best hyperparameters found:")
print(random_search.best_params_)
print("\nBest cross-validation score (Accuracy):")
print(f"{random_search.best_score_:.4f}")




# The random_search object now contains a model that has been
# automatically retrained on the full training data with the best parameters.
# We can use it to predict on the test set directly.
best_model = random_search.best_estimator_
test_accuracy = best_model.score(X_test, y_test)
print(f"\nTest set accuracy: {test_accuracy:.4f}")

When you run this code, RandomizedSearchCV will test 50 different combinations of the specified hyperparameters, using 5-fold cross-validation for each. After it finishes, it will report the best combination it found and the corresponding average accuracy. Importantly, the random_search object has an attribute .best_estimator_ which is the model refit on the entire training set using these best parameters, ready for evaluation on your test set.

This table provides a concise summary comparing the key characteristics of GridSearchCV and RandomizedSearchCV, covering their search strategy, guarantees, computational cost, and suitability for different hyperparameter spaces.

Conclusion

You now have a powerful and systematic way to optimize your machine learning models. Instead of guessing, you can define a search space and let your computer do the heavy lifting to find high-performing hyperparameter settings.

Key Takeaways:

  • Hyperparameter tuning is a critical step for maximizing model performance.
  • GridSearchCV performs an exhaustive search of all specified parameter combinations. It is thorough but can be very slow.
  • RandomizedSearchCV performs a search on a random sample of parameter combinations. It is much more computationally efficient and often finds a solution that is as good or nearly as good as one found by a grid search.
  • The process involves defining a parameter grid or distribution, instantiating the search object with a model and cross-validation strategy, and fitting it to the data.
  • The best model is automatically refit on the training data and can be accessed via the .best_estimator_ attribute.

In our next lesson, we will put everything together. You will learn how to compare the performance of entirely different algorithms (e.g., Logistic Regression vs. Random Forest vs. XGBoost) on the same dataset, allowing you to select the best overall approach for your problem.