Home · Volume 5 · Chapter 05

📖 Chapter 05 — Machine Learning

The ML lifecycle on the NAS. Training, tracking, deploying, monitoring.

v0.1 · draft Vol 5 · Ch 05
~15 min

Learning Objectives

Introduction

You have data, you have pipelines, you have analysis. Now: machine learning. The ML lifecycle is different from analysis: training a model takes time and resources, the model artifact is the output (not the chart), and you need to know if the model is still working in production.

This chapter covers the ML lifecycle on the NAS. For most home data science, the workload is: train a model on a CPU, save the model, use it for predictions (locally or via a small API). For heavier workloads (deep learning, large models), a GPU server (Volume 4, Chapter 9).

The ML lifecycle

The standard ML lifecycle has five steps:

  1. Data preparation: clean, transform, and split into train/test/validation sets.
  2. Training: fit a model on the training data. Choose the algorithm, the hyperparameters, the features.
  3. Evaluation: score the model on the test set. Compare to baselines. Decide if the model is good enough.
  4. Deployment: save the trained model. Make it available for predictions (an API, a batch job, a local function).
  5. Monitoring: in production, track the model's inputs and outputs. Detect when the model's performance degrades (data drift, concept drift).

For home data science, the lifecycle is similar to a production setup, but with smaller scale and less strict SLAs. The principles are the same.

Tooling: the right ones for the right job

For most home ML, scikit-learn + MLflow is the right stack. PyTorch for deep learning. Hugging Face when you need a pre-trained model.

Training a model

Example with scikit-learn:

import polars as pl
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import mlflow
import mlflow.sklearn

# Load the data
df = pl.read_parquet("/mnt/tank/Lab/data/processed/features.parquet")

# Split
X = df.drop("target").to_numpy()
y = df["target"].to_numpy()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Train
with mlflow.start_run():
    model = RandomForestClassifier(n_estimators=100, max_depth=10)
    model.fit(X_train, y_train)

    # Evaluate
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    mlflow.log_metric("accuracy", accuracy)

    # Log the model
    mlflow.sklearn.log_model(model, "model")

    # Log parameters
    mlflow.log_params({"n_estimators": 100, "max_depth": 10})

The with mlflow.start_run() block creates a "run" in MLflow. The parameters, metrics, and model are all recorded. The model artifact is saved to MLflow's storage, which can be on the NAS.

MLflow on the NAS

MLflow has two parts:

Install MLflow on the NAS:

version: "3.9"

services:
  mlflow:
    image: ghcr.io/mlflow/mlflow:latest
    restart: unless-stopped
    ports:
      - "5000:5000"
    volumes:
      - /mnt/tank/Lab/mlflow:/mlflow
    command: mlflow server --host 0.0.0.0 --backend-store-uri sqlite:///mlflow/mlflow.db --default-artifact-root /mlflow/artifacts

Set the tracking URI in your training script:

import mlflow
mlflow.set_tracking_uri("http://<nas>:5000")

Now all runs are recorded on the NAS, with the UI at http://<nas>:5000.

Why MLflow matters

Without MLflow, "I trained a model" is a vague claim. You trained it with what parameters? What was the accuracy? What data? Can you reproduce it?

With MLflow, "I trained a model" is a record. The run has the parameters, the metrics, the model artifact, the git commit hash of the training code, the environment. Future-you can re-run the same training and get the same result.

The discipline: every model is an MLflow run. Every run has parameters, metrics, and the model. The code, the data, the model — all linked.

GPU for training

For most home ML, CPU is enough. A modern CPU can train a scikit-learn model on a small-to-medium dataset in minutes to hours. For deep learning, GPU helps a lot.

For a GPU server, the right approach (from Volume 4, Chapter 9): a separate machine with one or more GPUs. Pass the GPU through to the training container. The data is on the NAS, mounted via NFS.

For most home data science, a CPU is enough. The conversation's recommendation: start with CPU. Buy a GPU when you have a specific workload that needs it (deep learning, LLM fine-tuning, Stable Diffusion training).

Deploying a model

For most home data science, the model is used in one of three ways:

For batch and interactive, the model is loaded with scikit-learn or PyTorch's standard API. For an API, the right tools:

For most home data science, FastAPI is the right default. The endpoint is a few lines of code, runs in a container, and is reachable from the network.

Monitoring in production

For a model in production, the question is: is it still good? The monitoring:

For most home data science, monitoring is a "nice to have" — the model is used occasionally, and degradation is caught when someone notices. For a production model, set up a monitoring system: log inputs and predictions, compare distributions, alert on drift.

The "what to save" question

For a trained model, save:

MLflow captures all of this. The run record is the model lineage: "this model was trained on this data, with this code, in this environment, achieving these metrics."

Engineering Note

The model is a product of the code, the data, and the environment. A trained model without these is a black box. "I have a model that's 95% accurate" is meaningless without knowing what data, what code, what environment. The discipline of MLflow (record everything) is the discipline of treating the model as a reproducible artifact, not a mysterious file.

Summary

The ML lifecycle on the NAS: data → training → evaluation → deployment → monitoring. scikit-learn for classical ML, PyTorch for deep learning. MLflow for experiment tracking. FastAPI for serving models. CPU for most home workloads, GPU when needed. The discipline: every model is an MLflow run, with parameters, metrics, code, data, and the model artifact. The run is the lineage.

Checklist

Looking Ahead

Chapter 06 is sharing and collaboration. Notebooks, datasets, results. How to share analytical work with other people: securely, with the right access, and with the right context. The chapter that turns "I have an analysis" into "the team can review, reproduce, and build on the analysis."

Ch 05 · v0.1 · drafted from the original ChatGPT conversation, July 2026