Interoperate with Optuna¶
Goal: keep your existing Optuna study and your existing dashboard.
Optuna is where most hyperparameter tuning happens, and "rewrite everything" is not a migration plan. atune reads and writes Optuna's own storage formats, so a study can cross in either direction without either tool knowing about the other.
This page is about moving the study. If what you are moving is the source code
— an objective, a sampler argument, a trial.report call — that is
Migrate from Optuna, which maps the two Python APIs onto
each other and names the places where the same line means something else.
Two formats, and the difference matters:
| Format | What it is | atune direction |
|---|---|---|
| Journal file | Optuna's append-only op-log, one JSON object per line | read and write |
| RDB-sqlite | Optuna's relational on-disk database | write only |
Export an atune study to Optuna¶
The command is atune export, and the flags name the format. --optuna PATH writes
a journal file; --optuna-rdb PATH writes the sqlite database. With neither, the
journal goes to stdout. Both may be given at once, each naming its own output — see
the CLI reference for the exact surface, which is generated
from the binary and therefore cannot drift from it.
The RDB output is the one to reach for if the goal is the dashboard:
optuna-dashboard sqlite:///PATH opens it, as does
optuna.load_study(storage="sqlite:///PATH"). Nothing atune-specific is needed on
the Optuna side; the schema is Optuna's own, mirrored from what the installed
version actually writes.
Import an Optuna study into atune¶
atune import <journal> --storage <spec> reads an Optuna journal and reconstructs
the study through atune's storage seam: distributions parsed by parameter name,
categoricals resolved by label, non-finite values decoded from Optuna's string
tokens. It reports what it did as counts, which is how you find out that something
was skipped rather than discovering it later.
The reverse of the RDB path does not exist: atune writes Optuna's database but does not read it. If your study is in an RDB, export it from Optuna to a journal first.
What does not survive the round trip¶
This is the part worth reading before you rely on it. The mapping is faithful where the two models agree and lossy where they do not, and the losses are counted rather than silent:
- Timestamps become import-time. Optuna's own timestamps are not carried across.
- A paused trial exports as
RUNNING. atune'sPausedstate has no Optuna equivalent, so it degrades to the nearest one rather than being dropped. - Worker attribution, retry counts, and multi-seed parent/fan structure are dropped. They have nowhere to go in Optuna's model.
- Wide integer parameters may lose precision. Optuna represents parameter
values internally as
f64, so it cannot preserve every distinct integer above2^53. Round-tripping such values can change an integer; keep Optuna integer ranges within the exact-integer range when exact fidelity matters. - An open search space exports its trials, not its policy. Every trial of
a grown study carries the range it was actually drawn from — the export
writes each trial with its own recorded distribution, so nothing about
what happened is lost — but the declaration itself (
open, the sides, thelimit, the growth knobs) has no Optuna counterpart and is dropped. A re-imported study is therefore a closed one; declare the range open again and you have made a new declaration on a new study, exactly as the write-once rule intends. - A NaN objective becomes a failed trial, which is Optuna's own semantics for it, with a note attribute recording what happened. A NaN intermediate uses Optuna's native encoding and is lossless.
That last pair is not a detail. A NaN written the naive way produces a database Optuna's loader refuses to open — the whole study, not the one trial. Both cases are regression-tested against a real Optuna load.
What has no example on this site¶
Nearly every other how-to here pulls its code from a file under examples/
that CI runs (Read a doctor report is the other
exception, for its own stated reason). This page does not, and the reason is
worth stating rather than hiding:
- The Python binding cannot do this.
atune_pydoes not enable theoptuna-compatfeature and exposes no Optuna symbol, so there is no Python arm to write. - The Rust arm is deferred. It needs a feature-gated example, and the interop
story is better told through the CLI in any case —
atune_clidepends on the facade withoptuna-compatandoptuna-rdbunconditionally, soatune exportworks out of the box with nothing to configure.
So treat the commands above as documented-but-ungated until a CLI case covers them. Everything on this page comes from the generated CLI reference and from the interop implementation's own tests; none of it is a guess. But it is not held true by a test on this page, the way tune any program is, and you are entitled to know which pages carry that guarantee and which do not.
Next¶
- Migrate from Optuna — the other half: the Python API mapping, and the six places a migrated line means something else.
- Inspect a study — atune's own viewers, if the dashboard was the only reason for the round trip.
- Feature reference —
optuna-compatandoptuna-rdb, and what each pulls in. - Storage — the seam import writes through.