Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Healthcare Disease Prediction Platform

A demonstration risk-scoring platform covering five conditions — diabetes, heart disease, stroke, liver disease, and kidney disease — built to show what a genuinely end-to-end system looks like: synthetic data generation, model selection, explainability, rule-based clinical recommendations, a FastAPI backend, a Streamlit dashboard, and a PDF report generator, all wired to the same prediction service so the two frontends can never drift apart.

This is a demonstration system trained on synthetic data. It is not a medical device, has not been validated on real patients, and must not be used for real clinical decision-making.

Why synthetic data

No real patient data is used anywhere in this project. Each disease's dataset is generated to match the shape of well-known public screening datasets — feature names, plausible clinical ranges, and known correlations (Pima diabetes, Cleveland heart disease, the common stroke-prediction schema, the Indian Liver Patient Dataset, and the UCI chronic kidney disease schema) — then labeled from a weighted, noisy combination of the real risk factors, so the models learn genuine, explainable structure instead of noise. See src/data_generation.py.

Architecture

Synthetic data generator (src/data_generation.py)
        │
        ▼
Training pipeline (src/training.py)          — LogisticRegression vs RandomForest,
        │                                        5-fold CV, best model persisted per disease
        ▼
Prediction service (src/prediction.py)  ──────────────┐
        │                                              │
        ▼                                              ▼
Explainability (src/explainability.py, SHAP)   Recommendations (src/recommendations.py)
        │                                              │
        └──────────────────┬───────────────────────────┘
                            ▼
              FastAPI backend (api/)  +  Streamlit dashboard (dashboard/)
                            │
                            ▼
                 PDF report generator (src/pdf_report.py)

Why recommendations are rules, not another model: stacking a second black-box model on top of the risk model would make the "explanation" just as opaque as the prediction it explains. Instead, each disease has a short list of named clinical thresholds (e.g. "ALT ≥ 80" for liver disease) that a reviewer can check directly against the patient's values.

API architecture

