--- title: Heart Attack Risk Predictor emoji: ๐ซ colorFrom: blue colorTo: purple sdk: docker app_file: app.py pinned: false ---
An AI-powered clinical decision-support tool that estimates a patient's heart-attack risk from tabular patient data, an ECG image, or both โ using an ensemble-router architecture with a tabular model, an ECG image model, and late-fusion of their scores.
๐ด TRY THE LIVE DEMO ON HUGGING FACE SPACES ๐ด
โ ๏ธ Educational / portfolio demo โ not a medical device. Do not use for real clinical decisions.
--- ## ๐ Table of Contents - [What's New in v2](#-whats-new-in-v2) - [Key Features](#-key-features) - [How It Works โ Architecture](#-how-it-works--architecture) - [The Two Models](#-the-two-models) - [Tech Stack](#-tech-stack) - [Project Structure](#-project-structure) - [Getting Started](#-getting-started) - [Usage & API](#-usage--api) - [Model Performance](#-model-performance) - [Testing](#-testing) - [Limitations & Honesty](#-limitations--honesty) - [Team Members](#-team-members) --- ## ๐ What's New in v2 Version 1 was a single-model biomarker classifier (8 vitals โ Random Forest). A leakage test showed its ~98% accuracy was largely a biomarker-threshold rule (accuracy fell to ~62% without Troponin & CK-MB). Version 2 re-architects the project into a **multimodal ensemble router**: - **Two models** instead of one โ a **tabular** model and an **ECG image** model. - **A router** that picks the model(s) based on what the user submits, and **averages** their scores when both are provided. - **Honest evaluation** โ proper metrics (ROC-AUC for the imbalanced tabular task, per-class metrics for the ECG task) and a clear statement of limitations. > The original v1 biomarker research is preserved in `research_and_experiments/`. --- ## โจ Key Features - **Multimodal input** โ enter patient data, upload an ECG image, or do both. - **Ensemble router** โ one `POST /predict` endpoint routes to the right model(s): tabular โ Model A, ECG โ Model B, both โ averaged score. - **Missing-data friendly** โ blank tabular fields are filled automatically by **K-Nearest-Neighbours imputation**, so a partial form still works. - **Server-side validation** โ out-of-range or non-numeric fields are rejected with a clear message (HTTP 422). - **ECG confidence check** โ low-confidence ECG predictions are flagged ("may not be a clear 12-lead ECG"). - **Transparent results** โ the UI shows each model's score and, in "both" mode, the combined average, so nothing is a black box. - **Modern UI** โ dark glassmorphism theme, drag-and-drop ECG upload, color-coded risk badges (๐ด High / ๐ก Moderate / ๐ข Low). --- ## ๐ง How It Works โ Architecture ``` โโโโโโโโโโโโโโโโโ POST /predict (multipart/form-data) โโโโโโโโโโโโโโโโโ tabular only โโคโ Model A (Framingham: KNN-impute โ scale โ RandomForest) โ p_a โโ โ โ โโ both โ average โ p โ band (Low/Mod/High) ECG only โโโโโโคโ Model B (ResNet18 transfer learning on ECG images) โ p_b โโ โ โ โ neither โโโโโโโคโ HTTP 400 โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ ``` Each model outputs a scalar **risk probability** `p โ [0, 1]`. That value is mapped to a band โ **Low** (`< 0.33`), **Moderate** (`0.33โ0.66`), **High** (`> 0.66`) โ and, when both models run, the two scores are combined by an equal-weight average. --- ## ๐ค The Two Models ### Model A โ Tabular (Framingham 10-year CHD) - **Data:** Framingham Heart Study (4,240 patients, 15 clinical features). - **Target:** `TenYearCHD` โ probability of coronary heart disease within 10 years. - **Pipeline:** `StandardScaler โ KNNImputer(k=5) โ classifier`, saved as one artifact. - **Model selection:** RandomForest vs XGBoost by 5-fold CV ROC-AUC โ **RandomForest won (0.69 vs 0.67)**. - **Handles imbalance** (~15% positive) with class weighting; the app uses the continuous probability, not a hard 0.5 cutoff. ### Model B โ ECG image (ResNet18) - **Data:** ECG Images Dataset of Cardiac Patients (928 images, 4 classes). - **Method:** **transfer learning** โ a ResNet18 pretrained on ImageNet, with a new 4-class head; train the head, then fine-tune the last block. - **Classes โ risk weight:** Normal `0.0`, abnormal heartbeat `0.5`, post-MI history `0.8`, myocardial infarction `1.0`. The 4-class softmax is collapsed to one risk score via these weights. --- ## ๐ ๏ธ Tech Stack | Layer | Technology | Purpose | |---|---|---| | **Backend** | [FastAPI](https://fastapi.tiangolo.com/) + [Uvicorn](https://www.uvicorn.org/) | Async web framework + ASGI server; multipart `/predict` router | | **Tabular ML** | [scikit-learn](https://scikit-learn.org/) (`RandomForest`, `KNNImputer`, `StandardScaler`), [XGBoost](https://xgboost.readthedocs.io/) | Model A pipeline + model comparison | | **Image ML** | [PyTorch](https://pytorch.org/) + [torchvision](https://pytorch.org/vision/) (ResNet18) | Model B transfer learning | | **Images / Uploads** | [Pillow](https://python-pillow.org/), `python-multipart` | ECG image decoding + file uploads | | **Data** | [pandas](https://pandas.pydata.org/), [NumPy](https://numpy.org/) | Data handling | | **Frontend** | HTML5, CSS3, Vanilla JS | Single-page glassmorphism UI with ECG drag-and-drop | | **Deployment** | Docker โ Hugging Face Spaces | Containerized serving on port 7860 | --- ## ๐ Project Structure ``` heart-attack-risk-predictor/ โ โโโ app.py # FastAPI app + ensemble router (multipart /predict) โโโ requirements.txt # Production dependencies โโโ Dockerfile # Container build (copies app, inference/, models/, static/) โ โโโ inference/ # Serving-time prediction package โ โโโ fusion.py # Risk bands + late-fusion (combine) โ โโโ framingham.py # Model A inference (with KNN imputation) โ โโโ ecg.py # Model B inference (softmax โ risk scalar) โ โโโ validation.py # Server-side field validation โ โโโ models/ # Trained artifacts (Git LFS) โ โโโ framingham_pipeline.joblib # Model A bundle โ โโโ ecg_resnet.pt # Model B weights โ โโโ ecg_classes.json # ECG class list + risk weights + preprocessing โ โโโ train_framingham.py # Trains Model A โโโ train_ecg.py # Trains Model B โ โโโ static/index.html # Frontend (form + ECG upload + per-branch results) โ โโโ DOCUMENTATION.md # Full technical documentation โโโ DEFENSE_GUIDE.md # Beginner-friendly project defense guide โ โโโ research_and_experiments/ # v1 biomarker research (notebook, dataset, old model) ``` --- ## ๐ Getting Started ### Prerequisites - Python **3.11+** (3.12 recommended) ### Install ```bash git clone https://github.com/Shahd1Sayed/heart-attack-risk-predictor.git cd heart-attack-risk-predictor pip install -r requirements.txt ``` ### Data (only needed to (re)train โ download from Kaggle) ``` data/framingham.csv # "Framingham Heart Study dataset" data/ecg_data/