Shipping Models: MLOps Fundamentals
A Model in a Notebook Earns Nothing
Production ML means a model that answers requests reliably, gets monitored, and gets retrained when the world drifts. The gap between “works in Jupyter” and “runs in prod” is where most ML projects die — this topic closes it.
Step 1: Make Preprocessing Part of the Model
The #1 production bug is training/serving skew — preprocessing in the notebook differing from preprocessing at inference. scikit-learn pipelines eliminate it by bundling the steps into the model object:
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
pre = ColumnTransformer([
("num", StandardScaler(), ["area", "age"]),
("cat", OneHotEncoder(handle_unknown="ignore"), ["city"]),
])
pipe = Pipeline([("pre", pre), ("model", Ridge(alpha=10))])
pipe.fit(X_train, y_train) # scaler fitted on train only — leakage impossibleStep 2: Serialize
import joblib
joblib.dump(pipe, "model_v3.joblib")
pipe = joblib.load("model_v3.joblib")Version the artefact (model_v3), and pin library versions in requirements.txt — a pickle saved under scikit-learn 1.4 may not load under 1.6.
Step 3: Serve Behind an API
from fastapi import FastAPI
from pydantic import BaseModel
import joblib, pandas as pd
app = FastAPI()
model = joblib.load("model_v3.joblib") # load once at startup
class House(BaseModel):
area: float
age: float
city: str
@app.post("/predict")
def predict(h: House):
X = pd.DataFrame([h.model_dump()])
return {"price": float(model.predict(X)[0]), "model_version": "v3"}uvicorn serve:app --host 0.0.0.0 --port 8000Pydantic validates every request — bad inputs get a clean 422 instead of a crash deep inside NumPy. Containerise with Docker and this deploys anywhere.
Step 4: Monitor, Because Models Rot
- System metrics — latency, error rate, throughput (same as any service).
- Data drift — log incoming features; alert when their distribution shifts from training (a price model trained pre-inflation quietly goes stale).
- Outcome metrics — when true labels arrive later (did the user churn?), join them back and track live accuracy.
Log every prediction with its inputs and model version — that log is both your debugging tool and your next training set.
Step 5: Retrain on a Schedule, Not a Panic
Automate: pull fresh data → retrain pipeline → evaluate against the current model on a held-out window → promote only if better → keep the old artefact for instant rollback. Tools like MLflow track experiments and model registries; start simple with a cron job and a metrics table.
Series Wrap-Up
You can now frame ML problems, build and evaluate models honestly, beat overfitting, train neural networks, and ship the result behind an API. The best next step: pick a real dataset you care about and run the entire workflow end to end — nothing teaches like shipping.