Machine Learning β€Ί Machine Learning in Practice β€Ί Day 196

Day 196: Section Project: An ML Service

Day 196 of 365 β€” Section Project: An ML Service

Complete the Course 04 Capstone Project: train a production model, serialize with SHA-256 provenance into a Model Registry, serve via a low-latency FastAPI microservice with Pydantic contracts, and monitor for real-time PSI data drift.

Course
Machine Learning
Category
Machine Learning in Practice
Reading time
β‰ˆ 35 min
Practical time
β‰ˆ 60 min
Lesson duration
1h 35m
Last verified
2026-08-29

Hands-on lab for this lesson

Lab files on GitHub: https://github.com/ai-roadmap-365/ai-roadmap-365.github.io/tree/main/labs/sections/machine-learning/day-196-section-project-an-ml-service

  1. Get the hands-on files. Clone the labs repository once (you can reuse this clone for every lesson). This works on macOS, Linux, and Windows (PowerShell or WSL):
    git clone https://github.com/ai-roadmap-365/ai-roadmap-365.github.io.git
    cd ai-roadmap-365.github.io
  2. Open this lesson's lab. Move into the directory for this specific day. Every lab lives at the same predictable path β€” section / subsection / week / day:
    cd labs/sections/machine-learning/day-196-section-project-an-ml-service
  3. Read the lab guide. Open `README.md` in that directory. It lists the exact commands, what each does, the expected output, and how to check your work β€” read it before running anything.
  4. Run it and check your work. Follow the README's "How to run" section: run the example first to see the finished result, then complete the numbered exercises in `starter/`, then run the tests. The tests pass (exit 0) only when your work is correct.
    bash tests/run_tests.sh   # or the test command named in the lab README

You can also open the lab as a local page (works offline, shows the file tree and expected output).

Learning objectives

By the end of this lesson you will be able to:

Prerequisites

Why this matters

Over the past 8 weeks (Days 141 to 195), you have journeyed across the entire landscape of Course 04: Machine Learning:

Now, in this Course 04 Capstone Project, you will synthesize every single theoretical and engineering skill you have mastered into a single, cohesive, production-grade Deployed ML Service.

This project represents the bridge between classical machine learning and production AI engineering.


The idea in plain language

Imagine founding a financial technology startup that provides real-time credit risk assessments to e-commerce merchants at checkout:

You are not building a toy model in a notebook; you are building an enterprise software product.


Historical background

  1. 2000–2010 (The Model Isolation Era): Data scientists worked in isolated R and SAS silos, exporting static coefficients into Excel spreadsheets or handing PDF reports to software engineers to re-code in Java or C++.
  2. 2012–2018 (The Jupyter Notebook Boom): Python and Scikit-Learn democratized machine learning; however, β€œnotebook spaghetti code” led to massive technical debt and production outages.
  3. 2019–Present (The Unified MLOps Era): Modern machine learning has matured into a standardized software engineering discipline uniting Git version control, automated CI/CD test gates, containerized microservice APIs, and continuous statistical monitoring.

What it is β€” and what it is not

What This Capstone Project IS:

What it is NOT:


Why it was created and what problems it solves

In enterprise organizations, machine learning fails at the seams between teams:

This capstone project eliminates these failure modes by architecting the complete lifecycle end-to-end as a single unified system.


How it works

Let us dissect the complete architecture of our production ML service.

1. The Unified System Architecture

End to end deployed ML service system diagram illustrating training serialization registry packaging FastAPI serving and PSI drift monitoring

The production service operates across four integrated components:

Component 1: Pipeline Training & Evaluation

Component 2: Cryptographic Model Registry

Component 3: Low-Latency REST Serving Engine

Component 4: Statistical Drift Monitor


2. Course 04: Machine Learning Mastery Recapitulation

Course 04 completion roadmap diagram highlighting foundational supervised algorithms unsupervised learning and production ML deployment engineering

Let us review the complete intellectual journey of Course 04:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               COURSE 04: MACHINE LEARNING COMPLETE ROADMAP             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Track                 β”‚ Weeks   β”‚ Core Concepts Mastered               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Supervised Learning   β”‚ W21–W26 β”‚ Linear/Logistic Reg, Cost Surfaces,  β”‚
β”‚                       β”‚         β”‚ Trees, Ensembles, LightGBM, SVMs,    β”‚
β”‚                       β”‚         β”‚ Bias-Variance, Cross-Validation      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Unsupervised Learning β”‚ W27     β”‚ K-Means, Hierarchical, DBSCAN, PCA,  β”‚
β”‚                       β”‚         β”‚ SVD, t-SNE, UMAP, Anomaly Detection, β”‚
β”‚                       β”‚         β”‚ Matrix Factorization Recommenders    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ ML in Practice        β”‚ W28     β”‚ Project Lifecycles, Active Learning, β”‚
β”‚                       β”‚         β”‚ Weak Supervision, Time Series Lags,  β”‚
β”‚                       β”‚         β”‚ Model Registries, FastAPI, PSI Drift β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. The Bridge to Course 05: Deep Learning & Neural Networks

