Hyperparameter Selection › Hyperparameter Search

Michael BrenndoerferJanuary 29, 202613 min read
Language AI HandbookAll chapters
Part 32 of 67Training Optimization
Chapter 238Hyperparameter Selection › Hyperparameter Search
Reading section 3 of 14 · Hyperparameter Search · 13 minSection 3 of 14 · 13 min

Book contents

Section 3 of 14 · 13 min read

Hyperparameter Selection › Hyperparameter SearchOne section · Sections in this chapter3 / 14 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Hyperparameter search is the process of finding configurations that perform well by evaluating multiple candidates. The right search strategy depends on your computational budget, the number of hyperparameters you are tuning, and how smooth the loss landscape is as a function of those parameters.

Grid search evaluates every point on a regular grid over the hyperparameter space. If you want to test three learning rates and four weight decay values, grid search runs twelve experiments covering all combinations. It is exhaustive and reproducible, with results that are easy to reason about.

The problem is combinatorial explosion. Adding one more dimension to search multiplies the number of experiments by the number of values in that dimension. A grid over six hyperparameters with five values each requires 56=15,6255^6 = 15{,}625 experiments. This is practical only for one or two hyperparameters or when each experiment is very cheap.

Grid search also wastes resources on less important dimensions. If learning rate matters a lot and weight decay barely matters, half your grid experiments vary weight decay while holding learning rate fixed at a bad value. You get many evaluations at useless configurations. The structure that makes grid search appealing, its exhaustiveness over the chosen axes, becomes a liability when the axes are not equally important, which is virtually always the case in practice.

Random search samples configurations uniformly at random from the hyperparameter space. Instead of a regular grid, you get scattered points. This sounds less systematic, but it is typically more efficient than grid search for the following reason: most hyperparameter landscapes have low intrinsic dimensionality. A few dimensions matter a lot and the rest matter little. In a grid, you spend 1/N1/N of your evaluations on each unique value of an important dimension; in random search, every evaluation uses a different value of that important dimension, so you explore it more thoroughly.

The seminal result from Bergstra and Bengio (2012) showed that random search finds equally good or better configurations than grid search using far fewer evaluations, especially when the number of relevant hyperparameters is small relative to the total number being tuned. For practical LLM training, where you might have fifteen hyperparameters but only three or four that substantially affect the outcome, random search is a natural choice.

Random Search Efficiency

The efficiency gain of random search over grid search is proportional to the ratio of total hyperparameters to important hyperparameters. If 3 out of 10 hyperparameters are important, random search explores the important dimensions roughly 3x more efficiently than grid search at the same compute budget.

Random search is embarrassingly parallel: all trials are independent and can run simultaneously. With a fixed budget of, say, 50 experiments, you can evaluate all 50 in parallel if you have the hardware. This property is invaluable in large-scale LLM work, where parallelizing across many GPUs is the norm.

The main limitation of random search is that it does not learn from previous evaluations. Each new sample is drawn independently of all past results, so random search cannot refine its search around promising regions. If the loss landscape has a sharp, narrow optimum, you may need many samples to hit it by chance. This observation motivates the next step in the progression: adaptive search methods that use past results to guide future queries.

Bayesian Optimization

Bayesian optimization treats hyperparameter search as a sequential decision problem. After each experiment, it updates a probabilistic model of how performance depends on the hyperparameter configuration and uses that model to choose the next configuration to evaluate. The key idea is to balance exploitation (trying configurations near the best found so far) with exploration (trying configurations in regions we know little about).

The probabilistic model is typically a Gaussian process or a tree-structured Parzen estimator (TPE). The model outputs a predicted performance and an uncertainty estimate. The next configuration is chosen by maximizing an acquisition function that combines expected performance with uncertainty. Common acquisition functions include:

  • Expected Improvement (EI): the expected amount by which the next trial improves over the current best
  • Upper Confidence Bound (UCB): predicted performance plus a scaled uncertainty term
  • Thompson Sampling: sample one function from the posterior and maximize it

