Skip to main content...
ML → Deep Learning via PyTorch — the Garment Classifier
30 min

Day 43: Serving from FastAPI: the /classify container

The classifier becomes a service

You built this exact shape in Stage 0 Day 13 — a FastAPI service behind NestJS. Now the payload is a trained model. The /classify endpoint takes a garment photo, runs it through the model, and returns the predicted class with a confidence. Load the model once at startup, not per request — model loading is expensive and belongs outside the hot path.

src/classifier/api.py — load once, infer per request
from fastapi import FastAPI, UploadFile, HTTPException
from contextlib import asynccontextmanager
import torch, io
from PIL import Image

CLASSES = ["shirt", "trousers", "dress", "saree", "shoes", "bag", "jacket", "skirt"]
state = {}

@asynccontextmanager
async def lifespan(app: FastAPI):
    model = torch.jit.load("garment_classifier.torchscript")  # load ONCE
    model.eval()
    state["model"], state["tf"] = model, build_val_transform()
    yield

app = FastAPI(lifespan=lifespan)

@app.post("/classify")
async def classify(file: UploadFile):
    img = Image.open(io.BytesIO(await file.read())).convert("RGB")
    x = state["tf"](img).unsqueeze(0)          # add batch dim: (1,3,224,224)
    with torch.no_grad():
        probs = state["model"](x).softmax(dim=1)[0]
    idx = int(probs.argmax())
    return {"class": CLASSES[idx], "confidence": round(float(probs[idx]), 4)}

softmax turns logits into a confidence

The model outputs raw scores (logits); softmax normalizes them into probabilities that sum to 1, giving you the confidence to return. Logging both the predicted class and its confidence per request (a Stage 1 exit criterion — 'predictions logged') is the seed of the model telemetry that becomes central in Stage 5.

Key terms

lifespan / startup load
Loading the model once when the service starts, rather than per request, to keep inference latency low.
softmax
A function turning raw class scores (logits) into a probability distribution that sums to 1.
Logits
The raw, unnormalized output scores of a classifier before softmax.

Why should the model be loaded in the FastAPI startup/lifespan, not inside the /classify request handler?

We use cookies

We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies. Learn more

    Day 43: Serving from FastAPI: the /classify container | RBTechIconX