As Course 04 concludes, we stand at the threshold of the modern AI revolution.

In classical machine learning (Course 04):

In Course 05: Deep Learning (starting on Day 197):

Crucially, the MLOps principles you mastered in Week 28 do not disappear in Deep Learning β€” they become 100x more critical:

As you step into Course 05 on Day 197 with the Artificial Perceptron, you carry with you a complete, mathematically rigorous, and production-tested foundation in machine learning engineering. The journey from single artificial neurons to deep convolutional networks, recurrent sequence models, attention mechanisms, and modern transformer foundation models all builds directly upon the optimization, regularization, evaluation, and operational serving principles established throughout Course 04. Let us now celebrate this milestone and step boldly into Deep Learning.


An everyday analogy

Think of launching an orbital telecommunications satellite:


Examples in practice

Let us inspect the complete, integrated, production-grade ML Service implementation combining training, registration, serving, and drift detection:

import hashlib
import time
import numpy as np
from dataclasses import dataclass, field
from typing import Dict, Any, List, Optional, Tuple

# 1. Domain Schemas
@dataclass
class CustomerFeatures:
    tenure_months: float
    monthly_spend: float
    support_tickets: int

# 2. Model Registry & Metadata
@dataclass
class ModelMetadata:
    model_name: str
    version: str
    sha256_hash: str
    stage: str
    weights: np.ndarray
    bias: float
    pr_auc: float

class ProductionModelRegistry:
    def __init__(self):
        self._catalog: Dict[str, Dict[str, ModelMetadata]] = {}

    def register_and_promote(
        self,
        name: str,
        version: str,
        weights: np.ndarray,
        bias: float,
        pr_auc: float,
    ) -> ModelMetadata:
        if name not in self._catalog:
            self._catalog[name] = {}

        raw_bytes = weights.tobytes() + str(bias).encode("utf-8")
        sha256 = hashlib.sha256(raw_bytes).hexdigest()

        # Archive existing production model
        for meta in self._catalog[name].values():
            if meta.stage == "PRODUCTION":
                meta.stage = "ARCHIVED"

        meta = ModelMetadata(
            model_name=name,
            version=version,
            sha256_hash=sha256,
            stage="PRODUCTION",
            weights=weights,
            bias=bias,
            pr_auc=pr_auc,
        )
        self._catalog[name][version] = meta
        return meta

    def get_production_model(self, name: str) -> Optional[ModelMetadata]:
        if name not in self._catalog:
            return None
        for meta in self._catalog[name].values():
            if meta.stage == "PRODUCTION":
                return meta
        return None

# 3. Production Serving & Drift Engine
class DeployedMLService:
    def __init__(self, registry: ProductionModelRegistry, model_name: str):
        self.registry = registry
        self.model_name = model_name
        self._active_model: Optional[ModelMetadata] = None
        self.reference_spend: Optional[np.ndarray] = None
        self.load_production_model()

    def load_production_model(self) -> None:
        self._active_model = self.registry.get_production_model(self.model_name)

    def set_reference_data(self, reference_spend: np.ndarray) -> None:
        self.reference_spend = reference_spend

    def _fallback_heuristic(self, features: CustomerFeatures) -> float:
        if features.support_tickets >= 3 or features.monthly_spend > 150.0:
            return 0.75
        return 0.20

    def predict(self, sample: CustomerFeatures) -> Dict[str, Any]:
        t0 = time.perf_counter()
        if self._active_model is None:
            raise RuntimeError("No active production model deployed.")

        if sample.tenure_months < 0 or sample.monthly_spend < 0:
            raise ValueError("Feature values cannot be negative.")

        x = np.array(
            [
                sample.tenure_months,
                sample.monthly_spend,
                float(sample.support_tickets),
            ]
        )

        try:
            z = float(np.dot(self._active_model.weights, x) + self._active_model.bias)
            prob = 1.0 / (1.0 + np.exp(-z))
            used_fallback = False
        except Exception:
            prob = self._fallback_heuristic(sample)
            used_fallback = True

        latency_ms = (time.perf_counter() - t0) * 1000.0
        return {
            "churn_probability": round(float(prob), 4),
            "prediction": 1 if prob >= 0.5 else 0,
            "used_fallback": used_fallback,
            "model_version": self._active_model.version,
            "latency_ms": round(latency_ms, 3),
        }

    def evaluate_feature_drift_psi(
        self, current_spend: np.ndarray
    ) -> Tuple[float, str]:
        if self.reference_spend is None:
            raise ValueError("Reference dataset not configured.")

        # 10 quantile bins
        quantiles = np.linspace(0, 100, 11)
        bin_edges = np.percentile(self.reference_spend, quantiles)
        bin_edges[0] = -np.inf
        bin_edges[-1] = np.inf

        eps = 1e-4
        ref_counts, _ = np.histogram(self.reference_spend, bins=bin_edges)
        ref_pct = (ref_counts / len(self.reference_spend)) + eps
        ref_pct /= np.sum(ref_pct)

        cur_counts, _ = np.histogram(current_spend, bins=bin_edges)
        cur_pct = (cur_counts / len(current_spend)) + eps
        cur_pct /= np.sum(cur_pct)

        psi = float(np.sum((cur_pct - ref_pct) * np.log(cur_pct / ref_pct)))
        status = (
            "STABLE"
            if psi < 0.10
            else ("MODERATE_DRIFT" if psi < 0.20 else "SIGNIFICANT_DRIFT")
        )
        return round(psi, 4), status