Each of these acquisition functions encodes a different strategy for balancing exploitation and exploration. EI focuses on configurations likely to beat the current best. UCB adds a bonus for poorly-explored regions. Thompson Sampling introduces randomness by sampling a plausible objective function and optimizing it, which naturally diversifies exploration without needing a manually tuned exploration coefficient.

Bayesian optimization tends to find good configurations in fewer evaluations than random search, particularly for expensive objectives. The cost is that each selection step requires fitting a surrogate model and solving an inner optimization. For problems where each evaluation costs hours, this overhead is negligible.

The limitation is sequential dependency: Bayesian optimization selects one configuration at a time based on previous results. In practice, most teams run experiments in parallel batches, which breaks the strict sequential assumption. Asynchronous variants like hyperopt and Optuna handle this by selecting multiple candidates using the current surrogate model without waiting for all running trials to finish. They use a "lie" strategy: they pretend that currently running trials have already returned some expected result and use this fictitious observation to select the next batch of candidates.

For LLM training, the high cost of individual evaluations makes Bayesian optimization appealing in principle, but the small number of feasible trials (often fewer than 30 at a given scale) limits the surrogate model's accuracy. In this regime, the advantage over random search is modest, and many practitioners use random search for simplicity with Bayesian optimization reserved for settings where even a few evaluations is prohibitively expensive.

Early Stopping and Successive Halving

Even with efficient search strategies, each trial trains a full model to completion before reporting its final performance. This is wasteful: a configuration with a learning rate ten times too large will diverge within the first thousand steps, yet a naive approach spends a full training run confirming that fact.

Early stopping cuts this waste by terminating runs that fall behind early. At fixed intervals during training, you compare all running configurations; those that perform significantly below the current best are terminated, and their compute is reallocated to the more promising survivors. This is not always safe (some good configurations start slowly before finding their footing) but works well when early performance correlates with final performance, which is generally true for learning rate sensitivity.

Successive halving formalizes early stopping into a systematic elimination protocol. It dramatically reduces cost by training all candidates for a short period, discarding the worst half, doubling the resources for the survivors, and repeating until one winner remains.

Formally, given nn initial configurations and a total budget BB, successive halving proceeds as:

Round 1: train all n configs for B/(nlog⁡2n) steps, keep top n/2Round 2: train surviving n/2 configs for 2B/(nlog⁡2n) steps, keep top n/4⋮Round log⁡2n: train final 2 configs, return winner\begin{aligned} &\text{Round 1: train all } n \text{ configs for } B/(n \log_2 n) \text{ steps, keep top } n/2 \\ &\text{Round 2: train surviving } n/2 \text{ configs for } 2B/(n \log_2 n) \text{ steps, keep top } n/4 \\ &\vdots \\ &\text{Round } \log_2 n: \text{ train final 2 configs, return winner} \end{aligned}

where:

  • nn: the number of initial configurations
  • BB: total compute budget in steps (or flops)
  • log⁡2n\log_2 n: number of elimination rounds

The assumption is that good configurations are identifiable early in training. This holds reasonably well for learning rate (divergent runs fail quickly) but less well for regularization (the effect of weight decay often only appears after substantial training). When performance rankings correlate between early and late training, successive halving finds nearly-optimal configurations with a fraction of the total compute.

Hyperband extends successive halving by running it with multiple values of nn, trading off between getting more configurations (wide, shallow search) and training each longer (narrow, deep search). With a large nn, you screen many candidates quickly but eliminate promising slow-starters too early. With a small nn, each survivor gets more training but you start with fewer candidates. Hyperband hedges by running multiple brackets simultaneously, each with a different nn, then selecting the best result across all brackets. This makes Hyperband more robust to the assumption that early performance predicts final performance.

The practical significance of Hyperband is substantial. In a controlled comparison, Hyperband with a total compute budget of BB frequently outperforms running random search for the same BB on a single configuration, because it can explore far more of the hyperparameter space in the early rounds while still committing full resources to the best candidates. For LLM pretraining where individual runs are expensive, Hyperband-style thinking should guide how you allocate your search budget.

Practical Search Protocol for LLMs

