pdmlabs.optimization.optuna_adapter#

Optuna 5 TPE optimizer adapter for PdMLabs.

All optuna imports are lazy so this module is importable even when optuna is not installed. Install with:

pip install pdmlabs[optuna]          # installs optuna>=5.0.0

The adapter uses optuna.create_study + study.optimize as the single entry point, with:

  • TPESampler(seed=42, multivariate=True, constant_liar=True) – multivariate mode models joint distributions over all hyperparameters; constant_liar enables meaningful multi-process coordination by treating in-flight trials as if they returned the current best value. (Both are the new defaults in Optuna 5.0, but specified explicitly here for clarity and forward compatibility.)

  • JournalStorage(JournalFileBackend) – a file-backed log that allows multiple independent worker processes to share a single study without an RDB server.

Parallelism model (mirrors GPyOpt adapter)#

joblib.Parallel(n_jobs=n_jobs, backend=”loky”) spawns n_jobs worker processes. Each process connects to the shared JournalStorage file and calls study.optimize(n_trials=trials_per_worker). The file uses OS-level file locks, so concurrent writes are safe on a single machine.

Space conversion rules (all preserve exact candidate sets for lists):
  • list[int | float | bool | str | mixed] -> suggest_categorical(name, values)

  • rv_frozen -> suggest_float(name, ppf(0.01), ppf(0.99))

Serialization note#

joblib’s loky backend uses cloudpickle (not stdlib pickle), so closures that capture self – such as the optimization_objective defined inside execute() – are serializable without any special handling.

Writes to self.extra_metrics or self.best_pipeline inside a worker subprocess update a deserialized copy of self that is discarded when the process exits. Experiments therefore report per-trial artifacts through pdmlabs.optimization.trial_sink.TrialSink – a filesystem channel the objective closure carries into the workers – rather than by assigning to self. Adapter correctness is unaffected either way: the return dict (best_params, best_objective) is built from the shared JournalStorage read back in the main process after all workers finish.

Classes

OptunaAdapter()

Adapter for Optuna 5 TPE (optuna>=5.0.0).

class pdmlabs.optimization.optuna_adapter.OptunaAdapter#

Bases: BaseOptimizerAdapter

Adapter for Optuna 5 TPE (optuna>=5.0.0).

Uses TPESampler(seed=42, multivariate=True, constant_liar=True) (both now the defaults in Optuna 5.0) and a JournalStorage file created on the fly for GIL-free multi-process parallelism via joblib.Parallel(backend='loky').

Requires optuna >= 5.0.0 (pip install pdmlabs[optuna]).

Parallelism#

n_jobs independent worker processes each run floor(n_iterations / n_jobs) trials, sharing a single study via a temporary JournalStorage log file (file-locked, safe on a single machine). The temp file is deleted after the run.

constant_liar=True instructs the TPE sampler to treat in-flight (not yet complete) trials as if they returned the current best value, enabling diverse candidate proposals across concurrent workers.

maximize(param_space: dict, objective_fn, n_iterations: int, n_jobs: int, initial_random: int, constraint_fn=None) dict#

Maximise objective_fn using Optuna TPE.

minimize(param_space: dict, objective_fn, n_iterations: int, n_jobs: int, initial_random: int, constraint_fn=None) dict#

Minimise objective_fn using Optuna TPE.

supports_categorical: bool = True#