By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A Zero-Fluff, Production-Ready Guide
Hyperparameter tuning is the process of systematically searching for the best configuration of a machine learning model’s settings (hyperparameters) to maximize performance. Unlike model parameters (e.g., weights in a neural network), hyperparameters are set before training—think of them as the "knobs" you adjust to optimize your model.
Why it matters in production:- A poorly tuned model can underperform, wasting compute resources and delivering inaccurate predictions.- Manual tuning ("guess and check") is slow, error-prone, and doesn’t scale.- Automated tuning (via GridSearchCV or RandomizedSearchCV) ensures reproducibility and saves time.
GridSearchCV
RandomizedSearchCV
Real-world scenario:You’re building a fraud detection model for a fintech startup. Your baseline logistic regression model has 85% accuracy, but the business needs 92% to meet compliance. Hyperparameter tuning is your fastest path to hitting that target without collecting more data or switching models.
C
max_depth
n_estimators
C=[0.001, 0.01, 0.1, 1, 10, 100, 1000]
k
cv=5
cv=10
cv=3
accuracy
f1
roc_auc
n_iter=50
refit=True
scikit-learn
pandas
numpy
digits
sklearn.datasets
sklearn
train_test_split
Pipeline
from sklearn.datasets import load_digits from sklearn.model_selection import train_test_split digits = load_digits() X, y = digits.data, digits.target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import GridSearchCV, RandomizedSearchCV from scipy.stats import randint # Define the model model = RandomForestClassifier(random_state=42) # Define the search space param_grid = { "n_estimators": [50, 100, 200], # GridSearchCV "max_depth": [None, 10, 20, 30], # GridSearchCV "min_samples_split": [2, 5, 10], # GridSearchCV } param_dist = { "n_estimators": randint(50, 200), # RandomizedSearchCV "max_depth": randint(1, 30), # RandomizedSearchCV "min_samples_split": randint(2, 10), # RandomizedSearchCV }
grid_search = GridSearchCV( estimator=model, param_grid=param_grid, cv=5, scoring="accuracy", n_jobs=-1, # Use all CPU cores verbose=1, ) grid_search.fit(X_train, y_train) # Best parameters and score print("Best params (GridSearchCV):", grid_search.best_params_) print("Best score (GridSearchCV):", grid_search.best_score_)
Expected output:
Fitting 5 folds for each of 36 candidates, totalling 180 fits Best params (GridSearchCV): {'max_depth': 20, 'min_samples_split': 2, 'n_estimators': 200} Best score (GridSearchCV): 0.972
random_search = RandomizedSearchCV( estimator=model, param_distributions=param_dist, n_iter=50, # Number of combinations to sample cv=5, scoring="accuracy", n_jobs=-1, random_state=42, verbose=1, ) random_search.fit(X_train, y_train) # Best parameters and score print("Best params (RandomizedSearchCV):", random_search.best_params_) print("Best score (RandomizedSearchCV):", random_search.best_score_)
Fitting 5 folds for each of 50 candidates, totalling 250 fits Best params (RandomizedSearchCV): {'n_estimators': 187, 'min_samples_split': 3, 'max_depth': 25} Best score (RandomizedSearchCV): 0.975
from sklearn.metrics import accuracy_score # GridSearchCV best model y_pred_grid = grid_search.predict(X_test) print("GridSearchCV test accuracy:", accuracy_score(y_test, y_pred_grid)) # RandomizedSearchCV best model y_pred_random = random_search.predict(X_test) print("RandomizedSearchCV test accuracy:", accuracy_score(y_test, y_pred_random))
GridSearchCV test accuracy: 0.975 RandomizedSearchCV test accuracy: 0.978
import joblib # Save the best model (RandomizedSearchCV in this case) joblib.dump(random_search.best_estimator_, "best_rf_model.pkl")
n_jobs=-1
pipe = Pipeline([ ("scaler", StandardScaler()), ("model", RandomForestClassifier(random_state=42)) ]) ```
n_iter
early_stopping_rounds
random_state
MLflow
Weights & Biases
mlflow.log_params(random_search.best_params_) mlflow.log_metric("accuracy", random_search.best_score_) ```
joblib
pickle
cv
n_jobs
scoring="roc_auc"
Answer: RandomizedSearchCV. It samples a subset of combinations.
"What does cv=5 mean in GridSearchCV?
Answer: 5-fold cross-validation (train on 4 folds, validate on 1).
"Why use refit=True?
param_grid
param_distributions
"You’re tuning a model with 5 hyperparameters, each with 10 possible values. How many combinations will GridSearchCV test?"- Answer: 10^5 = 100,000 combinations. Use RandomizedSearchCV instead.
10^5 = 100,000
Challenge:Tune a LogisticRegression model on the digits dataset using RandomizedSearchCV. Optimize for roc_auc (not accuracy). Use the following search space: - C: Log-uniform distribution between 1e-4 and 1e4.- penalty: ["l1", "l2"].- solver: ["liblinear", "saga"].
LogisticRegression
1e-4
1e4
penalty
["l1", "l2"]
solver
["liblinear", "saga"]
Solution:
from sklearn.linear_model import LogisticRegression from scipy.stats import loguniform param_dist = { "C": loguniform(1e-4, 1e4), "penalty": ["l1", "l2"], "solver": ["liblinear", "saga"], } model = LogisticRegression(random_state=42, max_iter=1000) random_search = RandomizedSearchCV( model, param_distributions=param_dist, n_iter=50, cv=5, scoring="roc_auc_ovr", n_jobs=-1, random_state=42, ) random_search.fit(X_train, y_train) print("Best params:", random_search.best_params_) print("Best ROC-AUC:", random_search.best_score_)
Why it works:- loguniform samples C on a log scale (better for regularization).- roc_auc_ovr is the correct metric for multi-class ROC-AUC.
loguniform
roc_auc_ovr
GridSearchCV(param_grid=...)
param_grid={"C": [0.1, 1, 10]}
RandomizedSearchCV(n_iter=50)
scoring="accuracy"
"accuracy"
"roc_auc"
"f1"
joblib.dump(model, "file.pkl")
joblib.dump(model, "model.pkl")
scipy.stats
randint
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.