Welcome to Chapter 11! In our journey through Databricks, we’ve explored data ingestion, transformation, and analysis. Now, we’re ready to dive into the exciting world of Machine Learning (ML) and, more specifically, how to manage the entire ML lifecycle effectively. Building a great model is one thing, but making it reliable, reproducible, and ready for production is another challenge entirely.
This chapter introduces you to MLflow, an open-source platform designed to streamline machine learning development, from experimentation to deployment. You’ll learn how to track experiments, package code, manage models, and even deploy them, ensuring your ML projects are organized, transparent, and scalable. We’ll build upon your existing knowledge of Databricks notebooks and Python, so get ready to bring your ML ideas to life with robust lifecycle management!
What is MLflow and Why Does it Matter?
Imagine you’re a scientist running multiple experiments in a lab. You try different ingredients, adjust temperatures, and observe outcomes. If you don’t meticulously record every detail – what you did, when you did it, and what happened – how can you ever reproduce your best results or explain why one experiment failed and another succeeded?
In the world of Machine Learning, this “lab notebook” problem is even more complex. You’re dealing with different datasets, various algorithms, countless hyperparameters, and evolving codebases. Without a structured way to manage all these moving parts, your ML projects can quickly become chaotic. This is where MLflow comes in!
MLflow is an open-source platform for managing the end-to-end machine learning lifecycle. It addresses four key challenges:
- Tracking Experiments: Keeping a record of every experiment, including parameters, metrics, and artifacts (like models).
- Reproducing Code: Packaging ML code in a reusable and reproducible format.
- Deploying Models: Managing and deploying models from various ML libraries to different serving platforms.
- Centralized Model Management: Providing a central repository to manage models, their versions, and their stages (e.g., Staging, Production).
Databricks integrates MLflow natively, making it a powerful tool for developing, deploying, and managing your ML solutions at scale.
Core Concepts of MLflow
MLflow is typically broken down into four primary components:
1. MLflow Tracking
This is like your digital lab notebook. MLflow Tracking allows you to record and query experiments, including:
- Parameters: The input variables you use for your model (e.g., learning rate, number of trees).
- Metrics: The quantitative evaluation scores of your model (e.g., accuracy, RMSE, F1-score).
- Artifacts: Any output files from your run (e.g., the trained model itself, plots, data slices).
- Source Code: A reference to the code that produced the run.
Every time you run an MLflow experiment, it creates a “run” within an “experiment.” You can then easily compare runs to see which parameters yielded the best metrics.
2. MLflow Projects
Think of MLflow Projects as a standard format for packaging your ML code. It defines a convention for organizing your code and its dependencies, making it easy to reproduce your work on different platforms (like another Databricks workspace, or even locally). While powerful, for this introductory chapter, we’ll focus more on Tracking and Models.
3. MLflow Models
Once you’ve trained a model, MLflow Models provide a standard format for packaging it. This means your model can be easily deployed to various platforms (e.g., real-time serving, batch inference) regardless of the ML library used (scikit-learn, TensorFlow, PyTorch, etc.).
4. MLflow Model Registry
This component is your centralized model library. It’s a collaborative hub where you can manage the full lifecycle of an MLflow Model. With the Model Registry, you can:
- Version Models: Automatically track new versions of your models.
- Stage Models: Define different stages for your models (e.g.,
Staging,Production,Archived). - Annotate Models: Add descriptions and comments to models and their versions.
- Search Models: Easily find models based on tags, descriptions, or stages.
The Model Registry is crucial for MLOps, allowing data scientists and ML engineers to manage model transitions from development to production seamlessly.
Step-by-Step Implementation: MLflow Tracking in Action
Let’s get our hands dirty! We’ll start by running a simple scikit-learn linear regression model and track its parameters, metrics, and the model itself using MLflow Tracking.
First, ensure you have a Databricks notebook open and are attached to a cluster. Any recent Databricks Runtime (e.g., DBR 16.x LTS or 17.x LTS, as of late 2025) will have MLflow pre-installed.
Step 1: Import necessary libraries and prepare some dummy data.
In a new cell, add the following code. We’re using sklearn for a simple regression task.
import mlflow
import mlflow.sklearn
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# Generate some synthetic data
np.random.seed(42)
X = np.random.rand(100, 1) * 10
y = 2 * X + 1 + np.random.randn(100, 1) * 2
# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("Data prepared!")
- Explanation: We’re importing
mlflowandmlflow.sklearn(a flavor for scikit-learn models). We then generate a simple linear dataset and split it into training and testing sets, which is standard practice for ML.
Step 2: Start an MLflow run and log parameters and metrics.
Now, let’s wrap our model training process within an MLflow run.
# Define a parameter
alpha = 0.5 # A dummy parameter for now
# Start an MLflow run
with mlflow.start_run():
# Log the parameter
mlflow.log_param("alpha", alpha)
print(f"Logged parameter 'alpha': {alpha}")
# Train a simple Linear Regression model
model = LinearRegression()
model.fit(X_train, y_train)
print("Model trained!")
# Make predictions
y_pred = model.predict(X_test)
# Calculate metrics
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
# Log the metrics
mlflow.log_metric("rmse", rmse)
mlflow.log_metric("r2_score", r2)
print(f"Logged metric 'rmse': {rmse:.2f}")
print(f"Logged metric 'r2_score': {r2:.2f}")
# Log the model
mlflow.sklearn.log_model(model, "linear_regression_model")
print("Logged model 'linear_regression_model'")
# You can also set a tag for the run
mlflow.set_tag("model_type", "Linear Regression")
print("Set run tag 'model_type'")
print("\nMLflow run completed!")
- Explanation:
with mlflow.start_run():is the recommended way to create an MLflow run. It ensures the run is properly ended even if errors occur.mlflow.log_param("alpha", alpha)records a key-value pair as a parameter for this run.mlflow.log_metric("rmse", rmse)andmlflow.log_metric("r2_score", r2)record numerical metrics. MLflow automatically tracks the best value for each metric across multiple runs.mlflow.sklearn.log_model(model, "linear_regression_model")logs the trained scikit-learn model as an artifact. The string “linear_regression_model” is the artifact path within the run. MLflow automatically infers the model’s signature and dependencies.mlflow.set_tag("model_type", "Linear Regression")adds a custom tag to the run for easier filtering later.
Step 3: View your MLflow Experiment.
After running the cell above, you’ll see a link in the output that says Logged to: .... Click this link, or navigate to the “Experiments” icon (a beaker) on the left sidebar in your Databricks workspace.
You’ll see a list of your experiments. The experiment associated with your notebook will likely be named after your notebook’s path. Click on your experiment, and you’ll see a table of runs. Find the most recent run (the one you just executed).
- Observe:
- Under the “Parameters” column, you should see
alphaand its value. - Under the “Metrics” column, you should see
rmseandr2_scorewith their respective values. - Click on the specific run. You’ll see more details, including a “Artifacts” section. Click on
linear_regression_model, and you’ll see the model files (e.g.,model.pkl,MLmodel).
- Under the “Parameters” column, you should see
This is the power of MLflow Tracking! Every experiment is now recorded and easily reviewable.
Step-by-Step Implementation: MLflow Model Registry
Now that we can track models, let’s learn how to manage them centrally using the MLflow Model Registry. This is vital for versioning, staging, and deploying models responsibly.
Step 1: Log a model to the MLflow Model Registry.
Instead of just logging the model as an artifact, we’ll now explicitly register it. This requires specifying a registered_model_name.
# Define a parameter
alpha = 0.6 # Let's change it slightly to simulate a new experiment run
model_name = "MyFirstLinearRegressionModel" # Name for our registered model
with mlflow.start_run():
mlflow.log_param("alpha", alpha)
print(f"Logged parameter 'alpha': {alpha}")
model = LinearRegression()
model.fit(X_train, y_train)
print("Model trained!")
y_pred = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
mlflow.log_metric("rmse", rmse)
mlflow.log_metric("r2_score", r2)
print(f"Logged metric 'rmse': {rmse:.2f}")
print(f"Logged metric 'r2_score': {r2:.2f}")
# Log the model to the registry
registered_model = mlflow.sklearn.log_model(
sk_model=model,
artifact_path="linear_regression_model",
registered_model_name=model_name
)
print(f"Logged model '{model_name}' to registry. Version: {registered_model.version}")
mlflow.set_tag("model_type", "Linear Regression")
print("Set run tag 'model_type'")
print("\nMLflow run completed and model registered!")
- Explanation: The key change is
registered_model_name=model_name. The first time you run this, it will create a new registered model named “MyFirstLinearRegressionModel” and assign it version 1. If you run it again, it will automatically create version 2, and so on.
Step 2: Explore the MLflow Model Registry.
Navigate to the “Models” icon (a cylinder) on the left sidebar in your Databricks workspace.
- Observe: You should now see “MyFirstLinearRegressionModel” listed. Click on it.
- You’ll see different versions of your model. Each version will link back to the MLflow run that created it.
- You can add descriptions, tags, and most importantly, change the “Stage” of each model version.
Step 3: Transition a model’s stage programmatically.
Let’s say you’ve evaluated Version 1 of your model and want to promote it to Staging.
from mlflow.tracking import MlflowClient
# Initialize MLflowClient
client = MlflowClient()
# Define the model name and target version
model_name = "MyFirstLinearRegressionModel"
model_version = 1 # Assuming we want to stage version 1
# Transition the model version to Staging
client.transition_model_version_stage(
name=model_name,
version=model_version,
stage="Staging",
archive_existing_versions=False # Set to True if you want to archive any existing Staging models
)
print(f"Model '{model_name}' Version {model_version} transitioned to 'Staging'.")
# Transition the model version to Production
# client.transition_model_version_stage(
# name=model_name,
# version=model_version,
# stage="Production",
# archive_existing_versions=False
# )
# print(f"Model '{model_name}' Version {model_version} transitioned to 'Production'.")
- Explanation:
MlflowClient()provides programmatic access to MLflow Tracking and the Model Registry.client.transition_model_version_stage()allows us to change the stage of a specific model version. Common stages includeNone(default),Staging,Production, andArchived. This is incredibly useful for MLOps pipelines.
Step 4: Load a model from the registry for inference.
Now, imagine a separate application or notebook that needs to use the latest Production model.
import mlflow.pyfunc
# Load the latest Production model
model_name = "MyFirstLinearRegressionModel"
production_model_uri = f"models:/{model_name}/Production" # URI to load the production model
# Load the model
loaded_model = mlflow.pyfunc.load_model(production_model_uri)
print(f"Loaded model from registry: {production_model_uri}")
# Make a prediction with the loaded model
sample_data = np.array([[12.0]]) # A new data point
prediction = loaded_model.predict(sample_data)
print(f"Prediction for {sample_data[0][0]}: {prediction[0][0]:.2f}")
# You can also load a specific version
specific_version_uri = f"models:/{model_name}/1" # Loads version 1
loaded_specific_model = mlflow.pyfunc.load_model(specific_version_uri)
print(f"Loaded specific model version 1. Prediction: {loaded_specific_model.predict(sample_data)[0][0]:.2f}")
- Explanation:
mlflow.pyfunc.load_model()is a generic way to load MLflow models, regardless of their original framework.- The URI
models:/<model_name>/<stage>(e.g.,models:/MyFirstLinearRegressionModel/Production) allows you to automatically load the latest model in a specific stage. - The URI
models:/<model_name>/<version>(e.g.,models:/MyFirstLinearRegressionModel/1) allows you to load a specific model version. This provides great flexibility for testing and deployment.
Mini-Challenge: Enhance Your Experiment and Registry
Ready for a small challenge?
Challenge: Modify the existing MLflow Tracking code to:
- Introduce a new hyperparameter,
fit_intercept(a boolean forLinearRegression), and log it. - Run two experiments: one with
fit_intercept=Trueand another withfit_intercept=False. - For each run, log the
rmseandr2_score. - After both runs, programmatically register the model from the run that achieved the lowest RMSE to the MLflow Model Registry under the name “OptimizedLinearRegressionModel”. Ensure it’s registered as a new version.
Hint:
- You can loop through different parameter values to create multiple runs.
- After the loop, you’ll need to query MLflow to find the run with the best metric. Look into
mlflow.search_runs()orMlflowClient().search_runs(). - Once you find the best run, you can register its model using
mlflow.register_model()orMlflowClient().create_model_version()by pointing to the artifact URI of the model within that run. The artifact URI within a run usually looks likeruns:/<run_id>/<artifact_path>.
What to observe/learn:
You should see two new runs in your MLflow UI, each with different fit_intercept parameters and their corresponding metrics. You will also see a new registered model named “OptimizedLinearRegressionModel” with at least one version, representing your best model. This exercise demonstrates how to systematically compare experiments and promote the best models to a central registry.
# Your solution code here. Don't forget to import necessary libraries!
import mlflow
import mlflow.sklearn
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from mlflow.tracking import MlflowClient
# (Optional: Re-run data prep if you cleared your environment)
# np.random.seed(42)
# X = np.random.rand(100, 1) * 10
# y = 2 * X + 1 + np.random.randn(100, 1) * 2
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
experiment_name = "/Users/your_email@example.com/MLflow Optimized Linear Regression" # Replace with your user path
mlflow.set_experiment(experiment_name) # Ensure runs are grouped under a specific experiment
best_rmse = float('inf')
best_run_id = None
best_model_uri = None
for intercept_val in [True, False]:
with mlflow.start_run() as run:
current_run_id = run.info.run_id
mlflow.log_param("fit_intercept", intercept_val)
print(f"Starting run {current_run_id} with fit_intercept={intercept_val}")
model = LinearRegression(fit_intercept=intercept_val)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
mlflow.log_metric("rmse", rmse)
mlflow.log_metric("r2_score", r2)
print(f" RMSE: {rmse:.2f}, R2: {r2:.2f}")
# Log the model as an artifact within the run
mlflow.sklearn.log_model(model, "model", registered_model_name=None)
# Keep track of the best run
if rmse < best_rmse:
best_rmse = rmse
best_run_id = current_run_id
# This is the URI within the run's artifacts
best_model_uri = f"runs:/{current_run_id}/model"
print(f"\nBest RMSE found: {best_rmse:.2f} in run ID: {best_run_id}")
# Register the best model to the Model Registry
if best_run_id:
client = MlflowClient()
registered_model_name = "OptimizedLinearRegressionModel"
# You can also use mlflow.register_model() directly if you have the run_id and artifact_path
# This will create a new version of the registered model
registered_model_info = mlflow.register_model(
model_uri=best_model_uri,
name=registered_model_name
)
print(f"Registered best model (version {registered_model_info.version}) from run {best_run_id} as '{registered_model_name}'.")
Common Pitfalls & Troubleshooting
Forgetting
mlflow.start_run()orwith mlflow.start_run()::- Pitfall: If you call
mlflow.log_param(),mlflow.log_metric(), ormlflow.log_model()outside an active MLflow run, you’ll get an error. - Troubleshooting: Always wrap your tracking code within
with mlflow.start_run():or explicitly callmlflow.start_run()andmlflow.end_run(). Thewithstatement is generally preferred as it handlesend_run()automatically.
- Pitfall: If you call
Incorrect Model URI for Registry Operations:
- Pitfall: When loading a model from the registry, using a wrong URI format (e.g.,
models:/<model_name>/Productionvs.models:/<model_name>/<version>) or misspelling the model name/stage. - Troubleshooting: Double-check the exact spelling of your registered model name and the stage (
Staging,Production,Archived). Verify the model and version exist in the MLflow Model Registry UI.
- Pitfall: When loading a model from the registry, using a wrong URI format (e.g.,
Permissions Issues for Model Registry:
- Pitfall: In a collaborative Databricks workspace, you might not have the necessary permissions to register new models or transition existing ones.
- Troubleshooting: If you encounter permission errors, contact your Databricks administrator. They can grant you the required permissions for the Model Registry.
Not Specifying an Experiment Name:
- Pitfall: If you don’t explicitly set an experiment name using
mlflow.set_experiment(), MLflow will log runs to a default experiment (often/Users/<your_email>/<notebook_path>). This can make it hard to find and compare related runs later. - Troubleshooting: Always start your MLflow script or notebook with
mlflow.set_experiment("/Shared/MyProjectExperiments")(or a user-specific path like/Users/your_email@example.com/MyProjectExperiments) to organize your runs logically.
- Pitfall: If you don’t explicitly set an experiment name using
Summary
Phew! You’ve just taken a massive leap in managing your machine learning projects like a pro. Let’s recap what we’ve covered:
- MLflow Introduction: We learned that MLflow is an open-source platform for managing the entire machine learning lifecycle, crucial for reproducibility and production readiness.
- Core Components: We explored MLflow Tracking (your experiment logbook), MLflow Projects (for reproducible code packaging), MLflow Models (standardized model formats), and MLflow Model Registry (your central model library).
- MLflow Tracking in Practice: You successfully tracked parameters, metrics, and models for a simple linear regression experiment within a Databricks notebook.
- MLflow Model Registry: You learned how to register models, manage their versions, transition them through stages (like
StagingandProduction), and load them for inference. This is key for MLOps! - Hands-on Challenge: You applied your knowledge to compare multiple runs and promote the best-performing model to the registry, simulating a real-world model selection process.
- Common Pitfalls: We identified common issues like forgetting to start a run or incorrect URIs and discussed how to resolve them.
You now have a solid foundation for organizing and managing your ML experiments and models on Databricks. This knowledge is indispensable as you move towards building more complex, production-ready machine learning solutions.
What’s Next?
In the upcoming chapters, we’ll build upon this foundation. We might explore more advanced MLflow features, delve into distributed machine learning with Spark MLlib, or even touch upon model deployment strategies using Databricks Model Serving. The world of MLOps awaits!
References
- MLflow Documentation
- MLflow on Databricks
- MLflow Tracking API
- MLflow Model Registry
- Databricks Runtime Release Notes 2025 (for general version context)
This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.