AW Dev Rethought

🕵️ Debugging is like being the detective in a crime movie where you are also the murderer - Filipe Fortes

⚡️ Saturday ML Spark – 📦 Model Versioning & Rollback Strategy


Description:

Building a better machine learning model is only half the challenge. The other half is deploying it safely.

What happens if a newly deployed model performs worse than the existing one? How do you know which version is currently serving users? Can you quickly switch back to the previous model if something goes wrong?

These questions are answered through Model Versioning and Rollback Strategies, two essential practices in modern MLOps.

In this project, we’ll learn how production teams manage multiple model versions and safely recover from failed deployments.


What Is Model Versioning?

Model versioning is the process of assigning unique versions to trained machine learning models throughout their lifecycle.

Instead of replacing an existing model, every new model receives its own version.

For example:

Version 1 (Production)

↓

Version 2 (Candidate)

↓

Version 3 (Future)

This makes it easy to identify which model is currently deployed and compare it with previous versions.


Why Model Versioning Matters

Imagine a fraud detection model that has been performing well in production.

A new version is trained using more recent data and appears to perform better during testing. The team deploys the new model. A few hours later, they discover that false positives have increased significantly.

Without versioning, recovering from this situation becomes difficult. With versioning, the team can simply switch back to the previous stable model.


Training Multiple Model Versions

To simulate this process, we’ll train two different models.

  • Version 1 → Production Model
  • Version 2 → Candidate Model
model_v1.fit(
    X_train,
    y_train
)

model_v2.fit(
    X_train,
    y_train
)

The production model represents the current stable deployment, while the candidate model is being evaluated for release.


Evaluating Model Performance

Before promoting a new version, both models are evaluated using the same test data.

f1_score(
    y_test,
    predictions
)

Metrics commonly compared include:

  • Accuracy
  • Precision
  • Recall
  • F1-score
  • Latency
  • Memory usage

Only after these metrics are reviewed should a deployment decision be made.


Maintaining a Model Registry

Production ML systems typically store information about every trained model inside a Model Registry.

A registry records details such as:

  • model version
  • deployment status
  • evaluation metrics
  • training date
  • model location

A simplified registry might look like:

Version    Status

v1         Production

v2         Candidate

This allows teams to track and manage every model throughout its lifecycle.


Promoting or Rolling Back

After evaluation, the deployment pipeline decides whether to promote the candidate model.

If the new model performs better:

Candidate

↓

Production

If performance degrades:

Candidate

↓

Rollback

↓

Production (Previous Version)

Rollback ensures that users continue receiving predictions from a stable model while engineers investigate the issue.


How Rollback Works

Rollback is one of the safest deployment strategies in machine learning.

Instead of retraining a model, the deployment system simply reloads the previous production version.

Because the earlier model has already been validated, service can recover within seconds.

This minimises downtime and reduces business risk.


Where Model Versioning Is Used

Model versioning is widely used in:

  • recommendation systems
  • fraud detection platforms
  • healthcare AI
  • financial risk models
  • autonomous systems
  • search engines

Any production ML application benefits from maintaining multiple model versions and a clear rollback strategy.


Key Takeaways


  1. Model versioning keeps track of every trained model throughout its lifecycle.
  2. Candidate models are evaluated before replacing production models.
  3. Model registries organise versions, metadata, and deployment status.
  4. Rollback enables rapid recovery when a deployment performs poorly.
  5. Versioning and rollback are fundamental practices in modern MLOps.

Conclusion

Machine learning models evolve continuously as new data becomes available and better algorithms are developed. Model versioning ensures these improvements are organised, traceable, and reproducible, while rollback strategies provide a reliable safety net when deployments don’t perform as expected. Together, they enable ML teams to release models confidently, reduce deployment risk, and maintain stable production systems.

This continues the ML Systems Advanced track in Saturday ML Spark ⚡️, where we’re exploring the operational practices that make production machine learning reliable, scalable, and easy to manage.


Code Snippet:

# =========================================================
# 📦 Import Required Libraries
# =========================================================

import joblib
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_breast_cancer

from sklearn.model_selection import train_test_split

from sklearn.linear_model import LogisticRegression

from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import (
    accuracy_score,
    precision_score,
    recall_score,
    f1_score
)


# =========================================================
# 🧩 Load Dataset
# =========================================================

data = load_breast_cancer()

X = pd.DataFrame(
    data.data,
    columns=data.feature_names
)

y = pd.Series(
    data.target,
    name="target"
)


# =========================================================
# ✂️ Train-Test Split
# =========================================================

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.30,
    random_state=42,
    stratify=y
)


# =========================================================
# 🤖 Train Production Model (Version 1)
# =========================================================

