Visualizing studies and importance

Optuna · Practical · 10 min

Plots reveal which parameters matter, whether the study converged and whether ranges need adjusting.

optuna.visualization builds interactive Plotly figures (and optuna.visualization.matplotlib the same plots for Matplotlib). Each takes a study and returns a figure you can .show() or save.

  • plot_optimization_history(study): objective value per trial with the best-so-far line. A flat best line means diminishing returns.
  • plot_param_importances(study): how much each parameter explains the objective's variation. Focus future tuning on the top few and fix the rest.
  • plot_slice(study): objective against each parameter. If good trials cluster at a range edge, widen the range.
  • plot_contour(study, params=["lr", "depth"]): interaction between two parameters.
  • plot_parallel_coordinate(study): all parameters at once.
  • plot_intermediate_values(study): learning curves of reported values, useful for checking pruning.
  • plot_pareto_front(study): for multi-objective studies.
  • plot_timeline(study): when each trial ran, revealing parallelism and stragglers.

The numbers behind the importance plot come from optuna.importance.get_param_importances(study), which uses fANOVA by default; PedAnovaImportanceEvaluator is a fast alternative focusing on what distinguishes top trials.

Importance is relative to the ranges you searched: a parameter can look unimportant because its range was too narrow to matter.

Example

import optuna

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

def objective(trial):
    lr = trial.suggest_float("lr", 1e-4, 1e-1, log=True)
    depth = trial.suggest_int("depth", 1, 10)
    noise = trial.suggest_float("unused_noise", 0, 1)   # barely matters
    return (lr * 100 - 1) ** 2 + (depth - 6) ** 2 * 0.5 + noise * 0.01

study = optuna.create_study(sampler=optuna.samplers.TPESampler(seed=0))
study.optimize(objective, n_trials=80)

imp = optuna.importance.get_param_importances(study)
print(list(imp)[-1])            # unused_noise  (least important)

fig = optuna.visualization.plot_optimization_history(study)
fig.write_html("history.html")  # or fig.show() in a notebook
optuna.visualization.plot_param_importances(study).write_html("importance.html")
optuna.visualization.plot_slice(study, params=["lr", "depth"]).write_html("slice.html")

Remember

  • History, importance, slice and contour plots answer different questions
  • Use importances to decide which parameters to keep tuning
  • Good trials at a range edge mean the range should be widened

Watch out for

  • Concluding a parameter does not matter when its searched range was simply too narrow.

Check yourself

  1. The slice plot shows all good trials at max_depth = 32, the top of the range. What should you 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/10_key_features/005_visualization.html