For large language model training, a practical search protocol takes into account that individual runs are expensive and that a small number of hyperparameters dominate performance:

  1. Identify proxy tasks: Use a small model (a few hundred million parameters at most) trained on a representative data sample for a small number of steps. If the proxy correlates with full-scale performance, this drastically reduces search cost.

  2. Fix cheap defaults first: Set architecture-linked hyperparameters (layer count, hidden size, attention heads) by scaling laws. Fix dropout to 0 for the pretraining phase. These are not search dimensions.

  3. Search learning rate: This is the most critical hyperparameter. Run random search over two to three orders of magnitude around a reasonable prior (discussed below in defaults). Use the proxy model and early stopping.

  4. Search weight decay: After finding a good learning rate, search weight decay in a one-dimensional sweep.

  5. Search batch size: Batch size interacts with learning rate. If you change batch size substantially, re-verify the learning rate.

  6. Verify on target scale: Confirm the best configuration found at proxy scale transfers to the target scale before committing to a full training run.

In[3]:
Code
from itertools import product

import numpy as np

# Simulate a grid search vs random search comparison
# We model the loss landscape as a function of learning rate and weight decay
# where only learning rate matters significantly

rng = np.random.default_rng(42)


def simulated_loss(lr, wd, noise_scale=0.05):
    """
    Simulated loss that depends strongly on lr and weakly on weight decay.
    Optimal lr is around 3e-4, optimal wd is around 1e-2.
    """
    lr_log = np.log10(lr)
    wd_log = np.log10(wd)
    lr_component = (lr_log - np.log10(3e-4)) ** 2 * 4.0
    wd_component = (wd_log - np.log10(1e-2)) ** 2 * 0.1  # weak dependence
    noise = rng.normal(0, noise_scale)
    return 2.5 + lr_component + wd_component + noise


# Grid search: 5 lrs x 5 wds = 25 evaluations
lr_grid = np.logspace(-5, -2, 5)
wd_grid = np.logspace(-4, -1, 5)

grid_results = []
for lr, wd in product(lr_grid, wd_grid):
    loss = simulated_loss(lr, wd)
    grid_results.append((lr, wd, loss))

grid_results.sort(key=lambda x: x[2])
best_grid = grid_results[0]
unique_lrs_explored_grid = len(set(r[0] for r in grid_results))

# Random search: 25 evaluations, same budget
lr_samples = np.power(10, rng.uniform(-5, -2, 25))
wd_samples = np.power(10, rng.uniform(-4, -1, 25))

random_results = []
for lr, wd in zip(lr_samples, wd_samples):
    loss = simulated_loss(lr, wd)
    random_results.append((lr, wd, loss))

random_results.sort(key=lambda x: x[2])
best_random = random_results[0]
unique_lrs_explored_random = len(set(f"{r[0]:.2e}" for r in random_results))
Out[4]:
Console
Grid search (25 evaluations):
  Best LR: 3.16e-04, Best WD: 3.16e-03, Loss: 2.5304
  Unique LR values explored: 5

Random search (25 evaluations):
  Best LR: 2.67e-04, Best WD: 4.96e-03, Loss: 2.5436
  Unique LR values explored: 24

Random search found a comparable configuration
Loss difference: 0.0132

Grid search fixes the values of each dimension at predetermined points. When the important dimension (learning rate) has its optimum between grid points, grid search can miss it entirely. Random search spreads evaluations across continuous ranges of both dimensions, exploring more of the learning rate axis and finding configurations closer to the true optimum. In practice, this advantage grows with the number of unimportant hyperparameters: each grid dimension you add multiplies compute requirements without helping you find the optimal value for the important dimensions.

Out[5]:
Visualization
Contour map of simulated validation loss with 25 grid-search evaluations arranged in five columns, a star marking the best grid point, and a vertical line at the true learning-rate optimum.
Grid search evaluates 25 combinations but samples only five distinct learning rates. The simulated optimum at log10(LR)=-3.2 falls between columns, so the best grid point remains visibly above the minimum loss.
Out[6]:
Visualization
Contour map of simulated validation loss with 25 randomly scattered evaluations, a star marking the best random point, and a vertical line at the true learning-rate optimum.
Random search uses the same 25-evaluation budget but samples 25 distinct learning rates. Its best point lands close to the simulated optimum and reaches a lower loss than the coarse grid.