PyTorch Model Deployment

Deployment takes a trained PyTorch model and makes it available for real-world predictions — as a web API, a mobile app, an embedded device, or a cloud service. This final topic covers the main deployment paths, each suited to a different production environment.

The Deployment Pipeline

Research / Training
    │
    ▼ torch.save() / model.eval()
Trained Model (.pth or .pt)
    │
    ├──▶ Flask / FastAPI REST API    ← web server, any client
    ├──▶ TorchServe                  ← PyTorch's production model server
    ├──▶ TorchScript + C++           ← high-performance backend
    ├──▶ ONNX Runtime                ← framework-agnostic inference
    └──▶ PyTorch Mobile              ← iOS / Android on-device

Step 1: Prepare the Model for Inference

Before deploying, always set the model to evaluation mode and wrap inference in torch.no_grad(). This disables dropout and batch norm's training behavior, reduces memory use, and speeds up inference.

import torch
import torch.nn as nn

# Load trained weights
model = MyModel()
model.load_state_dict(torch.load('best_model.pth', map_location='cpu'))
model.eval()

def predict(input_tensor):
    with torch.no_grad():
        output = model(input_tensor)
        return output

Deployment Option 1: Flask REST API

Wrap the model in a Flask web server. Clients send POST requests with input data and receive predictions as JSON responses. This is the quickest path to serving a model over HTTP.

from flask import Flask, request, jsonify
import torch

app   = Flask(__name__)
model = MyModel()
model.load_state_dict(torch.load('best_model.pth', map_location='cpu'))
model.eval()

@app.route('/predict', methods=['POST'])
def predict():
    data = request.json['input']              # list of floats from client
    x    = torch.tensor(data, dtype=torch.float32).unsqueeze(0)
    with torch.no_grad():
        output = model(x)
    return jsonify({'prediction': output.tolist()})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
Client sends:
  POST http://localhost:5000/predict
  {"input": [1.2, 0.5, -0.3, 0.8]}

Server returns:
  {"prediction": [[0.72, 0.19, 0.09]]}

Deployment Option 2: FastAPI (Modern REST API)

FastAPI is faster than Flask, has automatic input validation, and generates interactive API documentation automatically. It is the preferred framework for new ML API projects.

from fastapi import FastAPI
from pydantic import BaseModel
import torch

app = FastAPI()

model = MyModel()
model.load_state_dict(torch.load('best_model.pth', map_location='cpu'))
model.eval()

class PredictRequest(BaseModel):
    input: list[float]

@app.post('/predict')
def predict(req: PredictRequest):
    x = torch.tensor(req.input, dtype=torch.float32).unsqueeze(0)
    with torch.no_grad():
        out = model(x)
    return {'prediction': out.tolist()}

# Run with: uvicorn app:app --host 0.0.0.0 --port 8000

Deployment Option 3: TorchServe

TorchServe is PyTorch's official production model server. It handles batching, logging, multi-model serving, A/B testing, and REST endpoints automatically. It is the recommended path for production-grade serving at scale.

Workflow:
  1. Archive model: torch-model-archiver --model-name mymodel ...
  2. Start server:  torchserve --start --model-store=model_store
  3. Register:      curl -X POST "http://localhost:8081/models?model_name=mymodel&url=mymodel.mar"
  4. Predict:       curl -X POST http://localhost:8080/predictions/mymodel -T input.json

TorchServe handles:
  ✓ Multiple concurrent requests
  ✓ Request batching for GPU efficiency
  ✓ Health checks and metrics
  ✓ Model versioning and hot-swapping

Deployment Option 4: Docker Container

Packaging your model server in a Docker container makes deployment reproducible across any cloud provider or on-premise server.

# Dockerfile example
FROM python:3.10-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY best_model.pth .
COPY app.py .

EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
Build and run:
  docker build -t my-model-api .
  docker run -p 8000:8000 my-model-api

Deploy to cloud:
  AWS: push to ECR → deploy on ECS or EKS
  GCP: push to Artifact Registry → deploy on Cloud Run
  Azure: push to ACR → deploy on ACI or AKS

Deployment Option 5: PyTorch Mobile

For on-device inference without a network call — essential for privacy, offline use, or latency-sensitive apps — deploy directly to iOS or Android.

from torch.utils.mobile_optimizer import optimize_for_mobile

model.eval()
scripted   = torch.jit.script(model)
optimized  = optimize_for_mobile(scripted)
optimized._save_for_lite_interpreter('model_mobile.ptl')
# Bundle model_mobile.ptl with your iOS / Android app

Preprocessing and Postprocessing in Deployment

A deployed model needs the same preprocessing applied during training — normalization, resizing, tokenization. Always package these steps with the model so the API doesn't receive raw inconsistent input.

from torchvision import transforms

preprocess = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])
])

def predict_image(pil_image):
    x = preprocess(pil_image).unsqueeze(0)
    with torch.no_grad():
        logits = model(x)
        probs  = torch.softmax(logits, dim=1)
        top1   = probs.argmax(dim=1).item()
    return {'class_index': top1, 'confidence': probs[0, top1].item()}

Deployment Checklist

Before deploying:
  ✓ model.eval() called
  ✓ torch.no_grad() wrapping inference
  ✓ Same preprocessing as training
  ✓ Input validation (type, shape, range)
  ✓ Error handling for bad inputs
  ✓ Tested on edge cases
  ✓ Logging and monitoring set up
  ✓ Version pinned (PyTorch, torchvision, etc.)
  ✓ GPU/CPU device consistent between training and serving

Choosing a Deployment Path

Use case                          Recommended approach
──────────────────────────────────────────────────────────
Quick prototype API               Flask or FastAPI
Production API                    FastAPI + Docker or TorchServe
High-throughput GPU serving       TorchServe + batching
C++ backend integration           TorchScript → LibTorch
Cross-framework compatibility     ONNX + ONNX Runtime
Mobile (iOS/Android)              PyTorch Mobile (.ptl)
Edge / microcontroller            Quantize + TorchScript or ONNX

Summary

Model deployment takes a trained model into a production environment where it serves real predictions. Always call model.eval() and use torch.no_grad() at inference time. Flask and FastAPI serve models as REST APIs — FastAPI is the modern choice. TorchServe provides full production features including batching, monitoring, and versioning. Docker makes deployments reproducible across environments. PyTorch Mobile deploys models on-device to iOS and Android. ONNX export enables inference on hardware that has no PyTorch support. Always include the same preprocessing pipeline in your serving code that was used during training. Deployment is not an afterthought — a well-deployed model is what turns research into real-world impact.

Leave a Comment

Your email address will not be published. Required fields are marked *