model_v1 = LogisticRegression(
    max_iter=5000
)

model_v1.fit(
    X_train,
    y_train
)


# =========================================================
# 🚀 Train Candidate Model (Version 2)
# =========================================================

model_v2 = RandomForestClassifier(
    n_estimators=200,
    random_state=42
)

model_v2.fit(
    X_train,
    y_train
)


# =========================================================
# 📊 Evaluate Version 1
# =========================================================

pred_v1 = model_v1.predict(
    X_test
)

metrics_v1 = {

    "Accuracy": accuracy_score(
        y_test,
        pred_v1
    ),

    "Precision": precision_score(
        y_test,
        pred_v1
    ),

    "Recall": recall_score(
        y_test,
        pred_v1
    ),

    "F1 Score": f1_score(
        y_test,
        pred_v1
    )

}


# =========================================================
# 📊 Evaluate Version 2
# =========================================================

pred_v2 = model_v2.predict(
    X_test
)

metrics_v2 = {

    "Accuracy": accuracy_score(
        y_test,
        pred_v2
    ),

    "Precision": precision_score(
        y_test,
        pred_v2
    ),

    "Recall": recall_score(
        y_test,
        pred_v2
    ),

    "F1 Score": f1_score(
        y_test,
        pred_v2
    )

}


# =========================================================
# 📋 Create Model Registry
# =========================================================

model_registry = pd.DataFrame({

    "Version": [
        "v1",
        "v2"
    ],

    "Model": [
        "Logistic Regression",
        "Random Forest"
    ],

    "Status": [
        "Production",
        "Candidate"
    ],

    "Accuracy": [
        metrics_v1["Accuracy"],
        metrics_v2["Accuracy"]
    ],

    "Precision": [
        metrics_v1["Precision"],
        metrics_v2["Precision"]
    ],

    "Recall": [
        metrics_v1["Recall"],
        metrics_v2["Recall"]
    ],

    "F1 Score": [
        metrics_v1["F1 Score"],
        metrics_v2["F1 Score"]
    ]

})

print("=" * 60)
print("MODEL REGISTRY")
print("=" * 60)

print(
    model_registry.round(4)
)


# =========================================================
# 🚦 Deployment Decision
# =========================================================

if metrics_v2["F1 Score"] >= metrics_v1["F1 Score"]:

    active_model = model_v2
    active_version = "v2"

    model_registry.loc[
        model_registry["Version"] == "v1",
        "Status"
    ] = "Archived"

    model_registry.loc[
        model_registry["Version"] == "v2",
        "Status"
    ] = "Production"

    decision = "Promote Version 2"

else:

    active_model = model_v1
    active_version = "v1"

    decision = "Rollback to Version 1"


print("\nDeployment Decision:")
print(decision)


# =========================================================
# 💾 Save Active Model
# =========================================================

joblib.dump(
    active_model,
    "active_model.pkl"
)

print("\nActive model saved successfully.")


# =========================================================
# 📂 Load Active Model
# =========================================================

loaded_model = joblib.load(
    "active_model.pkl"
)

print(
    "Loaded Active Version:",
    active_version
)


# =========================================================
# 🔮 Predict Using Active Model
# =========================================================

sample_predictions = loaded_model.predict(
    X_test.iloc[:5]
)

print("\nSample Predictions:")
print(sample_predictions)


# =========================================================
# 📊 Version Comparison
# =========================================================

comparison = model_registry.set_index(
    "Version"
)[
    [
        "Accuracy",
        "Precision",
        "Recall",
        "F1 Score"
    ]
]

comparison.plot(
    kind="bar",
    figsize=(10, 5)
)

plt.title("Model Version Comparison")
plt.ylabel("Score")
plt.ylim(0, 1.05)

plt.grid(
    axis="y",
    linestyle="--",
    alpha=0.5
)

plt.tight_layout()
plt.show()


# =========================================================
# 💾 Save Registry
# =========================================================

model_registry.to_csv(
    "model_registry.csv",
    index=False
)

print(
    "\nModel registry saved successfully."
)


# =========================================================
# 📂 Read Registry
# =========================================================

saved_registry = pd.read_csv(
    "model_registry.csv"
)

print("\nUpdated Model Registry:\n")
print(saved_registry.round(4))


# =========================================================
# 📌 Final Summary
# =========================================================

print("\n" + "=" * 60)
print("MODEL VERSIONING COMPLETED")
print("=" * 60)

print(f"Active Model Version : {active_version}")
print(f"Deployment Decision  : {decision}")

print("\nProduction Registry:")

print(
    saved_registry[
        [
            "Version",
            "Status",
            "F1 Score"
        ]
    ]
)

Link copied!

Comments

Add Your Comment

Comment Added!