ML Atlas

Hyperparameter Tuning

Teaching your model how to learn — the meta-optimization problem every ML practitioner must master.

IntermediateSupervised
34 min read
Familiarity with at least one ML model (decision tree, SVM, neural network)Understanding of train/validation/test splitsCross-validation (k-fold CV)Basic understanding of overfitting and model complexity
  • Kaggle competitions: hyperparameter tuning of XGBoost/LightGBM is often the difference between top-10 and top-100 placement
  • Google Vizier: Google's internal Bayesian optimization service for tuning models across Search, Ads, and Translate
  • Optuna at Preferred Networks: the open-source framework used to tune deep learning models in robotics and drug discovery
  • AutoML pipelines (Auto-sklearn, H2O AutoML): automated hyperparameter search is the core of all AutoML systems
  • Neural Architecture Search (NAS): tuning layer widths, depths, and connectivity is a hyperparameter problem at scale
  • Pharmaceutical ML: Bayesian optimization used to tune QSAR models for drug potency prediction with minimal experimental budget
01

In Plain English

Hyperparameter tuning is the process of finding the best configuration settings for a machine learning model before training begins. Unlike model parameters (weights learned from data), hyperparameters are set by the practitioner — things like learning rate, number of trees, or regularization strength. Tuning finds the values that produce the best generalization performance.

Why It Exists

ML algorithms have many design choices that can't be learned from data — the algorithm needs them to start learning in the first place. A random forest needs to know how many trees to grow and how deep each tree can go. A neural network needs a learning rate. These choices profoundly affect performance, and the optimal values depend on the specific dataset, task, and compute budget.

Problem It Solves

Eliminating manual trial-and-error hyperparameter selection, finding configurations that maximize generalization (not just training fit), and doing so within a fixed compute budget — more efficiently than exhaustive search.

Real-Life Analogy

"A chef is calibrating an oven for a new recipe. The oven's dials (temperature, convection fan speed, rack position) are like hyperparameters — they must be set before baking starts. The actual chemical reactions (baking) are like model training. You can't learn the right temperature from the baking itself; you try different settings across test batches, evaluate results, and converge toward the optimal configuration. Bayesian optimization is like a smart chef who remembers previous baking experiments and picks the next temperature to try based on where the best results were clustered."

When To Use

  • You have a promising model architecture but default hyperparameters are underperforming
  • You want to squeeze the last few percentage points of performance from a model
  • You are comparing models fairly and want each to be at its best before comparison
  • You are building an AutoML pipeline that must automatically configure models
  • The compute budget allows running multiple training runs (each with a different configuration)

When NOT To Use

  • You have no validation data (or very little) — hyperparameter tuning will overfit to whatever validation set you have
  • Training a single model takes days — exhaustive or random search may not be feasible
  • You're prototyping — use defaults first; tune only when the baseline is working
  • The dataset is tiny (< 200 samples) — different hyperparameters may simply memorize different aspects of the tiny data; results are unreliable
02

Parameters vs. hyperparameters: parameters are internal to the model and learned during training (e.g., neural network weights, linear regression coefficients). Hyperparameters are external to the model and set by the practitioner before training (e.g., learning rate, number of layers, regularization strength, maximum tree depth). The model cannot tune its own hyperparameters — it needs them to know how to learn. Tuning hyperparameters is therefore a meta-learning problem: you're learning how to configure the learner.

Why hyperparameters matter so much: a random forest with max_depth=2 might have training accuracy of 0.70 and test accuracy of 0.69 (underfitting). The same algorithm with max_depth=50 might have training accuracy of 0.99 and test accuracy of 0.74 (overfitting). With max_depth=15, it might achieve training accuracy of 0.93 and test accuracy of 0.88 (well-tuned). The algorithm is identical — only the hyperparameter differs. This illustrates why tuning is not optional for production systems.

The hyperparameter tuning loop: propose a configuration → train model on training set → evaluate on validation set (or via cross-validation) → record result → propose next configuration informed by all previous results → repeat. The challenge is making each 'propose next configuration' step intelligent rather than random or exhaustive. Grid search is dumb (exhaustive). Random search is smarter (samples full range). Bayesian optimization is smartest (uses previous results to focus on promising regions).

The validation set is the oracle: every tuning method relies on validation performance as the signal to optimize. This creates a risk — if you run thousands of configurations and always report the best validation score, you've overfit the hyperparameters to the validation set. The validation score becomes an optimistic estimate of true generalization. Mitigations: use cross-validation instead of a single validation split (harder to overfit to), and keep a separate test set that is never seen during tuning.

The Metaphor

"Hyperparameter tuning is like searching for the best hiking trail in a mountain range you've never visited. Grid search walks every possible path in a grid pattern — thorough but slow and wastes time on valleys. Random search picks random starting points — surprisingly effective because a few good samples cover the terrain well. Bayesian optimization is like having a topographic map that gets more accurate with each hike: you start with a rough map, pick the most promising unexplored peaks to visit next, update the map after each hike, and converge toward the summit efficiently without covering every square meter."

Beginner Mental Model

Think of each hyperparameter as a dial. Grid search: systematically turn every combination of every dial. Random search: randomly spin the dials and try 50 random combinations. Bayesian optimization: after each spin, use what you learned to make a smarter guess about where the 'sweet spot' is. Successive halving: spin all dials randomly, train briefly, discard the worst half, give more time to the survivors.

