Spaces:
Sleeping
Sleeping
File size: 6,081 Bytes
11e8ba2 425532a 11e8ba2 dc3d345 bf27edd dc3d345 bf27edd dc3d345 bf27edd dc3d345 bf27edd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ---
title: NephroScreen
emoji: 🩺
colorFrom: green
colorTo: blue
sdk: docker
app_port: 8000
pinned: false
license: mit
---
# NephroScreen — Early Chronic Kidney Disease Screening
**An end-to-end applied machine-learning case study.** It estimates chronic
kidney disease (CKD) risk from routine clinical lab values — a **leakage-safe
scikit-learn pipeline**, a **FastAPI** service, and a **clean web interface**,
deployable on a free tier.
📄 **[Read the case study →](CASE_STUDY.md)** · ⚕️ *Educational project — not a
medical device.* Trained on a small public dataset (400 patients) and *not*
validated for clinical use.
---
## Why this project is interesting (the honest version)
On the UCI CKD dataset the models reach near-perfect scores — Random Forest hits
**100% test accuracy**. On most portfolios that number would be presented as the
headline. Here it is treated as a **teaching moment**, which is the more
defensible engineering story:
- The dataset is small (400 rows) and the classes are **highly separable** on a
handful of biomarkers (hemoglobin, PCV, serum creatinine). 100% is a *property
of the data*, not evidence of a deployable clinical model.
- The interesting engineering is therefore **not** the accuracy — it's doing the
workflow *correctly*: no data leakage, honest validation, a screening-aware
decision threshold, interpretability, and a reproducible serving path.
## Highlights
| Area | What's here |
|---|---|
| **Leakage-safe pipeline** | Custom `CKDPreprocessor` (imputation, encoding, feature engineering) fit on the **training fold only**, wrapped in a scikit-learn `Pipeline` so CV and serving never see test statistics. |
| **Screening-aware threshold** | Decision threshold tuned to keep **recall ≥ 0.99** — a missed CKD case is the costly error in screening. |
| **Interpretability** | Per-prediction, rule-based clinical indicators in the API; global + local **SHAP** analysis in the notebook. |
| **Serving** | Trained pipeline persisted with `joblib`; **FastAPI** loads it once and serves JSON predictions. |
| **Frontend** | Dependency-free HTML/CSS/JS single page; imputes missing fields so a partial lab panel still works. |
| **Reproducible** | Pinned dependencies; fixed seeds; automated `pytest` suite. |
## Model performance
Held-out test set (80 patients), 10-fold stratified CV, `random_state=42`:
| Model | Accuracy | Precision | Recall | F1 | ROC-AUC | 10-Fold CV |
|---|---|---|---|---|---|---|
| Logistic Regression | 98.75% | 100% | 98% | 98.99% | 1.0000 | 99.38% ± 1.25% |
| **Random Forest** (served) | **100%** | 100% | 100% | 100% | 1.0000 | 98.75% ± 2.86% |
| Decision Tree | 97.50% | 98% | 98% | 98% | 0.9893 | 96.56% ± 2.19% |
Top Random Forest predictors: hemoglobin, packed cell volume, serum creatinine,
`kidney_stress_index` (engineered), red blood cell count.
## Interpretability & maturity
Full write-up in the **[case study](CASE_STUDY.md)**. In short:
| SHAP — why the model decides | Calibration | Screening threshold |
|---|---|---|
|  |  |  |
- **SHAP** attributions are clinically coherent (low hemoglobin/PCV, high
creatinine, hypertension/diabetes drive CKD predictions).
- **Calibration** curve checks the probabilities are trustworthy, not just the labels.
- **Recall-tuned threshold (0.62)** — for screening, a missed case costs more
than a false alarm, so the served threshold keeps recall ≥ 0.99.
## Architecture
```
Browser (frontend/) ──POST /api/predict──► FastAPI (api/) ──► joblib pipeline (models/)
│
CKDPreprocessor → RandomForest
```
```
src/nephroscreen/ config · preprocessing · train (the ML package)
api/ main (FastAPI) · schemas (pydantic) (the service)
frontend/ index.html · style.css · app.js (the UI)
models/ ckd_pipeline.joblib · metrics.json (trained artifacts)
notebooks/ analysis.ipynb (SHAP + calibration) (the analysis)
tests/ test_api.py
```
## Quickstart
```bash
python -m venv .venv && source .venv/Scripts/activate # Windows Git Bash
pip install -r requirements.txt && pip install -e .
python -m nephroscreen.train # trains + saves models/ckd_pipeline.joblib
uvicorn api.main:app --reload # http://127.0.0.1:8000
pytest # run the test suite
```
Open <http://127.0.0.1:8000> for the UI, or <http://127.0.0.1:8000/docs> for the
interactive API docs.
### API
```bash
curl -X POST http://127.0.0.1:8000/api/predict \
-H "Content-Type: application/json" \
-d '{"hemo": 9.5, "sc": 3.2, "al": 3, "htn": "yes", "dm": "yes"}'
```
```json
{ "prediction": "CKD", "probability": 0.98, "risk_band": "High",
"threshold": 0.62, "key_indicators": [ ... ] }
```
## Deployment (free tier)
- **One box (recommended):** deploy the whole app on **Render** (`render.yaml`
included) or any Docker host (`Dockerfile` included). FastAPI serves both the
API and the static frontend.
- **Split hosting:** put `frontend/` on **Vercel/Netlify** (static) and the API
on **Render**; set `window.NEPHRO_API_BASE` in the frontend to the API URL.
- Free instances sleep when idle; expect a ~30–50s cold start on first request.
## Limitations & future work
- Single small, single-source dataset → near-perfect scores do **not** transfer
to real clinical populations.
- Future: external validation on an independent cohort; a **minimal low-cost
feature subset** for resource-limited screening; fairness analysis across age
and sex; hyperparameter tuning; probability calibration in the serving path.
## Credits
Solo project by **Sadiq Mansoor** — see [CREDITS.md](CREDITS.md). An independent
rebuild and extension of an earlier university coursework analysis. Dataset: UCI
ML Repository, Chronic Kidney Disease (ID 336). Licensed under [MIT](LICENSE).
|