Scope owned: Proof of Concept (POC), ETL Pipeline, Machine Learning Model, REST API, Web Interface
This document covers the components I personally built for the OpenHousing project — an instant real estate valuation tool for the Housing Observatory use case.
Before building production code, I validated feasibility in a Jupyter notebook using the real Boston Housing dataset.
- Source data: BostonHousing.csv — 506 records, 13 features + target
- Steps: data load → exploratory analysis (correlation heatmap) → baseline model comparison (Linear Regression vs. Random Forest) → feature importance
- Result: Random Forest achieved R² ≈ 0.88, confirming the dataset carries enough signal to proceed to a production pipeline
A three-stage pipeline, chained by a single orchestrator script.
| File | Responsibility |
|---|---|
extract.py |
Downloads the raw dataset from the source URL, saves a local copy |
transform.py |
Handles missing values (median imputation), removes invalid rows, converts target to full USD (price_usd = medv * 1000), engineers one derived feature (rooms_per_dis) |
load.py |
Saves the cleaned dataset to data/processed_housing.csv |
pipeline.py |
Runs Extract → Transform → Load as a single command |
Run it:
cd etl
python pipeline.py-
Model: Random Forest Regressor (
n_estimators=300,max_depth=10) -
Features (13):
crim, zn, indus, chas, nox, rm, age, dis, rad, tax, ptratio, b, lstat -
Target:
price_usd -
Split: 80/20 train/test,
random_state=42 -
Performance:
Metric Value R² 0.880 MAE ~$2,076 RMSE ~$2,964 -
Output: trained model + feature list bundled and saved to
ml/model.pklviajoblib
Run it:
cd ml
python train.pyBuilt with FastAPI, loads the trained model once at startup and serves predictions.
| Endpoint | Method | Purpose |
|---|---|---|
/ |
GET | API status check |
/health |
GET | Health check (uptime monitoring) |
/predict |
POST | Accepts 13 property/tract features, returns predicted_price_usd |
/docs |
GET | Auto-generated interactive Swagger UI |
Input validation is handled via Pydantic — malformed requests are rejected automatically before reaching the model.
Run it:
uvicorn api.main:app --reload --port 8001A live, real-time valuation UI served directly by the API at /app/:
- Form covering all 13 model inputs, grouped into Property, Neighborhood, and Civic & Tax
- Calls
/predictautomatically as the user edits fields (debounced), plus a manual "Update estimate" button - Displays the result as a listing-style card with price, live stat strip, and the model's R² confidence
No separate frontend server needed — mounted directly on the FastAPI app via StaticFiles.
extract.py -> transform.py -> load.py (ETL: raw data -> processed_housing.csv)
|
train.py (ML: processed_housing.csv -> model.pkl)
|
api/main.py (loads model.pkl, serves /predict)
|
static/index.html (calls /predict, displays live result)
Python 3.11 - pandas - scikit-learn - FastAPI - Uvicorn - joblib - vanilla HTML/CSS/JS (no frontend framework)
- Target currency is USD, converted from the source dataset's
medv(in $1000s) - No MLflow/Optuna/XGBoost/PostgreSQL — this implementation intentionally kept the stack minimal (CSV-based storage, Random Forest, no experiment tracking) to match project scope and timeline; flagging in case slides referencing those tools need to be reconciled with the actual codebase
To make the application portable and easy to deploy, the entire backend was containerized using Docker and deployed on Render.
Docker Created a Dockerfile to package the FastAPI application, trained model, and dependencies into a single container. Configured the application to run with Uvicorn on port 8001. Ensured the API, static web interface, and ML model are all available from the same container.
Run locally with Docker:
docker build -t openhousing . docker run -p 8001:8001 openhousing
The application is then accessible at:
API: http://localhost:8001/ Web UI: http://localhost:8001/app Render Cloud: https://openhousing-8q7c.onrender.com/app/ Render Cloud Deployment Deployed the Docker container to Render as a Web Service. Configured Render to build the Docker image automatically from the repository. Exposed port 8001 for serving the FastAPI application. Enabled automatic deployments on new commits, allowing updates to be published without manual server configuration.