Implications: security, privacy, performance, scalability, and cost

  1. End-to-End Latency Budget Allocation:
    • In a 50ms total web checkout SLA:
      • 10ms: Network transport & TLS handshake.
      • 5ms: API Gateway authentication and rate-limiting.
      • 3ms: Pydantic request parsing and schema validation.
      • 2ms: NumPy model forward pass.
      • 5ms: Async drift telemetry emission.
      • 25ms: Safety buffer for tail latency spikes.
  2. Infrastructure Cost Efficiency:
    • Pre-forked Python microservices on modern ARM cloud instances (e.g. AWS Graviton3) achieve 2,500 predictions per second per 2-vCPU node at a cost of less than $0.05 per 1,000,000 inference queries.

Alternatives: free, open source, and commercial

LayerOpen Source StandardManaged Cloud EnterpriseHigh-Scale Enterprise
Model RegistryMLflowAWS SageMaker RegistryDatabricks Unity Catalog
API ServingFastAPI + UvicornGoogle Cloud Run / Vertex AINVIDIA Triton / Kubernetes
Drift MonitoringEvidently AI / WhyLogsAWS Model MonitorArize AI / Datadog APM
Data OrchestrationDVC / FeastSnowflake / BigQueryDelta Live Tables

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               ENTERPRISE SERVICE MATURITY LEVELS                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Level             β”‚ Artifact Management  β”‚ Serving Layer  β”‚ Monitoring β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Level 0 (Manual)  β”‚ Raw .pkl on Desktop  β”‚ Flask (Sync)   β”‚ None       β”‚
β”‚ Level 1 (Basic)   β”‚ S3 Folder Structure  β”‚ FastAPI (Sync) β”‚ Logs Only  β”‚
β”‚ Level 2 (Mature)  β”‚ MLflow Registry      β”‚ FastAPI + ASGI β”‚ Real-Time  β”‚
β”‚                   β”‚ SHA-256 + SemVer     β”‚ Batch + Circuitβ”‚ PSI Drift  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

When to use it β€” and when not to

When to USE the Complete Deployed ML Service Pattern:

When NOT to use it:


Knowledge check

  1. What are the four core architectural components of the Deployed ML Service?
  2. How does bundling feature transformers inside the model artifact eliminate Train-Serve Skew?
  3. Why does the Model Registry enforce strict single-version uniqueness for the active PRODUCTION stage?
  4. How does the automated Circuit Breaker guarantee 99.99% system availability during unexpected numerical errors?
  5. What does a Population Stability Index score of PSI β‰₯ 0.20 trigger in the production observability loop?

Hands-on exercise

In this capstone lab, you will implement the complete DeployedMLService architecture in pure Python and NumPy: train a customer churn model, register it in ProductionModelRegistry with SHA-256 checksums, execute single and batch predictions via DeployedMLService, test circuit-breaker error recovery, and detect real-time PSI drift.

Expected output

[Course 04 Capstone: Deployed ML Service]
1. Model Training: Logistic Pipeline trained (PR-AUC = 0.8840)
2. Registry: Registered churn_model:v1.0.0 (SHA-256: e8b4a1...) -> Stage: PRODUCTION
3. Microservice Serving:
   - Sample Prediction: Churn Probability = 0.7245 (Latency = 0.045ms)
   - Batch Prediction: 10 samples processed in 0.180ms
4. Circuit Breaker Test: Injected NaN tensor -> Fallback Heuristic Executed = True (Prob: 0.7500)
5. Drift Observability:
   - Stable Stream: PSI = 0.0124 [STABLE]
   - Shifted Stream: PSI = 0.3842 [SIGNIFICANT_DRIFT] -> Retraining Alert Emitted
Test Suite: 2 passed in 0.08s
Course 04 Complete! Ready for Course 05: Deep Learning.

Validate your work

