Budgets, callbacks and enqueued trials

Optuna · Practical · 10 min

Real tuning runs need time budgets, early stopping of the whole study, and a head start from prior knowledge.

study.optimize stops when either limit is reached:

  • n_trials=100: number of trials in this call (not counting earlier ones in a resumed study).
  • timeout=3600: seconds; the running trial finishes, no new one starts.

With neither, it runs until interrupted or study.stop() is called.

Callbacks are functions callback(study, frozen_trial) called after each trial, passed via optimize(..., callbacks=[...]). Uses include logging to your experiment tracker, saving the best model, or stopping when no improvement happened for N trials by calling study.stop(). optuna.study.MaxTrialsCallback(n, states=...) caps the total number of trials across all workers sharing a storage.

Enqueue known configurations with study.enqueue_trial({"lr": 1e-3, "depth": 6}) before optimizing. The next trial uses those values instead of sampling (missing parameters are sampled), so defaults or previous best results are evaluated first and give the sampler a strong starting point.

Other useful options:

  • show_progress_bar=True for a tqdm bar.
  • gc_after_trial=True to run garbage collection between memory-heavy trials.
  • study.add_trial(optuna.trial.create_trial(params=..., distributions=..., value=...)) to import results computed outside Optuna.

Example

import optuna

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

def objective(trial):
    x = trial.suggest_float("x", -10, 10)
    return (x - 2) ** 2

class StopWhenStale:
    def __init__(self, patience):
        self.patience = patience
    def __call__(self, study, trial):
        if trial.number - study.best_trial.number >= self.patience:
            study.stop()                     # no improvement for `patience` trials

study = optuna.create_study(sampler=optuna.samplers.TPESampler(seed=0))
study.enqueue_trial({"x": 1.5})              # evaluate a known-good guess first
study.optimize(objective, n_trials=500, timeout=60, callbacks=[StopWhenStale(25)])

print(study.trials[0].params)                # {'x': 1.5}
print(len(study.trials) < 500)               # True: stopped early by the callback

Remember

  • n_trials and timeout bound a run; study.stop() ends it from a callback
  • Callbacks receive (study, frozen_trial) after every trial
  • enqueue_trial evaluates chosen parameters before sampling starts

Watch out for

  • Expecting timeout to interrupt a running trial; it only prevents new trials from starting.

Check yourself

  1. What does study.enqueue_trial({'lr': 0.001}) do?

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/20_recipes/008_specify_params.html