What you will be able to do
- Control which tracking server and experiment an MLflow run is logged to
- Log parameters, metrics, tags and artifacts with the MLflow logging API, alongside autologging
- Structure complex experiments as parent and child runs, both with SparkTrials and by hand from distributed Ray tasks
Key concept
Parent and child (nested) runs — A complex experiment is logged as one parent run that groups many child runs. Each child run records one trial, task or iteration with its own parameters and metrics, so related results stay together in a hierarchy you can compare.
1.Runs, experiments, and where they are logged
MLflow tracking is built from three objects. A run is a single execution of model code, and you log parameters and results while it runs. An experiment is a collection of related runs that you can compare and filter. A model is a collection of artifacts that represent a trained model. MLflow 3 adds LoggedModels, which make the model a separate entity that is tracked across training and evaluation runs, not only a file that belongs to one run.
Before you nest runs or log anything custom, you need to know where a run will land. Two settings decide this. The tracking URI picks the server, and on Databricks it defaults to the current workspace's hosted tracking server. The experiment picks which experiment on that server receives the run.
import mlflow
# By default MLflow logs to the Databricks-hosted workspace tracking server. You can connect to a different server using the tracking URI.
mlflow.set_tracking_uri("databricks://remote-workspace-url")
# Set experiment in the tracking server
mlflow.set_experiment("/Shared/my-experiment")The notebook experiment is the default, but it has a limit. A notebook experiment can only receive runs started from inside its own notebook. Runs started from any notebook, or from the APIs, can go to a workspace experiment, which you choose with mlflow.set_experiment("/Shared/name_of_experiment/"). This matters for nested work. When a parent run is on the driver and child runs come from other processes, every participant has to point at the same named experiment.
Checkpoint 1 of 6· Check yourself
A team wants runs from several notebooks and an API-driven script to land in one place. Which choice works?
Only runs started inside a notebook can go to that notebook's experiment. A workspace experiment set with mlflow.set_experiment() accepts runs from any notebook or from the APIs.
“Only MLflow runs initiated within a notebook can be logged to the notebook experiment.”Source: docs.databricks.com
Sources1
2.Logging custom parameters, metrics, tags and artifacts
Each run stores the notebook that launched it, any models it created, parameters and metrics as key-value pairs, tags for run metadata, and artifacts (output files). On the run page, saved artifacts appear in the Artifacts tab.
You can fill a run in two ways. Autologging is the easiest. Databricks Autologging records parameters, metrics and model lineage for supported frameworks in interactive notebooks. For Spark ML, the PySpark ML autologger is the one that is on by default. The MLflow logging API gives you control, and it is how you record anything a framework cannot know about: a business metric, an extra parameter, a plot, or a CSV file.
The rule that trips people up is that Databricks Autologging does not apply to a run you open yourself with mlflow.start_run(). To get both autologged content and your own values in that run, call mlflow.autolog(exclusive=False) first. Then log your own values before and after training, inside the same run.
import mlflow
mlflow.autolog(exclusive=False)
with mlflow.start_run():
mlflow.log_param("example_param", "example_value")
# <your model training code here>
mlflow.log_metric("example_metric", 5)Checkpoint 2 of 6· Put it in order
Put these steps for adding custom content to an autologged run in order
- 1.Call mlflow.autolog() with exclusive=False
- 2.Train one or more models in a framework supported by Databricks Autologging
- 3.If you did not use a with block, end the run with mlflow.end_run()
- 4.Track post-training content with methods such as mlflow.log_metric()
- 5.Start an MLflow run with mlflow.start_run()
- 6.Track pre-training content with methods such as mlflow.log_param()
Databricks documents this exact sequence. Parameters are logged before training and metrics after, all inside one run that autologging is also writing to.
“Use MLflow Tracking methods, such as mlflow.log_param(), to track pre-training content.”Source: docs.databricks.com
After runs are logged, you can query them in code. The MLflow client's search_runs API returns a pandas DataFrame, and the MLflow experiments data source returns a Spark DataFrame. This is how you compare child runs or build dashboards over them.
Checkpoint 3 of 6· Exam question
A data science team is using Optuna to tune hyperparameters for a gradient boosting model in a Databricks notebook. They want every trial's parameters and metrics logged as a distinct MLflow run, but all trials should be grouped visually under a single parent run representing the overall tuning job. Which approach achieves this?
Correct answer: A — Wrap the tuning loop in `mlflow.start_run()` to open the parent run, then call `mlflow.start_run(nested=True)` inside the objective function so each trial becomes a child run.
- A. Passing `nested=True` while a parent run is active creates a true parent-child relationship, so the tracking UI and `search_runs` API group each trial's run beneath the tuning job's parent run automatically.
- B. Reusing a single run object across every trial merges all trials' metric histories into one run, so individual trial results overwrite or blend together instead of staying separable.
- C. Creating a new experiment per trial scatters the trials across unrelated top-level containers; experiments are not nested inside each other, so this cannot reproduce a parent-child grouping.
- D. A tag on rows within one run is a manual workaround that never produces independent per-trial run objects with their own metric histories, unlike genuine nested runs.
Checkpoint 4 of 6· Exam question
A team trains three different base learners (a random forest, a gradient boosted tree, and a linear model) and then combines their predictions into a stacked ensemble. They want the MLflow experiment to show one top-level run for the ensemble and three linked runs underneath it, one per base learner. Which pattern satisfies this requirement?
Correct answer: A — Open the ensemble run with `mlflow.start_run()`, then inside it call `mlflow.start_run(run_name="base_learner", nested=True)` once per base learner to create three child runs.
- A. Calling `start_run(nested=True)` while the ensemble run is active links each base learner's run to it as a child, so the tracking UI displays the three runs nested beneath the ensemble run.
- B. Tagging independent top-level runs does not create an actual hierarchy; the three runs remain siblings in the run list and must be manually joined by the tag rather than shown nested.
- C. Prefixing metric names inside a single run mixes every base learner's history into one run's metric charts, which loses the ability to compare each model as its own tracked run.
- D. Registering model versions in Model Registry tracks deployment and lineage of already-trained artifacts, not the experiment-tracking run hierarchy needed while training the base learners.
3.Nested runs for complex experiments
Hyperparameter search is the standard example of a complex experiment: one search, many trials. Logging each trial as its own top-level run scatters the results. Nesting puts the search in a parent run and each trial in a child run under it.
| Situation | What gets logged |
|---|---|
| The fmin() call | The main (parent) run |
| Each hyperparameter setting tested | A child run under the main run, which also holds MLflow log records from workers |
| An active run exists when fmin() is called | SparkTrials logs to it and does not end it when fmin() returns |
| No active run exists | SparkTrials creates a new run, logs to it, and ends it before fmin() returns |
| fmin() is called several times in one active run | All calls log to the same main run, and MLflow appends a UUID to parameter and tag names that conflict |
Databricks therefore recommends wrapping each fmin() call in its own with mlflow.start_run():. That gives every search its own parent run, where you can add extra tags, parameters or metrics. Inside the objective function, you do not manage runs: calling mlflow.log_param(...) there writes to the trial's child run.
SparkTrials is still worth knowing as a pattern, but it is not the current tool. Hyperopt is not included in Databricks Runtime for Machine Learning after 16.4 LTS ML. Databricks recommends Optuna for single-node tuning and Ray Tune for distributed tuning.
Without a library that builds the hierarchy for you, you nest runs by hand. The Ray pattern shows how. Start the parent run on the driver. Pass its run_id to each task. In each task, set the credentials and the experiment, then open a child run with nested=True.
@ray.remote
def ray_task(x, run_id):
import os
# Set the MLflow credentials within the Ray task
os.environ.update(mlflow_db_creds)
# Set the active MLflow experiment within each Ray task
mlflow.set_experiment(experiment_name)
# Create nested child runs associated with the parent run_id
with mlflow.start_run(run_id=run_id, nested=True):
# Log metrics to the child run within the Ray task
mlflow.log_metric("x", x)
return x
# Start parent run on the main driver process
with mlflow.start_run() as run:
# Pass the parent run's run_id to each Ray task
results = ray.get([ray_task.remote(x, run.info.run_id) for x in range(10)])Checkpoint 5 of 6· Check yourself
Child runs from Ray tasks are not showing up under the parent run. Which two things must each Ray task receive for the parent-child relationship to work?
Ray tasks run in separate processes. Each one needs Databricks credentials (from get_databricks_env_vars) and the parent's run_id to create a child run under it.
“ensure that each Ray task receives the necessary client credentials and the parent run_id.”Source: docs.databricks.com
Ray Tune follows the same pattern. A parent run on the driver wraps the tuner, and each trial's training function opens mlflow.start_run(run_id=run_id, nested=True) and logs its metrics on every step. Finally, nesting multiplies runs and metric steps quickly. MLflow enforces quotas on total parameters, tags, metric steps and runs per experiment. If you reach the runs-per-experiment limit, Databricks recommends deleting runs you no longer need.
Checkpoint 6 of 6· Exam question
A team performs 5-fold cross-validation for a classifier and wants each fold's metrics logged separately while still being able to roll results up under one parent run per model configuration. Which of the following statements about implementing this with MLflow nested runs are correct?(Select 3)
Correct answers: A, B, D — Opening the parent run first and calling `mlflow.start_run(nested=True)` inside the fold loop creates one child run per fold, holding that fold's own metrics.; The parent run can log the averaged cross-validation metric, such as mean AUC, after the fold loop finishes, kept separate from each individual fold's metric values.; Calling `mlflow.search_runs()` with a filter on the `mlflow.parentRunId` tag returns only the fold-level child runs that belong to that specific parent run.
- A. Because the parent run is already active, wrapping each fold's training in a nested `start_run` call produces a distinct child run object per fold with its own isolated metric history.
- B. Metrics logged directly to the still-active parent run, such as an aggregate mean AUC computed after the loop, live on the parent run and stay independent of any child run's own metrics.
- C. Child runs are separate run objects with their own metric storage; they do not overwrite the parent run's metrics, so this describes behavior that nested runs do not exhibit.
- D. MLflow automatically tags every nested run with its parent's run ID, so filtering `search_runs` on that tag is the documented way to retrieve exactly the child runs of one parent.
- E. Nested runs share the same experiment as their parent by default; splitting folds across separate experiments is unnecessary and would actually break the parent-child grouping in the UI.
- F. The `nested` argument belongs to `mlflow.start_run()`, which is what establishes the parent-child link; `log_metric()` has no `nested` parameter and simply logs to whichever run is currently active.
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Databricks Autologging automatically fills any run, including one you open yourself with mlflow.start_run().Why is that wrong?
Autologging does not apply to runs created with the fluent mlflow.start_run(). Call mlflow.autolog() (with exclusive=False to mix in your own logging) before you start the run.
Covered in Logging custom parameters, metrics, tags and artifacts
2.SparkTrials always opens and closes its own parent run, so wrapping fmin() in start_run() adds nothing.Why is that wrong?
If a run is already active, SparkTrials logs to it and leaves it open, so you can add tags or metrics to it afterwards. It only creates and ends its own run when no run is active.
Covered in Nested runs for complex experiments
3.Hyperopt with SparkTrials is the current Databricks recommendation for distributed tuning.Why is that wrong?
Hyperopt is no longer shipped in Databricks Runtime ML after 16.4 LTS. Databricks recommends Optuna for single-node tuning and Ray Tune for distributed tuning.
Covered in Nested runs for complex experiments
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://docs.databricks.com/aws/en/mlflow/trackingOfficial docs
“A run is a single execution of model code.”
↩︎ Runs, experiments, and where they are logged“Tracking URI: Determines which server to use (defaults to current Databricks workspace)”
↩︎ Runs, experiments, and where they are logged“MLflow runs launched from any notebook or from the APIs can be logged to a workspace experiment.”
↩︎ Runs, experiments, and where they are logged“to log additional artifacts such as CSV files or plots, use the MLflow logging API”
↩︎ Logging custom parameters, metrics, tags and artifacts“The MLflow Python client search_runs API returns a pandas DataFrame.”
↩︎ Logging custom parameters, metrics, tags and artifacts“If you hit the runs per experiment quota, Databricks recommends you delete runs that you no longer need”
↩︎ Nested runs for complex experiments“Only MLflow runs initiated within a notebook can be logged to the notebook experiment.”
↩︎ Checkpoint - 2.https://docs.databricks.com/aws/en/mlflow/runsOfficial docs
“model parameters and metrics saved as key-value pairs, tags for run metadata, and any artifacts, or output files, created by the run.”
↩︎ Logging custom parameters, metrics, tags and artifacts - 3.
“use MLflow PySpark ML autologging by calling mlflow.pyspark.ml.autolog(), which is enabled by default with Databricks Autologging.”
↩︎ Logging custom parameters, metrics, tags and artifacts - 4.https://docs.databricks.com/aws/en/machine-learning/automl-hyperparam-tuning/hyperopt-conceptsOfficial docs
“Call mlflow.log_param("param_from_worker", x) in the objective function to log a parameter to the child run.”
↩︎ Nested runs for complex experiments - 5.https://docs.databricks.com/gcp/en/machine-learning/automl-hyperparam-tuning/hyperopt-conceptsOfficial docs
“Databricks recommends using either Optuna for single-node optimization or RayTune for a similar experience”
↩︎ Nested runs for complex experiments“If there is no active run, SparkTrials creates a new run, logs to it, and ends the run before fmin() returns.”
↩︎ Exam trap 2“Hyperopt is not included in Databricks Runtime for Machine Learning after 16.4 LTS ML.”
↩︎ Exam trap 3“If there is an active run, SparkTrials logs to this active run and does not end the run when fmin() returns.”
↩︎ Prediction - 6.
“Each Ray Tune task creates a child run under the parent run, maintaining a clear hierarchy of experiment results.”
↩︎ Nested runs for complex experiments“This run acts as a hierarchical container for all subsequent child runs.”
↩︎ Key concept“ensure that each Ray task receives the necessary client credentials and the parent run_id.”
↩︎ Checkpoint
Also cited
“Databricks Autologging is not applied to runs created using the MLflow fluent API with mlflow.start_run().”
↩︎ Exam trap 1“Use MLflow Tracking methods, such as mlflow.log_param(), to track pre-training content.”
↩︎ Checkpoint“If no experiment is active, Databricks creates a notebook experiment.”
↩︎ Prediction