First optimization
This page builds a first Optuna.jl optimization from start to finish. The objective is intentionally small so that the Optuna workflow is visible: create a study, let each trial suggest parameters, report intermediate values, prune weak trials, and inspect the best result.
Setup
Load Optuna.jl and create storage for the study.
using OptunaOptuna separates two kinds of persistence:
storagestores the study, trials, parameter values, and objective values.artifact_storestores files or Julia data associated with a trial.
For a first local run, in-memory study storage is enough. A file-system artifact store is still useful because it shows the same artifact workflow used in larger experiments.
storage = InMemoryStorage()
artifact_store = FileSystemArtifactStore("artifacts")If you want to keep trial history across Julia sessions, use SQLite instead:
storage_url = create_sqlite_url("storage", "first_optimization")
storage = RDBStorage(storage_url)Create the study
A Study owns the optimization direction and the strategy objects used during optimization.
study = Study(
"first-optimization",
artifact_store,
storage;
sampler=TPESampler(seed=123),
pruner=MedianPruner(),
direction="minimize",
load_if_exists=true,
)The sampler chooses new parameter values. The pruner can stop trials early after you report intermediate values. For a first optimization, TPESampler and MedianPruner are good defaults.
Define the objective
An objective function receives a Trial. Each trial asks for parameter values with suggest_int, suggest_float, or suggest_categorical.
function objective(trial::Trial)
x = suggest_float(trial, "x", -10.0, 10.0)
y = suggest_int(trial, "y", -5, 5)
use_offset = suggest_categorical(trial, "use_offset", [true, false])
offset = use_offset ? 2.0 : 0.0
value = Inf
for step in 1:10
progress = step / 10
value = (x - 2.0)^2 + (y + 1)^2 + offset / progress
report(trial, value, step)
if should_prune(trial)
return nothing
end
end
upload_artifact(
study,
trial,
Dict(
"x" => x,
"y" => y,
"use_offset" => use_offset,
"objective_value" => value,
),
)
return value
endReturning nothing marks the trial as pruned. Returning a number completes the trial with that objective value.
Run the optimization
optimize(study, objective; n_trials=30, verbose=true)
println("Best parameters: ", best_params(study))
println("Best value: ", best_value(study))The result should move toward x = 2, y = -1, and use_offset = false, because that combination minimizes the objective.
Where to define the search space
Define the search space inside the objective with suggest_int, suggest_float, and suggest_categorical. This keeps the sampled values close to the code that uses them and also supports conditional spaces, where later suggestions depend on earlier choices.
For larger objectives, move the actual workload into helper functions and keep the Optuna-specific suggestion calls near the top of the objective.
License
Optuna.jl and this documentation page are licensed under the project MIT license. See the License page for the complete license text and the notices for third-party material used elsewhere in the documentation.