OptunaMLflow
See also
Code documentation can be found here: code documentation page
OptunaMLflow
is a wrapper to use Optuna and
log to MLflow at the
same time. If an exception occurs during communication with MLflow, it is caught and handled
without interrupting the training process. The OptunaMLflow
class
is used as a decorator for Optuna objective functions.
It looks like this:
from hpoflow import OptunaMLflow
import optuna
@OptunaMLflow()
def objective(trial):
x = trial.suggest_float("x", -10, 10)
return (x - 2) ** 2
study = optuna.create_study()
study.optimize(objective, n_trials=100)
If this decorator is applied the Optuna optuna.study.Study
object is augmented.
This augmentation entails logging information to Optuna
and MLflow in parallel.
Autologging to MLflow
You can use Optuna and the Trial object as you are used to. The following is automatically logged in parallel:
the Optuna distributions and parameters (name and ranges)
the sampled hyperparameters
the objective result
exceptions with traceback
the direction of the study (
MINIMIZE
orMAXIMIZE
)hostname and process id
Manual Logging
In addition to what is logged automatically by Optuna usage, the following can be logged manually:
additonal metrics:
log_metric()
orlog_metrics()
parameter:
log_param()
orlog_params()
tags:
set_tag()
orset_tags()
Note
The manually logged information is stored by Optuna as a user attribute on the
Trial
object (also see set_user_attr()
).
Logging Nested Runs
Sometimes you want to repeat a training several times with the same hyperparameters within a trial.
This is the case, for example, when performing a cross-validation.
It is possible to log the results of these repetitions as so-called nested runs on the MLflow side.
To do this use the log_iter()
method.
It looks like this:
from hpoflow import OptunaMLflow
import numpy as np
import optuna
@OptunaMLflow()
def objective(trial):
x = trial.suggest_uniform("x", -10, 10)
results = []
for i in range(7): # simulate 7 fold cross-validation
result = (x - 2) ** 2
trial.log_iter({"fold_result": result}, i) # call to log the fold as nested run
results.append(result)
result = np.mean(results)
return result # auto logging - no explicit call to log_metric needed
study = optuna.create_study()
study.optimize(objective, n_trials=100)
Note
Optuna does not support nested runs. That is why the results are aggregated into lists when they are stored as user attributes at Optuna.
Set MLflow Tracking Server URI
By passing tracking_uri
to the constructor of OptunaMLflow
you can set the MLflow tracking server URI (also see mlflow.set_tracking_uri()
).
The values can be:
not set or
None
: MLflow logs to the default locale folder./mlruns
or uses theMLFLOW_TRACKING_URI
environment variable if it is available.local file path, prefixed with
file:/
: Data is stored locally at the provided directory.HTTP URI like
https://my-tracking-server:5000
Databricks workspace, provided as the string
databricks
or, to use a Databricks CLI profile,databricks://<profileName>
Enforce no uncommitted GIT Changes
By passing enforce_clean_git=True
to the constructor of
OptunaMLflow
you can check and enforce that the
GIT repository has no uncommitted changes (see git.repo.base.Repo.is_dirty()
).
If there are uncommitted GIT changes an exception is raised.
In this way, reproducibility of experiments is facilitated.