Inference-first web interface for a CIFAR-10 CNN project using FastAPI and a PyTorch CNN model.
Demo: https://cifar10-pytorch.up.railway.app/
The production cnnv2 model is a 3-stage convolutional network for CIFAR-10 (32x32 RGB input) with batch normalization and progressively stronger dropout regularization.
| Stage | Layers | Output Shape | Dropout |
|---|---|---|---|
| Input | RGB image | [B, 3, 32, 32] |
- |
| Stage 1 | Conv(3->64) + BN + ReLU x2, MaxPool(2) |
[B, 64, 16, 16] |
0.15 |
| Stage 2 | Conv(64->128) + BN + ReLU x2, MaxPool(2) |
[B, 128, 8, 8] |
0.20 |
| Stage 3 | Conv(128->256) + BN + ReLU x2, MaxPool(2) |
[B, 256, 4, 4] |
0.30 |
| Head | AdaptiveAvgPool2d(1), Flatten |
[B, 256] |
- |
| Classifier | Linear(256->10) |
[B, 10] |
- |
[B, 3, 32, 32] -> [B, 64, 16, 16] -> [B, 128, 8, 8] -> [B, 256, 4, 4] -> [B, 256, 1, 1] -> [B, 256] -> [B, 10]
- All convolutions use
3x3kernels withpadding=1to preserve spatial resolution inside each stage. - Convolutions are created with
bias=Falsebecause each is immediately followed by BatchNorm. - Dropout increases by depth (
0.15 -> 0.20 -> 0.30) to regularize higher-level features. - The final layer outputs raw logits (no softmax in-model); post-processing (e.g., probabilities) is applied at inference time.
Metrics below are from src/reports/results.json on the CIFAR-10 test set.
| Model | Accuracy | Macro Precision | Macro Recall | Macro F1 |
|---|---|---|---|---|
cnnv2 |
90.56% |
90.53% |
90.56% |
90.52% |
baseline |
77.17% |
76.99% |
77.17% |
77.03% |
- Install dependencies:
uv sync
- Start the web app:
uv run uvicorn webapp.main:app --host 0.0.0.0 --port 8000 --reload
- Open:
http://localhost:8000/http://localhost:8000/docs
- Build:
docker build -t cifar10-fastapi . - Run:
docker run --rm -p 8000:8000 -e PORT=8000 cifar10-fastapi
- Verify:
http://localhost:8000/health
- The production image is optimized for Railway with a multi-stage Docker build.
- Runtime dependencies are split into:
requirements.railway.txt(FastAPI/runtime libs from PyPI)requirements.railway.torch.txt(CPU-onlytorch/torchvisionfrom the PyTorch CPU index)
- This avoids downloading CUDA packages in cloud builds and reduces image push/build overhead.
- Docker targets:
runtimetarget (default): slim image for Railway/prod.devtarget: addswatchfilesfor better local hot reload UX.
- Start development container:
The compose file builds Docker
docker compose -f docker-compose.dev.yml up --build
target: dev, which enableswatchfiles-based reloads for*.py,*.html,*.css, and*.js. - Edit files in
webapp/orsrc/and changes reload automatically in the running container. - Open:
http://localhost:8000/http://localhost:8000/docs
| Method | Path | Purpose |
|---|---|---|
| GET | /health |
service readiness and loaded models |
| POST | /api/v1/predict |
single-image prediction (multipart upload) |
| GET | /api/v1/reports |
metrics + figure metadata for UI |
| GET | / |
demo page |
- Checkpoints expected at:
src/checkpoints/best_baseline.pthsrc/checkpoints/best_cnnv2.pth



