No. 03 — ML Engineering

A model, deployed.

Taking a student depression classifier from a Jupyter notebook all the way to a production REST API — containerized, monitored, and live.

ML EngineeringMay 2025Solo

Most machine learning projects end as notebooks. Accurate on the training set, presentable in a PDF, and never heard from again. I wanted to know what it actually takes to make one useful — to turn a classification model into something that could respond to a real HTTP request in under half a second, from anywhere in the world.

This is the record of that process: from a trained TensorFlow model to a Dockerized FastAPI service, deployed on Render and callable right now from the playground at the bottom of this page.

82%Model Accuracy
0.91AUC Score
27KTraining SamplesBehavioral survey data
<500msAvg. Response Time
I.The Problem

The original project was a data science final: predict depression among students from survey responses using 18 behavioral and academic features. The model trained well — 82% accuracy, AUC of 0.91 — but it existed only as a Scikit-learn pipeline inside a notebook.

That’s a common stopping point. But a model that only runs locally isn’t a product. The interesting question was: what does it take to make it callable by anyone?

II.The Architecture

The stack is deliberately simple. FastAPI for the HTTP layer — it handles request validation, OpenAPI generation, and async routing without ceremony. Pydantic schemas enforce input contracts at the boundary: wrong types get rejected with a 422 before the model ever sees the data.

Everything runs in a single Docker container. The image includes the serialized model artifacts, the preprocessing pipeline, and a /health endpoint so the orchestrator knows when the service is ready. Render pulls the image on every push to main, rebuilds, and swaps traffic with zero downtime.

CI/CD via GitHub Actions runs a smoke test on every pull request. The deploy only happens if the container starts and the health check passes.

III.What the Model Learned

SHAP analysis on the full 18-feature model surfaced a clear hierarchy. The five features below explain the majority of prediction variance — the rest added noise rather than signal. Trimming to them cut inference payload size without measurably affecting accuracy.

Top SHAP Features
Suicidal_Thoughts

Strongest single predictor across all tested models.

bool
Academic_Pressure

Self-reported scale of academic burden (1–5).

float
Financial_Stress

Perceived financial strain over the study period (1–5).

float
Work_Study_Hours

Daily hours spent working or studying — higher load correlates with elevated risk.

float
Dietary_Habits

Encoded as ordinal: Healthy → Moderate → Unhealthy.

string

The model also takes Age as a sixth input — a weaker individual predictor but one that sharpens confidence at boundary cases.

A model that only runs locally isn’t a product. The interesting question was: what does it take to make it callable by anyone?
IV.The Deployment

The Render deployment runs on the free tier — which means the instance sleeps after a period of inactivity. The first request after a cold start incurs a spin-up delay of up to 90 seconds. Subsequent requests hit the <500 ms target consistently.

This is a deliberate tradeoff: zero infrastructure cost for an unpredictable audience, at the expense of cold-start latency. A production deployment would use a paid instance or a keep-alive ping to hold the process warm.

V.Limitations

The training data is synthetic — generated to approximate the distribution of a real student mental health survey but not drawn from clinical subjects. The model should not be used to make real-world clinical assessments.

The API is also unauthenticated. For a real deployment handling sensitive health data, you would want JWT or API key gating at minimum, and likely compliance review depending on jurisdiction.

SHAP feature selection was done on the training split. Selection bias is possible — the dropped features may generalize better on out-of-distribution data than the retained ones.

VI.API Playground

The API is live. Adjust the sliders, select your inputs, and hit Predict — the request goes to the actual deployed model on Render.

POST /predict
depression-api-e0l4.onrender.com
21
1840
3
15
3
15
6
112

Suicidal Thoughts

One of the model’s top SHAP-ranked features.

Request Body
{
  "Age": 21,
  "Dietary_Habits": "Moderate",
  "Suicidal_Thoughts": false,
  "Academic_Pressure": 3,
  "Financial_Stress": 3,
  "Work_Study_Hours": 6
}
Colophon

Model trained in TensorFlow and Scikit-learn. API built with FastAPI and validated via Pydantic. Containerized with Docker and deployed on Render with GitHub Actions CI/CD. Feature importance via SHAP.

The Index— fin —