03

Given a learning algorithm A parameterized by hyperparameters λ ∈ Λ (the hyperparameter space), a dataset D split into D_train and D_val, and a performance metric m, hyperparameter optimization solves: λ* = argmax_{λ ∈ Λ} m(A(λ, D_train), D_val). The objective function f(λ) = m(A(λ, D_train), D_val) is expensive to evaluate (requires training a full model), non-differentiable with respect to λ (can't use gradient descent), and may be stochastic (different results with different random seeds). This is a black-box optimization problem.

Hyperparameter
A configuration setting of a learning algorithm that is set before training and cannot be learned from data. Examples: learning rate, number of trees, regularization strength, kernel type, network depth.
Parameter
An internal variable of a model learned from training data via optimization. Examples: neural network weights, linear regression coefficients, SVM support vectors.
Search Space (Λ)
The set of all valid hyperparameter configurations. Can be discrete (number of layers ∈ {1,2,3,4}), continuous (learning rate ∈ [1e-5, 1e-1]), or conditional (dropout rate only applies if using dropout layers).
Objective Function f(λ)
The function mapping a hyperparameter configuration λ to a scalar performance metric (e.g., validation AUC). Expensive to evaluate because it requires training a full model. Also called the 'black-box function' in optimization literature.
Surrogate Model
In Bayesian optimization, a cheap probabilistic model (typically a Gaussian Process) that approximates f(λ) based on previously observed evaluations. Used to decide where to evaluate next without training a full model.
Acquisition Function
A function that uses the surrogate model's predictions (mean and uncertainty) to score which λ to evaluate next. Balances exploration (high uncertainty) and exploitation (high predicted value). Common choices: Expected Improvement (EI), Upper Confidence Bound (UCB), Probability of Improvement (PI).
Successive Halving
A resource-efficient tuning strategy: start many configurations with a small budget (few training epochs), eliminate the worst half, double the budget for survivors, repeat. Efficiently allocates compute to promising configurations.
HyperBand
An extension of successive halving that runs multiple brackets with different initial budgets, removing the sensitivity to the initial number of configurations. Combines the efficiency of successive halving with robustness to configuration.
ASHA (Asynchronous Successive Halving)
An asynchronous version of successive halving designed for distributed settings where workers can promote configurations as soon as they complete a rung, without waiting for all workers to finish. Used in Ray Tune.
TPE (Tree-structured Parzen Estimator)
The surrogate model used by Optuna's default sampler. Models p(λ|y > y*) and p(λ|y ≤ y*) separately as Parzen window estimates, then computes acquisition as the ratio. More scalable than Gaussian Processes for high-dimensional discrete spaces.
  1. 1. Define the search space: list each hyperparameter, its type (int, float, categorical), and its range. Use log scale for parameters that span orders of magnitude (learning rate, regularization).
  2. 2. Choose a tuning strategy: grid search (small, discrete spaces), random search (moderate budgets), Bayesian optimization (expensive evaluations, moderate space), or successive halving/HyperBand (large spaces with early stopping).
  3. 3. Choose an evaluation protocol: k-fold CV on training set (most robust, expensive) or single validation split (faster, noisier). Never use the test set during tuning.
  4. 4. Run the search: for each proposed configuration, train the model and evaluate on the validation criterion. Record all results.
  5. 5. Analyze results: plot learning curves by hyperparameter value, check for interactions between hyperparameters, identify if the search space needs adjustment.
  6. 6. Select the best configuration: choose the hyperparameter values with the best validation performance (lowest loss, highest metric).
  7. 7. Retrain on all training data: using the selected configuration, retrain on 100% of the training set (not just the training folds used during tuning).
  8. 8. Evaluate on the test set exactly once: report this as final performance.

Training dataset, validation dataset (or CV protocol), model class, search space definition (hyperparameter names, types, ranges), compute budget (number of trials or wall-clock time).

Best hyperparameter configuration λ*, its validation performance score, and optionally the full results table of all evaluated configurations.

01The validation set is representative of the deployment distribution — if not, tuned hyperparameters may not generalize.
02The objective function is relatively smooth — nearby hyperparameter values produce similar performance (enables surrogate models to generalize).
03There is a fixed compute budget — the optimal strategy depends on how many evaluations you can afford.
04Hyperparameters are somewhat independent — strong interactions make the search space exponentially harder to navigate.
  • Conditional hyperparameters: some hyperparameters only apply under certain conditions (dropout rate only relevant if dropout=True). Optuna and Hyperopt handle conditional spaces natively.
  • Multi-objective tuning: optimizing both accuracy and inference latency simultaneously. Requires Pareto front analysis rather than a single argmax.
  • Noisy evaluations: if the same λ gives different validation scores on different runs (due to random initialization), the surrogate model must account for noise. Use multiple seeds and average.
  • Unbounded search spaces: if the optimal value is at or near the boundary of your search range, the true optimum is outside your search space — widen the range.
04

Hyperparameter tuning sits between model selection and final evaluation. It wraps the training process in an outer optimization loop that operates on validation performance. All tuning must happen on the training set (using CV) — the test set must remain unseen until the final evaluation of the tuned model.

  • 01.Split data into train, validation (or use CV), and test sets before any tuning begins. The test set must not influence any tuning decision.
  • 02.If using cross-validation during tuning: wrap the entire preprocessing pipeline inside the CV to prevent leakage (use sklearn Pipeline).
  • 03.Normalize search ranges: log-scale sampling for learning rates, regularization, and other multiplicative parameters that span orders of magnitude.
  • 04.Fix random seeds for reproducibility: set numpy, torch, and sklearn random states so that different hyperparameter configurations are compared fairly.
  • 01.Grid Search: enumerate all combinations of a discrete hyperparameter grid. Fit and evaluate each. Complexity: O(∏ᵢ |Hᵢ|) evaluations where |Hᵢ| is the number of values for hyperparameter i.
  • 02.Random Search: sample configurations uniformly at random from the search space for a fixed number of trials. Each trial is independent.
  • 03.Bayesian Optimization: maintain a surrogate model (GP or TPE). After each evaluation, update the surrogate and use an acquisition function to select the next configuration.
  • 04.Successive Halving: start n configurations with budget b₀. After each round, keep the top 1/η fraction and multiply budget by η. Continue until one configuration remains.
  • 05.HyperBand: run successive halving with multiple brackets (different starting n and b₀), then combine results. Removes sensitivity to n choice.

n_trials / n_iter

Total number of hyperparameter configurations to evaluate. More trials = better exploration but higher compute cost.

50–200 for random/Bayesian search. For grid search: determined by grid size.

cv (number of folds in CV during tuning)

When using cross-validation to evaluate each configuration, the number of folds. Higher k = more reliable evaluation per trial but k× cost.

3-fold during tuning (fast), 5-fold for final model selection

eta (η) in successive halving

The halving factor — fraction of configurations eliminated in each round. η=3 means keep top 1/3.

η = 3 (standard) or η = 4

  1. 1Define the search space as a dict (sklearn) or trial.suggest_* calls (Optuna)
  2. 2Wrap model training in an objective function that returns validation metric
  3. 3For sklearn: GridSearchCV(estimator, param_grid, cv=3, scoring='roc_auc').fit(X_train, y_train)
  4. 4For Optuna: study = optuna.create_study(direction='maximize'); study.optimize(objective, n_trials=100)
  5. 5Inspect study.best_params and study.best_value
  6. 6Retrain final model with best_params on all training data
  7. 7Evaluate on test set once: report this score as final performance
05
06
python
1import numpy as np
2from itertools import product
3from sklearn.model_selection import cross_val_score
4from sklearn.ensemble import RandomForestClassifier
5from sklearn.datasets import make_classification
6
7np.random.seed(42)
8X, y = make_classification(n_samples=1000, n_features=20,
9                            n_informative=10, random_state=42)
10
11# ── 1. Grid Search from Scratch ───────────────────────────────────────────────
12def grid_search(model_class, param_grid, X, y, cv=3, scoring='roc_auc'):
13    """Exhaustive grid search over all combinations."""
14    keys   = list(param_grid.keys())
15    values = list(param_grid.values())
16    best_score  = -np.inf
17    best_params = None
18    results     = []
19
20    for combo in product(*values):
21        params = dict(zip(keys, combo))
22        model  = model_class(**params)
23        scores = cross_val_score(model, X, y, cv=cv, scoring=scoring)
24        mean_score = scores.mean()
25        results.append({"params": params, "score": mean_score})
26        if mean_score > best_score:
27            best_score  = mean_score
28            best_params = params
29
30    return best_params, best_score, results
31
32param_grid = {
33    "n_estimators": [50, 100, 200],
34    "max_depth":    [3, 5, 10, None],
35    "min_samples_split": [2, 5, 10],
36}
37best_p, best_s, all_results = grid_search(
38    RandomForestClassifier, param_grid, X, y)
39print(f"Grid Search — Best Score: {best_s:.4f}")
40print(f"Grid Search — Best Params: {best_p}")
41print(f"Total evaluations: {len(all_results)}")   # 3×4×3 = 36
42
43# ── 2. Random Search from Scratch ─────────────────────────────────────────────
44def random_search(model_class, param_distributions, X, y,
45                  n_iter=20, cv=3, scoring='roc_auc', random_state=42):
46    """Random search: sample configurations from distributions."""
47    rng = np.random.RandomState(random_state)
48    best_score  = -np.inf
49    best_params = None
50    results     = []
51
52    for _ in range(n_iter):
53        params = {}
54        for key, dist in param_distributions.items():
55            if hasattr(dist, 'rvs'):            # scipy distribution
56                params[key] = dist.rvs(random_state=rng)
57            elif callable(dist):                # lambda / function
58                params[key] = dist(rng)
59            elif isinstance(dist, list):        # discrete list
60                params[key] = rng.choice(dist)
61
62        model  = model_class(**params)
63        scores = cross_val_score(model, X, y, cv=cv, scoring=scoring)
64        mean_score = scores.mean()
65        results.append({"params": params, "score": mean_score})
66        if mean_score > best_score:
67            best_score  = mean_score
68            best_params = params.copy()
69
70    return best_params, best_score, results
71
72# Log-uniform sampling for n_estimators (sample in log space)
73param_dists = {
74    "n_estimators":     lambda rng: int(rng.choice([50, 75, 100, 150, 200, 300])),
75    "max_depth":        lambda rng: rng.choice([3, 5, 7, 10, 15, None]),
76    "min_samples_split":lambda rng: rng.randint(2, 20),
77    "max_features":     lambda rng: rng.choice(["sqrt", "log2", 0.3, 0.5, 0.7]),
78}
79best_p, best_s, all_results = random_search(
80    RandomForestClassifier, param_dists, X, y, n_iter=30)
81print(f"\nRandom Search — Best Score: {best_s:.4f}")
82print(f"Random Search — Best Params: {best_p}")
83
84# ── 3. Simple Bayesian Optimization (GP + EI) from Scratch ─────────────────────
85from scipy.stats import norm
86
87def expected_improvement(mu, sigma, f_best):
88    """Compute Expected Improvement at predicted (mu, sigma) given best f+."""
89    Z  = (mu - f_best) / (sigma + 1e-9)
90    ei = (mu - f_best) * norm.cdf(Z) + sigma * norm.pdf(Z)
91    return np.maximum(ei, 0)
92
93class GaussianProcessSurrogate:
94    """Minimal RBF-kernel GP for 1D demonstration."""
95    def __init__(self, length_scale=1.0, noise=1e-4):
96        self.ls    = length_scale
97        self.noise = noise
98        self.X_obs = None
99        self.y_obs = None
100        self.K_inv  = None
101
102    def _rbf(self, X1, X2):
103        # X1: (n,d), X2: (m,d) → (n,m) kernel matrix
104        diff = X1[:, None, :] - X2[None, :, :]   # (n,m,d)
105        return np.exp(-0.5 * np.sum(diff**2, axis=-1) / self.ls**2)
106
107    def fit(self, X, y):
108        self.X_obs = np.array(X)
109        self.y_obs = np.array(y)
110        K = self._rbf(self.X_obs, self.X_obs)
111        K += self.noise * np.eye(len(X))
112        self.K_inv = np.linalg.inv(K)
113
114    def predict(self, X_new):
115        X_new = np.array(X_new)
116        k_star = self._rbf(X_new, self.X_obs)          # (m, n)
117        mu     = k_star @ self.K_inv @ self.y_obs       # (m,)
118        k_ss   = self._rbf(X_new, X_new)               # (m, m)
119        cov    = k_ss - k_star @ self.K_inv @ k_star.T # (m, m)
120        sigma  = np.sqrt(np.maximum(np.diag(cov), 1e-9))
121        return mu, sigma
122
123
124def bayesian_optimization_1d(objective, bounds, n_init=5, n_iter=20,
125                               random_state=42):
126    """
127    Bayesian optimization over a 1D continuous hyperparameter.
128    objective(x) returns a scalar (higher is better).
129    bounds: (low, high) tuple.
130    """
131    rng = np.random.RandomState(random_state)
132    low, high = bounds
133
134    # Initial random evaluations
135    X_obs = rng.uniform(low, high, size=(n_init, 1))
136    y_obs = np.array([objective(x[0]) for x in X_obs])
137
138    gp = GaussianProcessSurrogate(length_scale=(high - low) / 5)
139
140    for iteration in range(n_iter):
141        gp.fit(X_obs, y_obs)
142        f_best = y_obs.max()
143
144        # Evaluate acquisition on a dense grid
145        candidates = np.linspace(low, high, 500).reshape(-1, 1)
146        mu, sigma  = gp.predict(candidates)
147        ei         = expected_improvement(mu, sigma, f_best)
148
149        next_x = candidates[np.argmax(ei)]   # pick highest EI
150        next_y = objective(next_x[0])
151
152        X_obs = np.vstack([X_obs, next_x])
153        y_obs = np.append(y_obs, next_y)
154
155        if (iteration + 1) % 5 == 0:
156            print(f"  BO iter {iteration+1:2d}: best so far = {y_obs.max():.4f}"
157                  f" at x = {X_obs[y_obs.argmax(), 0]:.4f}")
158
159    best_idx = y_obs.argmax()
160    return X_obs[best_idx, 0], y_obs[best_idx]
161
162
163# Demo: tune log(learning_rate) for a synthetic objective
164def synthetic_objective(log_lr):
165    """Simulated validation AUC as a function of log10(learning_rate)."""
166    # Peak near log_lr = -2.5 (lr ≈ 0.003)
167    return 0.90 - 0.5 * (log_lr + 2.5)**2 + np.random.randn() * 0.01
168
169print("\nBayesian Optimization (1D demo):")
170best_log_lr, best_auc = bayesian_optimization_1d(
171    synthetic_objective, bounds=(-5, 0), n_init=5, n_iter=20)
172print(f"Best log10(lr) = {best_log_lr:.3f} → lr = {10**best_log_lr:.5f}")
173print(f"Best AUC = {best_auc:.4f}")
The from-scratch implementation demonstrates all three core strategies. The GP surrogate uses RBF kernel with closed-form posterior equations. EI balances exploitation (μ - f+) and exploration (σ·φ(Z)). In practice, use Optuna or scikit-optimize instead of this pedagogical implementation — they handle kernel hyperparameter optimization, multi-dimensional spaces, and TPE which scales better than GP for high-dimensional integer spaces.
X_train: (1600, 20). GradientBoostingClassifier. Search space: n_estimators ∈ [50,500], max_depth ∈ [2,15], learning_rate ∈ [0.001, 0.5] (log), subsample ∈ [0.5,1.0], min_samples_leaf ∈ [1,20], max_features ∈ [0.3,1.0]. 80 Optuna trials.
GridSearchCV (27 trials): Best CV AUC = 0.8821, Test AUC = 0.8794
RandomizedSearchCV (50 trials): Best CV AUC = 0.8953, Test AUC = 0.8912
Optuna TPE (80 trials): Best CV AUC = 0.9012, Test AUC = 0.8987
Optuna + HyperBand (60 trials, 38 pruned): Best val AUC = 0.8834
  • Always sample learning_rate, alpha, and regularization parameters on a log scale: trial.suggest_float('lr', 1e-4, 1e-1, log=True). These parameters span orders of magnitude and uniform sampling wastes most trials on the uninteresting high-value end.
  • Use 3-fold CV during tuning (not 5-fold) to reduce compute by 40%. For final model selection, use 5-fold or a clean validation set. The relative ordering of configurations is reliable even with 3-fold.
  • Optuna's TPE sampler outperforms random search after ~20 trials. For the first 10 trials (n_startup_trials), TPE uses random sampling to build its initial model. Never use fewer than 20 trials with Optuna.
  • Set random seeds everywhere: np.random.seed, study sampler seed, and model random_state. Without seeds, the same configuration gives different CV scores across runs — masking true hyperparameter effects.
  • After tuning, always retrain on ALL training data with the best params. GridSearchCV.best_estimator_ with refit=True does this automatically. With Optuna, manually create a fresh model with best_params and fit on X_train, y_train.
  • Monitor the convergence plot: if the best score keeps improving at trial 80, extend the search. If it plateaus at trial 20, you've found the optimum — more trials waste compute.
  • Tuning hyperparameters on the test set (peeking) — even once invalidates the test set as an unbiased performance estimate.
  • Using uniform sampling for learning rate — loguniform(1e-4, 1e-1) is correct; uniform(1e-4, 1e-1) wastes most trials on large values where the model likely diverges.
  • Reporting GridSearchCV.best_score_ as test performance — it's the non-nested CV score, upwardly biased by hyperparameter selection.
  • Not fixing random seeds — comparing configurations that use different random initializations conflates randomness with hyperparameter effects.
07
📋

Small Dataset (< 1,000 rows)

Context-Dependent

Hyperparameter tuning on small datasets is risky — the validation set is tiny and noisy. CV estimates are unreliable. The 'best' hyperparameters may overfit to the specific validation fold composition. Use few trials, strong regularization, and be skeptical of small improvements.

💡 Use 5-fold CV for evaluation, limit to 20-30 trials, prefer simpler models with fewer hyperparameters. Consider nested CV to assess if tuning helps at all.
📊

Medium Dataset (1K–100K rows)

Excellent

The sweet spot for hyperparameter tuning. Enough data for reliable CV estimates; fast enough to run 50-100 trials. Bayesian optimization with Optuna is the recommended approach. Gains of 2-5% AUC over defaults are typical.

💡 Use Optuna TPE with 50-100 trials, 3-fold CV for tuning speed, 5-fold for final validation. Log-scale sampling for multiplicative parameters.
🗄️

Large Dataset (> 1M rows)

Good

Tuning is expensive but impactful. Each trial trains on 1M+ samples. Use subsampling (train on 10% per trial, full data for final model), successive halving with early stopping, or HyperBand to reduce cost while maintaining search quality.

💡 Optuna HyperbandPruner or Ray Tune ASHA are standard. Subsample to 100K for tuning trials; retrain on full data with best config.
📐

High-Dimensional Features (> 1K features)

Good

High-dimensional input doesn't fundamentally change tuning, but the regularization hyperparameter becomes critical. Tuning regularization strength, feature selection threshold, or dimensionality reduction components is especially important in these settings.

💡 Tune regularization strength (alpha, C, lambda) on log scale. Consider including feature selection as part of the tuning pipeline.
📈

Time Series Data

Good

Use TimeSeriesSplit for CV during tuning. Standard k-fold would leak future information into hyperparameter selection. The search space should include lookback window length and sequence-specific architecture choices.

💡 Always TimeSeriesSplit inside the objective function. Tune sequence length and lag features as hyperparameters alongside model hyperparameters.
⚖️

Imbalanced Dataset

Good

Include class_weight and resampling strategy as hyperparameters to tune. Optimize on AUC or F1, not accuracy. Use StratifiedKFold inside the tuning loop to maintain class proportions across folds.

💡 Add class_weight: ['balanced', None] and SMOTE oversampling ratio to search space. Tune threshold alongside model parameters if precision-recall trade-off matters.
08

Mandatory Visual Blueprint

What should move

At least one parameter, threshold, split, cluster state, or metric should change interactively.

What to observe

The learner should see how the concept affects error, fit, grouping, or decision quality.

Planned visual type

Interactive chart, step animation, or side-by-side failure-mode comparison.

Reference image slot

If no live lab exists yet, attach a relevant diagram/reference image before marking the page complete.

Topic key: hyperparameter-tuning

Search Strategy Comparison — Evaluations vs. Best Score Found

Cumulative best score versus number of evaluations for grid search, random search, and Bayesian optimization on a 6-dimensional hyperparameter space. Bayesian optimization finds near-optimal configurations in 20-30 trials. Random search requires 50-60. Grid search with 27 points misses the optimum entirely because the grid is too coarse.

Gradient descent convergence — MSE decreasing over iterations

Successive Halving Budget Allocation

How successive halving allocates compute across 81 initial configurations with η=3. Most configurations are eliminated after 1 epoch. Only the final winner receives 81 epochs. Total compute: 405 epoch-equivalents vs. 6,561 for training all configs fully.

Comparison visualization data is documented in this section.

Bayesian Optimization — Acquisition Function in Action

The GP surrogate after 10 evaluations of a 1D learning rate objective. The acquisition function (EI) peaks at an unexplored region between two good observations, balancing exploitation of the known good region (high mean) and exploration of the uncertain region (high variance). The next trial is placed at the EI peak.

GP posterior mean ± 2σ shown as a band. EI acquisition function overlaid. Observed points marked. Next suggested point (argmax EI) indicated by a vertical dashed line. Demonstrates how BO balances exploration and exploitation.

Hyperparameter Importance — FAnova Decomposition

Relative importance of each hyperparameter to validation AUC variance across 80 Optuna trials. Learning rate accounts for 48% of performance variance, followed by n_estimators (21%) and max_depth (17%). Subsample and min_samples_leaf have minimal effect on this dataset — reducing future search space.

Comparison visualization data is documented in this section.
09
  • Direct performance improvements without changing the algorithm

    A well-tuned default model often outperforms a poorly configured advanced model. Hyperparameter tuning squeezes the maximum performance out of a chosen algorithm — frequently adding 2-10% improvement over defaults with no algorithmic changes.

  • Bayesian optimization is highly sample-efficient

    Optuna's TPE sampler can find near-optimal configurations in 30-50 trials for moderate search spaces, compared to hundreds of trials needed for equivalent random search coverage. For expensive training runs, this efficiency difference is the practical difference between feasible and infeasible tuning.

  • Successive halving makes large-scale tuning affordable

    HyperBand with early stopping evaluates 81 configurations at the compute cost of training ~5 full models. Deep learning hyperparameter searches that would take weeks with random search become tractable in hours with HyperBand.

  • Systematic and reproducible

    Automated tuning with fixed random seeds produces reproducible results. Manual hyperparameter selection by trial-and-error is irreproducible, subjective, and rarely explores the full space of good configurations.

  • Identifies unimportant hyperparameters

    FAnova importance analysis (available in Optuna) reveals which hyperparameters matter most for a given dataset. This allows narrowing future searches to the important dimensions and setting unimportant ones to defaults.

  • Overfitting to the validation set

    Tuning 200 hyperparameter configurations optimizes for the specific validation set (or CV folds) used. The best configuration may not generalize — it may be the one that happened to fit the validation set's random characteristics. More configurations evaluated = more overfitting risk. Use nested CV or keep tuning trials under 100 for moderate datasets.

  • Computationally expensive

    Each trial requires training a full model. With 100 trials × 5-fold CV = 500 model training runs. For deep learning, each run takes hours. Even with successive halving, large neural architecture searches can require significant GPU clusters.

  • Search space design requires domain knowledge

    Poorly designed search spaces miss the optimum or waste compute. Setting a log-uniform range when the optimal value is near the boundary of your range means the best configuration is never evaluated. Choosing the right range requires prior knowledge about the algorithm.

  • No guarantee of global optimum

    The hyperparameter optimization landscape may have multiple local optima. Bayesian optimization is not globally optimal — it finds a good local region efficiently. Random search with enough trials has better theoretical coverage guarantees but worse sample efficiency.

  • Black-box — no gradient signal

    Hyperparameter optimization is fundamentally different from parameter optimization: you cannot differentiate through the training process with respect to most hyperparameters. Gradient-based methods like DARTS (differentiable architecture search) exist but require specific model architectures.

10
Kaggle / Competitive ML

GBM tuning for tabular competition leaderboards

XGBoost and LightGBM have 20+ hyperparameters. Optuna-based tuning with 100 trials typically adds 0.3-0.8% AUC over defaults on tabular tasks — the difference between gold and silver on many Kaggle competitions. The standard Kaggle workflow: Optuna for LightGBM tuning, 5-fold StratifiedKFold, optimize logloss.

Financial Services

Credit scoring model optimization

A credit risk model's hyperparameters (regularization, depth, ensemble size) directly affect both predictive performance and model complexity (a regulatory concern). Bayesian optimization is used to find the Pareto-optimal frontier between AUC and model simplicity, with constraints on maximum feature count and model depth.

Healthcare / Drug Discovery

Bayesian optimization for QSAR model tuning with limited experimental data

Quantitative structure-activity relationship (QSAR) models predict drug potency from molecular structure. Datasets often have < 500 compounds. Each evaluation is expensive. Bayesian optimization with GP surrogates finds the best regularization and kernel parameters in 20 trials — essential when every training run uses all available experimental data.

Computer Vision

Neural architecture and training hyperparameter search

ResNet training involves learning rate schedule, batch size, weight decay, data augmentation strength, and architecture choices. HyperBand with early stopping (ASHA) is used to evaluate 200 configurations at the cost of training 5 full models, finding architectures that achieve top-1 accuracy 2-3% above manual tuning.

NLP / LLM Fine-tuning

Efficient fine-tuning hyperparameter optimization

Fine-tuning language models requires tuning learning rate, warmup steps, batch size, and LoRA rank. Grid search is infeasible (training takes hours per trial). Bayesian optimization with Optuna and 15 trials — using early stopping via validation perplexity — finds optimal configurations for downstream task adaptation efficiently.

11

The four main hyperparameter search strategies have different strengths depending on budget, search space size, and evaluation cost.

Grid Search

Evaluates multiple configurations and returns the best

Exhaustively tries every combination. Combinatorial explosion with more than 3-4 hyperparameters. Wastes evaluations on unimportant dimensions. Best when search space is small and discrete.

Fewer than 3 hyperparameters, small discrete search space, need guaranteed exhaustive coverage, small compute budget per configuration.

Random Search

Also evaluates multiple configurations and returns the best

Samples configurations randomly from distributions. More efficient than grid search when some hyperparameters are unimportant (Bergstra & Bengio 2012). Trivially parallelizable. Each trial is independent.

Moderate budget (30-100 trials), high-dimensional space (> 4 hyperparameters), easy parallelization, when you want a simple baseline before trying Bayesian optimization.

Bayesian Optimization (GP / TPE)

Same interface: propose configuration, evaluate, record, repeat

Uses past results to intelligently select next configuration. More sample-efficient than random search after ~20 warm-up trials. Sequential (each trial depends on all previous results) — harder to parallelize naively. Optuna supports asynchronous parallelism via TPE.

Expensive evaluations (minutes to hours per trial), budget of 20-100 trials, continuous search spaces with smooth objective landscapes.

Successive Halving / HyperBand

Evaluates many configurations to find the best

Uses early stopping to eliminate bad configurations before they use full budget. Most compute-efficient for training with a natural fidelity axis (epochs, data size). Requires early performance to correlate with final performance.

Deep learning or iterative training where early performance is predictive of final performance, large search spaces (> 100 configurations), distributed compute available (ASHA).

Methodn_evaluationsParallelizableSample EfficiencySearch Space
Grid Search∏|Hᵢ| (fixed)Yes (trivially)LowSmall discrete
Random Searchn_iter (budget)Yes (trivially)MediumAny
Bayesian Opt (GP)n_trials (budget)Partial (async)HighContinuous, low-d
Bayesian Opt (TPE)n_trials (budget)Partial (async)HighMixed, high-d
Successive Halvingn × log_η(n)YesHighAny (with budget)
HyperBand≈ n × log(n)YesHighAny (with budget)
ASHA (async)ContinuousYes (fully)HighAny (distributed)

For most tabular ML tasks with moderate compute: use Optuna TPE with 50-100 trials. For deep learning with GPU clusters: use HyperBand (Optuna HyperbandPruner or Ray Tune ASHA). For quick prototyping: use RandomizedSearchCV with 30 trials. Grid search only for very small, well-understood spaces.

12

Validation CV Score (Best)

The best mean CV score across all evaluated configurations. This is the tuning objective — optimized by the search. Note: it's an optimistically biased estimate of the true test performance due to selection bias across many configurations.

Target: Context-dependent. More meaningful relative to baseline (default hyperparameter CV score).

Test Set Score

The one true final evaluation. Should be close to (but slightly below) the best CV score. A large gap between CV and test scores indicates overfitting to the validation set during tuning (too many configurations evaluated, too small a validation set).

Target: Within 0.01-0.03 AUC of the best CV score. Larger gaps indicate hyperparameter overfitting.

Tuning Improvement

How much tuning improved over default hyperparameters. If Δ is small, tuning may not be worth the compute cost. If Δ is large, the model was significantly misconfigured with defaults.

Target: Δ > 0.01 AUC justifies tuning cost for production models. Δ < 0.005 suggests defaults are already near-optimal.

Hyperparameter Importance

FAnova-based decomposition of which hyperparameters explain most of the variance in validation scores across trials. High importance = this hyperparameter must be tuned carefully. Low importance = can be fixed at a reasonable default.

Target: Typically 1-2 hyperparameters dominate (> 50% combined importance). Guides where to focus tuning in future runs.

  1. 01.1. Run tuning with a fixed budget (e.g., 80 trials) and record all (config, cv_score) pairs.
  2. 02.2. Plot the convergence curve: best score vs. trial number. Confirm it has plateaued before budget exhausted.
  3. 03.3. Inspect hyperparameter importance (Optuna's optuna.importance.get_param_importances) — identify unimportant parameters to fix in future runs.
  4. 04.4. Compare best CV score to default CV score — quantify the tuning benefit.
  5. 05.5. Retrain with best params on ALL training data.
  6. 06.6. Evaluate on test set exactly once. If the gap between CV and test is large (> 0.05), investigate hyperparameter overfitting.
  7. 07.7. For critical applications: use nested CV to get an unbiased estimate of how well 'the tuning process' generalizes.
  • Reporting best_score_ as test performance — this is the non-nested CV score, biased upward by selection across many configurations.
  • Evaluating on the test set multiple times during tuning to check progress — this contaminates the test set and invalidates it as an unbiased final estimate.
  • Not accounting for randomness: running tuning once with a fixed seed and claiming this is the optimal configuration — repeat tuning with different seeds to assess stability.
  • Searching too narrow a range: if the optimal value is at the boundary of the search range, the true optimum is outside your range and you'll never find it.

Gradient boosting on a churn prediction task. Default params: CV AUC = 0.871. After 80 Optuna trials: best CV AUC = 0.912 (best params: lr=0.023, n_estimators=347, max_depth=5). Tuning improvement Δ = 0.041 — significant. FAnova importance: learning_rate = 52%, n_estimators = 23%, max_depth = 15%. Final retrain on all 8,000 training samples with best params: Test AUC = 0.907. Gap = 0.005 — small, indicates minimal hyperparameter overfitting. Conclusion: tuning added 3.6 points of AUC on test set; learning rate was by far the most important parameter to tune.

13
  • ×Tuning on the test set: evaluating different hyperparameters using test set performance and picking the best — this fundamentally invalidates the test set as an unbiased performance estimate.
  • ×Not using log-scale for learning rate and regularization: searching learning_rate uniformly in [0.001, 0.3] wastes 90% of trials on the 0.1-0.3 range where most models diverge or perform poorly.
  • ×Reporting the tuning CV score as final performance: after trying 50 configurations, the best CV score is optimistically biased. Report the test set score after retraining with best params.
  • ×Using the model from the best CV fold rather than retraining: the fold model was trained on 80% of training data, not 100%. Always retrain on all training data with the best configuration.
  • ×Not setting random seeds: configurations that use different random initializations are not fairly compared. Set numpy, framework, and model random states consistently across all trials.
  • ×Running grid search when random search would be 5× more efficient: a 5×5×5 grid (125 trials) evaluates redundant combinations. 50 random trials typically finds an equivalent or better configuration.
  • ×Ignoring the search space boundary problem: if the best parameter is at the edge of your range (e.g., best learning_rate = 0.001 at the lower bound), the true optimum is likely below your range — widen it.
  • ×Not saving study results: losing all 80 trial results when Optuna crashes. Always use study = optuna.create_study(storage='sqlite:///study.db') to persist results.
  • ×Saying 'Bayesian optimization always beats random search' — for the first 10-15 trials, random search is better (GP has no useful prior). BO dominates after the surrogate has enough observations.
  • ×Not knowing what an acquisition function is: interviewers expect you to explain the exploration-exploitation trade-off in EI or UCB, not just say 'Bayesian optimization uses a surrogate model.'
  • ×Confusing hyperparameters with model parameters: hyperparameters are set before training; parameters are learned during training. This distinction is fundamental.
  • ×Claiming nested CV is 'just running GridSearchCV inside cross_val_score' without understanding why: the outer loop provides an unbiased estimate because the outer validation fold was never used during the inner hyperparameter selection.
  • ×Data leakage through preprocessing during tuning: fitting StandardScaler or imputer on all training data before the tuning loop, then using these fitted transformers inside each trial. Correct: create a fresh Pipeline inside the objective function that fits preprocessing on the training fold only.
  • ×Tuning hyperparameters for a metric the model won't be deployed on: optimizing validation AUC when the business metric is precision at top-5% recall. Tune on the metric that matters.
  • ×Over-tuning on a stale validation set: collecting new production data, adding it to the training set, but forgetting to update the validation set. The validation set may no longer represent the current data distribution.
  • ×Hyperparameter hunting without baseline comparison: reporting 'we tuned for 200 trials and got AUC=0.91' without reporting what the default AUC was. If defaults give 0.90, the entire tuning effort added only 0.01 AUC.
14

What kind of bias does this model have?

Bias depends on model assumptions and feature expressiveness.

What kind of variance does it have?

Variance grows with model flexibility and weak regularization.

How does it overfit?

Overfitting usually appears as strong train performance but weaker validation/test behavior.

How do we regularize it?

Use complexity constraints, robust validation, and data-centric cleanup.

What kind of data does it like?

Prefers representative, low-leakage data with stable feature definitions.

What kind of data breaks it?

Breaks under leakage, severe distribution drift, noisy labels, and poorly engineered features.

14

Quick Revision Reference

  • Hyperparameters are set before training; parameters are learned during training
  • Grid search: O(∏|Hᵢ|) — exponential in number of hyperparameters, use only for tiny spaces
  • Random search beats grid search when some hyperparameters are unimportant (Bergstra & Bengio 2012)
  • Bayesian optimization (Optuna TPE) is most sample-efficient after ~20 warmup trials
  • Successive halving / HyperBand: allocate more compute to promising configs via early stopping
  • Always tune on log scale for learning rate, regularization — these span orders of magnitude
  • Fix random seeds everywhere for reproducible, fair comparison across configurations
  • After tuning: retrain with best params on ALL training data, then evaluate on test set once
  • FAnova importance identifies which hyperparameters matter — fix unimportant ones to defaults
Grid complexity
Expected Improvement
UCB acquisition
Successive Halving budget
  • Any model whose default hyperparameters are suboptimal for a specific dataset
  • Competitive scenarios (Kaggle, A/B tests) where squeezing last improvements matters
  • When comparing models fairly — each model should be at its best before comparison
  • AutoML pipelines that must configure models without human intervention
  • You're still prototyping — fix the data pipeline first, tune hyperparameters last
  • Training budget is so tight that even one extra run is infeasible
  • Validation set is too small (< 200 samples) — tuning will overfit to validation set noise
  • The improvement from tuning (Δ < 0.005 AUC) doesn't justify the compute cost
Explain why random search beats grid search when hyperparameters differ in importance
Describe a Gaussian Process surrogate: mean prediction + uncertainty quantification
Explain Expected Improvement: exploitation (μ - f+) + exploration (σ·φ(Z))
Explain successive halving: start many configs at low budget, eliminate bottom fraction each round
Know the difference between nested and non-nested CV during tuning
State that after tuning, you retrain on ALL training data with best params
15
16

These questions are designed to break assumptions and expose weak understanding. Most people will answer them wrong on their first attempt. Work through each one carefully.