The FastAPI app is split by responsibility rather than living in one file:

  • api/main.py — assembly only: builds the app, wires middleware, mounts routers
  • api/routers/health.py/healthz (liveness) and /readyz (readiness — reports per-disease model availability, suitable for an orchestrator's readiness gate)
  • api/routers/diseases.py — catalog, schema, and metrics endpoints
  • api/routers/predict.py — one POST route per disease, dynamically generated from DiseaseSpec so /docs can never drift from what the model actually requires
  • api/deps.py — dependency-injection providers (ModelRegistry, Settings) so routers are testable via app.dependency_overrides, not real disk/model access
  • api/middleware.py — request-ID correlation and latency logging on every request
  • src/exceptions.py — typed domain errors (UnknownDiseaseError, ModelNotTrainedError, PredictionError), each mapped to the correct HTTP status in exactly one place (api/main.py's exception handlers) instead of scattered try/except HTTPException blocks per route

Configuration is centralized in src/config.py's Settings (via pydantic-settings), reading from environment variables prefixed HDPP_ or a .env file — see .env.example. Predict endpoints are rate-limited separately from read endpoints (HDPP_RATE_LIMIT_PREDICT, default 20/minute).

Project layout

healthcare-platform/
├── data/raw/                 synthetic per-disease CSVs (generated, not committed)
├── models/                   trained pipeline + metrics per disease (generated)
├── src/
│   ├── config.py              disease specs (features/targets/paths) + env-driven Settings
│   ├── exceptions.py           typed domain error hierarchy shared by API + dashboard
│   ├── logger.py               shared logging setup
│   ├── data_generation.py      synthetic data generator for all 5 diseases
│   ├── training.py              LogisticRegression vs RandomForest, CV, persistence
│   ├── explainability.py        generic SHAP wrapper (works for either model type)
│   ├── recommendations.py       rule-based doctor recommendation engine
│   ├── prediction.py            ModelRegistry + unified prediction service (used by API + dashboard)
│   └── pdf_report.py            one-page patient PDF report (reportlab)
├── api/
│   ├── main.py                 app assembly: middleware, exception handlers, router mounting
│   ├── deps.py                  FastAPI dependency-injection providers
│   ├── middleware.py            request-ID + latency logging middleware
│   └── routers/
│       ├── health.py             /healthz, /readyz
│       ├── diseases.py           /v1/diseases catalog, schema, metrics
│       └── predict.py            /v1/predict/{disease} — rate-limited
├── dashboard/
│   ├── app.py                  Home / executive summary — search, KPI cards, dark mode
│   ├── theme.py                 CSS-variable theming (light/dark), sticky nav, skeleton loaders
│   ├── common.py                shared per-disease page renderer (no duplication)
│   └── pages/                   Diabetes, Heart Disease, Stroke, Liver Disease,
│                                  Kidney Disease, Model Insights, About
├── tests/                     78 pytest tests across every module
├── requirements.txt
├── .env.example
├── Dockerfile
├── docker-compose.yml
└── README.md

Running it locally

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# Generate the synthetic datasets (one CSV per disease, ~4,000 rows each)
python -m src.data_generation

# Train and select a model per disease (compares LogisticRegression vs
# RandomForest by 5-fold CV, persists the winner)
python -m src.training

# API — docs at http://localhost:8000/docs, health at /healthz, readiness at /readyz
uvicorn api.main:app --reload --port 8000

# Dashboard (separate terminal) — http://localhost:8501
streamlit run dashboard/app.py

Running it with Docker

docker compose up --build
# API:       http://localhost:8000/docs
# Dashboard: http://localhost:8501

The image runs data generation and training once at build time, so both containers start with ready-to-serve models sharing a models-data volume.

Running tests

pytest tests/ -v

78 tests across data generation (schema, label balance, missing values), training (artifact creation, minimum performance bar, split integrity), prediction (output shape, SHAP direction sanity-check), the recommendation engine (band thresholds, rule triggers), PDF report generation (valid file signature), and the FastAPI backend (all endpoints, validation, error codes).

API reference

GET  /                              service info + list of available diseases
GET  /v1/diseases                   feature list per disease
GET  /v1/diseases/{key}/metrics     trained-model metrics for one disease
POST /v1/predict/{key}              run a prediction (key = diabetes | heart_disease |
                                     stroke | liver_disease | kidney_disease)

Each disease's POST body schema is generated directly from its feature list — see /docs for the exact required fields per disease.

Example

curl -X POST http://localhost:8000/v1/predict/diabetes \
  -H "Content-Type: application/json" \
  -d '{
    "pregnancies": 2, "glucose": 150, "blood_pressure": 80,
    "skin_thickness": 25, "insulin": 120, "bmi": 33,
    "diabetes_pedigree": 0.6, "age": 45
  }'

Response:

{
  "disease": "Diabetes",
  "probability": 0.42,
  "risk_category": "Moderate",
  "top_contributors": [
    {"feature": "glucose", "shap_value": 0.81},
    {"feature": "bmi", "shap_value": 0.34}
  ],
  "general_advice": "Recommend a follow-up consultation within 3 months and repeat panel testing.",
  "specific_flags": ["Fasting/random glucose is elevated — recommend HbA1c confirmation test."],
  "disclaimer": "This output is generated by a demonstration model trained on synthetic data...",
  "model_used": "logistic_regression",
  "model_test_roc_auc": 0.9726
}

Dashboard pages

Page What it's for
Home Executive summary — live KPIs computed from the trained models' metrics files.
Diabetes / Heart Disease / Stroke / Liver Disease / Kidney Disease Patient input form → risk score, SHAP explanation chart, recommendations, PDF download.
Model Insights Cross-disease comparison of chosen model, ROC-AUC, F1, precision, recall.
About Design decisions, data provenance, and explicit limitations.

Extending it

  • Add a sixth disease: add one DiseaseSpec entry to src/config.py, one generator function in src/data_generation.py, and one rule list in src/recommendations.py. Training, the API endpoint, explainability, and the PDF report all pick it up automatically — only the dashboard needs a new thin page file that calls render_disease_page("your_key").
  • Swap in real data: replace the CSVs src/data_generation.py produces in data/raw/ with real (properly consented, de-identified) clinical data using the same column names, then re-run python -m src.training.
  • Add a model type: extend the candidates dict in src/training.py::train_one_disease; SHAP explainability and the API/ dashboard require no changes since they only depend on predict_proba.

Known limitations

  • Not validated on real patients; all reported metrics are against a held-out split of the same synthetic generator, not an independent real-world population.
  • The recommendation engine's thresholds are illustrative demonstrations, not sourced from a clinical guideline body.
  • SHAP values explain what the model learned from the (synthetic) training data, not a causal medical claim.

About

Shubham Panchal

— Data Analytics | Data Science | AI | Machine Learning | Business Intelligence

LinkedIn: https://linkedin.com/in/shubham-panchal-a100282a8

About

Multi-disease risk prediction platform diabetes, heart disease, stroke, liver disease & kidney disease with SHAP explainability, a FastAPI backend, and a Streamlit dashboard. Trained on synthetic data for demonstration purposes.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages