Choosing a sampler

Optuna · Practical · 12 min

The sampler is the search algorithm; the right one can halve the trials you need.

The sampler decides which parameters each trial gets. Pass one to create_study(sampler=...).

  • TPESampler (default): Tree-structured Parzen Estimator. Robust, handles conditional and categorical spaces, scales to hundreds or thousands of trials. In Optuna 5 it models parameters jointly (multivariate) by default for single-objective studies.
  • GPSampler: Gaussian-process Bayesian optimization. Very sample-efficient for small budgets (tens of trials) on mostly continuous spaces; heavier per trial and requires PyTorch and SciPy.
  • CmaEsSampler: evolution strategy (needs the cmaes package), strong for continuous parameters with larger budgets; categorical parameters fall back to independent sampling.
  • RandomSampler: a useful baseline and for broad initial exploration.
  • QMCSampler: quasi-random low-discrepancy points, which cover the space more evenly than random.
  • GridSampler(search_space): exhaustive grid when you truly need every combination.
  • NSGAIISampler/NSGAIIISampler: genetic algorithms for multi-objective problems.

Model-based samplers start with n_startup_trials random trials (10 for TPE) before modelling, so tiny budgets behave like random search.

Pass seed= for reproducible sequences in single-process runs. Parallel runs are inherently non-deterministic because trial completion order varies.

Rules of thumb: under ~100 trials with continuous parameters try GPSampler; otherwise TPE. Compare samplers on your problem with a few seeds before committing.

Example

import optuna

optuna.logging.set_verbosity(optuna.logging.WARNING)

def objective(trial):
    x = trial.suggest_float("x", -5, 5)
    y = trial.suggest_float("y", -5, 5)
    return (x - 1) ** 2 + (y + 2) ** 2

samplers = {
    "random": optuna.samplers.RandomSampler(seed=0),
    "tpe": optuna.samplers.TPESampler(seed=0),
    "cmaes": optuna.samplers.CmaEsSampler(seed=0),
    "qmc": optuna.samplers.QMCSampler(seed=0),
}
for name, sampler in samplers.items():
    study = optuna.create_study(sampler=sampler)
    study.optimize(objective, n_trials=60)
    print(f"{name:7} {study.best_value:.4f}")
# model-based tpe and cmaes end much closer to 0 than random or qmc

grid = optuna.samplers.GridSampler({"x": [0, 1, 2], "y": [-2, 0]})
study = optuna.create_study(sampler=grid)
study.optimize(objective)        # stops by itself after all 6 combinations
print(len(study.trials))         # 6

Remember

  • TPE is the robust default; GP is sample-efficient for small continuous problems
  • CMA-ES suits continuous spaces with bigger budgets; Random/QMC are baselines
  • Seed samplers for reproducible single-process runs

Watch out for

  • Comparing samplers with a single seed and tiny budget, where differences are mostly noise.

Check yourself

  1. You can afford only about 30 expensive trials over 5 continuous parameters. Which sampler is a strong first choice?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: optuna.readthedocs.io/en/stable/tutorial/10_key_features/003_efficient_optimization_algorithms.html