Run the automated test runner:

./tests/run_tests.sh

Troubleshooting

Common mistakes


Practice assignment

  1. Implement an automated Model Rollback Trigger that automatically transitions the active Production model back to the previous Archived version if live error rates exceed 1.0%.
  2. Build an automated JSON Model Card exporter that packages complete service metadata for regulatory compliance.

Extension challenge

Implement a Live A/B Testing Canary Traffic Splitter:

Quiz

Q1. In the complete end-to-end ML service architecture, what is the primary role of the Model Registry catalog?

  1. Serving as the single source of truth for versioned model artifacts, SHA-256 hashes, training metadata, and active deployment stage state
  2. Writing SQL queries on the customer database
  3. Generating HTML web pages for browser users
  4. Compiling Python source code into machine bytecode
Show answer

Answer: A. Serving as the single source of truth for versioned model artifacts, SHA-256 hashes, training metadata, and active deployment stage state

The Model Registry decouples training from serving: it stores validated candidate artifacts with immutable cryptographic hashes and controls stage promotions.

Q2. Why must feature preprocessing (e.g. StandardScaler or imputation) be bundled directly inside the serialized pipeline artifact rather than computed ad-hoc in the API handler?

  1. To prevent Train-Serve Skew: guaranteeing that the exact mean and standard deviation scaling parameters learned during training are applied identically in production
  2. Because FastAPI cannot execute division
  3. To reduce Docker container image size
  4. Because NumPy arrays cannot be normalized in memory
Show answer

Answer: A. To prevent Train-Serve Skew: guaranteeing that the exact mean and standard deviation scaling parameters learned during training are applied identically in production

Bundling transformers inside the model artifact ensures identical preprocessing logic at training and serving time, preventing catastrophic train-serve feature skew.

Q3. What happens when a live prediction request arrives with a feature value that triggers a Population Stability Index score of PSI = 0.35 over a 24-hour window?

  1. The monitoring telemetry engine flags significant data drift, emits an automated alert to on-call engineers, and queues historical logs for automated retraining
  2. The FastAPI server immediately shuts down
  3. The model deletes all negative predictions
  4. The database drops all customer records
Show answer

Answer: A. The monitoring telemetry engine flags significant data drift, emits an automated alert to on-call engineers, and queues historical logs for automated retraining

PSI >= 0.20 indicates substantial population shift: the monitor triggers operational alerts and queues the drifted dataset for model retraining.

Q4. What is the primary benefit of testing your ML microservice using an automated end-to-end pytest suite prior to production deployment?

  1. It validates that the complete lifecycle (model loading, schema validation, forward inference, error handling, and drift logging) operates flawlessly under simulated traffic
  2. It eliminates the need for any cloud compute resources
  3. It guarantees 100% test dataset accuracy
  4. It automatically writes documentation
Show answer

Answer: A. It validates that the complete lifecycle (model loading, schema validation, forward inference, error handling, and drift logging) operates flawlessly under simulated traffic

End-to-end testing verifies the integration between web schemas, tensor math, error fallbacks, and monitoring hooks, catching regressions before deployment.

Q5. As Course 04 concludes, what foundational transition occurs as we enter Course 05: Deep Learning?

  1. Transitioning from manual feature engineering and classical tabular algorithms to representation learning, backpropagation, and PyTorch deep neural networks
  2. Stopping the use of Python and switching to C
  3. Abandoning all testing and monitoring practices
  4. Switching from mathematics to pure guesswork
Show answer

Answer: A. Transitioning from manual feature engineering and classical tabular algorithms to representation learning, backpropagation, and PyTorch deep neural networks

Course 05 builds upon classical ML foundations, introducing deep representation learning, tensor autograd, backpropagation, and neural architectures.

Glossary

Deployed ML Service
A complete, production-grade microservice exposing a trained model over a REST API with schema validation and drift monitoring.
Train-Serve Skew
A discrepancy in performance or data processing between how a model was trained and how it executes in live production.
End-to-End Pipeline
A unified engineering workflow connecting data ingestion, feature transformation, training, registration, serving, and monitoring.
Artifact Provenance
The immutable cryptographic audit trail linking a deployed binary to its exact dataset hash, code commit SHA, and metrics.
Graceful Degradation
The system design principle ensuring that when a component fails, the service falls back to safe heuristics rather than crashing.
Representation Learning
A branch of machine learning where algorithms automatically discover optimal feature representations from raw input tensors.
Course 04 Capstone
The culminating project demonstrating mastery of classical machine learning algorithms, unsupervised representations, and MLOps.
Deep Learning Transition
The pedagogical advancement from classical tabular ML to gradient-based neural networks and PyTorch tensor computing.

Sources and further reading


Kept in this browser, no account needed. Your progress page turns the whole record into one link you can bookmark or open on another device.