Nested runs are useful in the case of Cross-Fold validation or Hyperparameter tuning, when you're performing iterative validation of models.
Take for example:
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score, KFold
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
import numpy as np
import mlflow
import mlflow.sklearn
# Load the iris dataset
iris = load_iris()
X = iris.data
y = iris.target
# Initialize a model
model = LogisticRegression()
# Initialize cross validation
kf = KFold(n_splits=5)
with mlflow.start_run(run_name="Iris Logistic Regression") as parent_run:
# Log parameter, metrics, and model to MLflow
mlflow.log_param("Model", "Logistic Regression")
for fold, (train_index, test_index) in enumerate(kf.split(X)):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model.fit(X_train, y_train)
predictions = model.predict(X_test)
# Start nested MLflow run
with mlflow.start_run(run_name=f"Fold {fold}", nested=True):
# Log metrics
mlflow.log_metric("Accuracy", metrics.accuracy_score(y_test, predictions))
mlflow.log_metric("Precision", metrics.precision_score(y_test, predictions, average='micro'))
mlflow.log_metric("Recall", metrics.recall_score(y_test, predictions, average='micro'))
# Save the model to the current nested run's artifact directory
mlflow.sklearn.log_model(model, "model")
In this example, we want to track the model metrics on each fold, but we want the partitioned fold-level metrics to correspond to the same parent Logistic Regression run. In this way, we keep related nested run information available to the same model.
An HPO example would be similar, with the addition of hyperparameters that are tracked and maybe model artifact checkpoints if you're doing something fancier.