Placeholder — replace with a real product screenshot of the prediction interface before publishing.
Quick Start • ML Pipeline • Architecture • Installation • Deployment • Contact
Caution
Medical Disclaimer: CardioPredict AI is an educational and research project. It is not a certified medical device, has not been clinically validated, and must never be used as a substitute for professional medical diagnosis, advice, or treatment. Always consult a qualified healthcare provider for any medical concerns.
Click to expand full documentation index
CardioPredict AI is a full-stack machine learning platform that estimates the likelihood of heart disease from a patient's clinical parameters — age, blood pressure, cholesterol, ECG results, and related measurements — using classical supervised classification algorithms trained on the widely-used UCI Cleveland Heart Disease dataset.
The platform pairs a Flask REST API backend, serving a trained scikit-learn model, with a lightweight, responsive web interface that lets a user enter clinical values and instantly receive a predicted risk classification along with a probability score.
This repository is built as a portfolio-grade, technically rigorous reference implementation demonstrating an end-to-end applied ML workflow: data preprocessing, feature engineering, exploratory analysis, multi-model training and comparison, evaluation, and deployment — all wrapped in production-style engineering practices.
Important
This project is intended for educational and research purposes only. It has not undergone clinical trials, regulatory review, or validation against real-world patient outcomes, and must not be used for actual medical decision-making.
To demonstrate that rigorous, explainable machine learning can be applied to healthcare-adjacent problems in a way that is transparent about its assumptions, honest about its limitations, and engineered to the same standard as production software — while remaining firmly positioned as a learning and research tool rather than a clinical product.
|
|
| Challenge | Traditional Approach | CardioPredict AI Approach |
|---|---|---|
| Manually reviewing risk factors is time-consuming | Clinician cross-references guidelines by hand | Model surfaces a probability-based estimate in milliseconds |
| ML healthcare demos are often black boxes | Prediction with no reasoning shown | Explainable AI section documents feature influence transparently |
| Portfolio ML projects often stop at a notebook | Jupyter notebook, no deployment | Full REST API + responsive frontend + deployment guide |
| Model choice is rarely justified | One model, no comparison | Four algorithms evaluated side-by-side with documented rationale |
Tip
Think of CardioPredict AI as a clinical decision-support prototype, not a diagnostic tool — similar in spirit to research dashboards used to explore how classical ML performs on structured clinical data, but explicitly not certified for patient care.
Cardiovascular disease remains one of the most extensively studied conditions in clinical data science, largely due to the availability of well-structured, feature-rich public datasets such as the UCI Cleveland Heart Disease dataset. The core problem this project addresses:
Given a set of clinical measurements for a patient, can a classification model reliably distinguish between "likely presence" and "likely absence" of heart disease indicators found in the training data?
This is fundamentally a binary classification problem in supervised machine learning, and it serves as an excellent vehicle for demonstrating the full applied ML lifecycle — from raw tabular data to a deployed, queryable API.
CardioPredict AI addresses this problem through a structured, four-stage pipeline:
flowchart LR
A[Raw Clinical Dataset] --> B[Preprocessing & Cleaning]
B --> C[Feature Engineering]
C --> D[Multi-Model Training]
D --> E[Model Comparison & Selection]
E --> F[Deployed Prediction API]
F --> G[Web Interface]
style A fill:#0B1120,color:#5EEAD4
style F fill:#0B1120,color:#5EEAD4
style G fill:#134E4A,color:#5EEAD4
Rather than committing to a single algorithm upfront, the project evaluates four distinct classification approaches — Logistic Regression, Random Forest, Support Vector Machine, and K-Nearest Neighbors — and documents the reasoning behind the final model selection, mirroring how a real ML engineering team would approach model selection.
|
Structured preprocessing and feature engineering tailored to the Cleveland Heart Disease feature set. |
Four classical ML algorithms trained and evaluated side-by-side, with documented trade-offs. |
A Flask REST API serves predictions with probability scores in real time via a simple JSON contract. |
|
Confusion matrices and classification metrics are generated and documented, not just claimed. |
A clean, dependency-light HTML/CSS/JS frontend works across desktop and mobile viewports. |
Feature influence is documented and discussed, avoiding black-box "just trust the model" outputs. |
Applying machine learning to healthcare-adjacent data introduces engineering and ethical considerations beyond a typical classification task:
mindmap
root((Healthcare AI))
Data Quality
Missing values
Class imbalance
Feature reliability
Model Trust
Explainability
Uncertainty communication
Avoiding overconfidence
Ethical Use
No diagnostic claims
Clear disclaimers
Educational framing
Deployment
Reproducibility
Versioned models
Transparent metrics
CardioPredict AI is designed around these considerations explicitly — see Healthcare Considerations for the full discussion.
flowchart TD
subgraph INGEST["1️⃣ Data Ingestion"]
A[UCI Cleveland Dataset] --> B[Load into Pandas DataFrame]
end
subgraph PREP["2️⃣ Preprocessing"]
B --> C[Handle Missing Values]
C --> D[Encode Categorical Features]
D --> E[Feature Scaling / Normalization]
end
subgraph ENG["3️⃣ Feature Engineering"]
E --> F[Derive/Select Relevant Features]
F --> G[Train/Test Split]
end
subgraph TRAIN["4️⃣ Model Training"]
G --> H1[Logistic Regression]
G --> H2[Random Forest]
G --> H3[Support Vector Machine]
G --> H4[K-Nearest Neighbors]
end
subgraph EVAL["5️⃣ Evaluation"]
H1 & H2 & H3 & H4 --> I[Compare via Classification Metrics]
I --> J[Select Best-Performing Model]
end
subgraph SERVE["6️⃣ Serving"]
J --> K[Serialize Model]
K --> L[Flask Inference Endpoint]
end
style INGEST fill:#0B1120,color:#5EEAD4
style TRAIN fill:#0B1120,color:#5EEAD4
style SERVE fill:#134E4A,color:#5EEAD4
CardioPredict AI is trained on the UCI Cleveland Heart Disease dataset, one of the most widely referenced datasets in clinical machine learning research.
| Attribute | Description |
|---|---|
| Source | UCI Machine Learning Repository — Cleveland Clinic Foundation |
| Records | 303 patient records (standard Cleveland subset) |
| Target | Presence/absence of heart disease indicators |
| Type | Structured / tabular clinical data |
| License | Public research dataset — see UCI repository terms |
| Feature | Description | Type |
|---|---|---|
age |
Patient age in years | Numeric |
sex |
Biological sex (1 = male, 0 = female) | Categorical |
cp |
Chest pain type (4 categories) | Categorical |
trestbps |
Resting blood pressure (mm Hg) | Numeric |
chol |
Serum cholesterol (mg/dl) | Numeric |
fbs |
Fasting blood sugar > 120 mg/dl | Binary |
restecg |
Resting electrocardiographic results | Categorical |
thalach |
Maximum heart rate achieved | Numeric |
exang |
Exercise-induced angina | Binary |
oldpeak |
ST depression induced by exercise | Numeric |
slope |
Slope of the peak exercise ST segment | Categorical |
ca |
Number of major vessels colored by fluoroscopy | Numeric |
thal |
Thalassemia indicator | Categorical |
target |
Presence of heart disease (label) | Binary |
Note
Exact feature encodings and value ranges should be verified against the specific dataset version bundled in data/, as UCI dataset mirrors occasionally differ slightly in encoding conventions.
flowchart LR
A[Raw CSV] --> B{Missing Values?}
B -->|Yes| C[Impute or Drop]
B -->|No| D[Continue]
C --> D
D --> E[Encode Categorical Variables]
E --> F[Scale Numeric Features]
F --> G[Train/Test Split]
style A fill:#0B1120,color:#5EEAD4
style G fill:#134E4A,color:#5EEAD4
| Step | Technique | Purpose |
|---|---|---|
| Missing value handling | Imputation / row filtering | Ensures model receives complete, valid input vectors |
| Categorical encoding | One-hot / ordinal encoding | Converts non-numeric fields (cp, restecg, thal, etc.) into model-consumable form |
| Feature scaling | Standardization (z-score) | Normalizes feature magnitude for distance-based models (SVM, KNN) |
| Train/test split | Stratified split | Preserves class balance across training and evaluation sets |
Tip
Distance-based algorithms (KNN, SVM) are highly sensitive to unscaled features — a feature like chol (measured in the hundreds) can otherwise dominate distance calculations over a binary feature like sex. Scaling is applied consistently across all models for fair comparison.
| Technique | Applied To | Rationale |
|---|---|---|
| One-hot encoding | cp, restecg, slope, thal |
Prevents the model from assuming false ordinal relationships between categories |
| Binary normalization | sex, fbs, exang |
Ensures consistent 0/1 representation |
| Standard scaling | age, trestbps, chol, thalach, oldpeak |
Centers and scales continuous features to comparable ranges |
| Correlation review | All numeric features | Identifies redundant or weakly predictive features before training |
Feature engineering decisions in this project prioritize interpretability alongside predictive value — every transformation is documented so that the relationship between a raw clinical measurement and its model-ready representation stays traceable.
Exploratory Data Analysis (EDA) is performed prior to model training to understand feature distributions, class balance, and inter-feature relationships.
flowchart TD
A[Load Dataset] --> B[Summary Statistics]
B --> C[Class Balance Check]
C --> D[Feature Distribution Plots]
D --> E[Correlation Heatmap]
E --> F[Outlier Review]
F --> G[EDA Report / Notebook]
style A fill:#0B1120,color:#5EEAD4
style G fill:#134E4A,color:#5EEAD4
Typical EDA artifacts produced (see notebooks/eda.ipynb):
- Class distribution bar chart (presence vs. absence of disease indicators)
- Histograms for continuous features (
age,chol,trestbps,thalach) - Correlation heatmap across all numeric features
- Boxplots to visually inspect outliers per feature
Four classical supervised classification algorithms are trained on the identical preprocessed dataset and train/test split, ensuring a fair, apples-to-apples comparison.
flowchart LR
Data[Preprocessed Training Data] --> LR[Logistic Regression]
Data --> RF[Random Forest]
Data --> SVM[Support Vector Machine]
Data --> KNN[K-Nearest Neighbors]
LR --> Eval[Evaluation Suite]
RF --> Eval
SVM --> Eval
KNN --> Eval
style Data fill:#0B1120,color:#5EEAD4
style Eval fill:#134E4A,color:#5EEAD4
# Simplified training loop (see src/train.py for full implementation)
models = {
"logistic_regression": LogisticRegression(max_iter=1000),
"random_forest": RandomForestClassifier(n_estimators=200, random_state=42),
"svm": SVC(probability=True, kernel="rbf"),
"knn": KNeighborsClassifier(n_neighbors=7),
}
for name, model in models.items():
model.fit(X_train, y_train)
evaluate(model, X_test, y_test, name=name)| Model | Why It Was Evaluated | Key Characteristics |
|---|---|---|
| Logistic Regression | Strong, interpretable baseline for binary classification | Fast to train, coefficients are directly interpretable, assumes linear decision boundary |
| Random Forest | Captures non-linear feature interactions | Ensemble of decision trees, robust to outliers, provides feature importance scores |
| Support Vector Machine | Effective in higher-dimensional, well-scaled feature spaces | Strong margin-based separation, sensitive to feature scaling and kernel choice |
| K-Nearest Neighbors | Simple, non-parametric baseline for comparison | Distance-based, intuitive, sensitive to feature scaling and choice of k |
Note
No accuracy, precision, recall, F1, or AUC values are published in this README. Run python src/evaluate.py locally to generate real metrics for your training run — see Performance Evaluation for the reporting template.
| Criterion | Why It Matters |
|---|---|
| Interpretability | Healthcare-adjacent contexts benefit from explainable decisions |
| Robustness to feature scale | Determines preprocessing requirements |
| Training/inference speed | Impacts API response latency |
| Sensitivity to class imbalance | Affects reliability of minority-class predictions |
The final deployed model is selected based on a documented, reproducible evaluation process — not a single accuracy number in isolation.
flowchart TD
A[Train All 4 Models] --> B[Generate Confusion Matrix per Model]
B --> C[Compute Precision, Recall, F1 per Model]
C --> D[Compare Cross-Validation Stability]
D --> E{Best Balance of Metrics + Interpretability?}
E -->|Selected| F[Serialize as production model]
E -->|Not Selected| G[Retained for comparison/reference]
style F fill:#134E4A,color:#5EEAD4
style A fill:#0B1120,color:#5EEAD4
Selection criteria, in priority order:
- Balanced performance across precision and recall (not just raw accuracy)
- Stability across cross-validation folds
- Reasonable inference latency for real-time API use
- Degree of interpretability appropriate for a healthcare-adjacent context
Important
The specific model marked as "production" in models/production_model.pkl should be treated as configurable — swap it based on your own evaluation results rather than assuming any one algorithm is universally superior.
sequenceDiagram
participant U as User
participant F as Frontend (HTML/JS)
participant A as Flask API
participant M as Trained Model
U->>F: Enter clinical parameters
F->>F: Client-side validation
F->>A: POST /api/predict (JSON payload)
A->>A: Validate & preprocess input
A->>M: model.predict_proba(input)
M-->>A: Class + probability score
A-->>F: JSON response
F-->>U: Display risk classification + probability
Request lifecycle, end to end:
- User submits clinical parameters through the web form.
- Frontend performs basic client-side validation (required fields, numeric ranges).
- A
POSTrequest is sent to the Flask/api/predictendpoint as JSON. - The backend applies the same preprocessing pipeline used during training (encoding, scaling).
- The trained model produces a class prediction and an associated probability score.
- The API returns a structured JSON response, rendered by the frontend as a risk indicator.
Note
No fabricated accuracy, precision, recall, F1, or AUC values are included in this README, per project policy. The template below reflects the reporting format used by src/evaluate.py — populate it with your own generated results.
Reporting template (fill in after running your own evaluation):
| Model | Accuracy | Precision | Recall | F1-Score | AUC |
|---|---|---|---|---|---|
| Logistic Regression | <run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
| Random Forest | <run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
| Support Vector Machine | <run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
| K-Nearest Neighbors | <run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
<run evaluate.py> |
# Generate the populated metrics table locally
python src/evaluate.py --model all --output reports/metrics.mdA confusion matrix is generated per model during evaluation, visualizing true positives, true negatives, false positives, and false negatives.
flowchart LR
subgraph CM["Confusion Matrix Structure"]
direction TB
A["True Positive (TP)<br/>Correctly predicted disease present"]
B["False Negative (FN)<br/>Missed disease case"]
C["False Positive (FP)<br/>Incorrectly flagged as at-risk"]
D["True Negative (TN)<br/>Correctly predicted no disease"]
end
style A fill:#134E4A,color:#5EEAD4
style D fill:#134E4A,color:#5EEAD4
style B fill:#7F1D1D,color:#fff
style C fill:#78350F,color:#fff
Caution
In a healthcare-adjacent context, false negatives (missed at-risk cases) and false positives (unnecessary alarm) carry very different real-world costs. Model selection should explicitly weigh this trade-off rather than optimizing for accuracy alone — see Healthcare Considerations.
| Metric | Formula | What It Tells You |
|---|---|---|
| Accuracy | (TP + TN) / (TP + TN + FP + FN) |
Overall correctness — can be misleading with class imbalance |
| Precision | TP / (TP + FP) |
Of predicted "at-risk" cases, how many were correct |
| Recall (Sensitivity) | TP / (TP + FN) |
Of actual at-risk cases, how many were correctly identified |
| F1-Score | 2 · (Precision · Recall) / (Precision + Recall) |
Harmonic balance between precision and recall |
| AUC-ROC | Area under the ROC curve | Model's ability to distinguish classes across thresholds |
Tip
For a screening-style healthcare use case, recall is often prioritized over raw accuracy, since missing an at-risk patient (false negative) is typically more costly than a false alarm that prompts further clinical review.
CardioPredict AI treats explainability as a first-class requirement, not an afterthought — critical in any healthcare-adjacent ML system.
flowchart TD
A[Trained Model] --> B{Model Type}
B -->|Logistic Regression| C[Coefficient Magnitude & Sign]
B -->|Random Forest| D[Feature Importance Scores]
B -->|SVM / KNN| E[Permutation Importance]
C --> F[Human-Readable Feature Influence Report]
D --> F
E --> F
style A fill:#0B1120,color:#5EEAD4
style F fill:#134E4A,color:#5EEAD4
| Technique | Applicable Models | What It Reveals |
|---|---|---|
| Coefficient inspection | Logistic Regression | Direction and relative strength of each feature's influence |
| Feature importance | Random Forest | Which features most reduce impurity across the ensemble |
| Permutation importance | SVM, KNN | How much performance drops when a feature is shuffled |
Note
Explainability outputs describe statistical influence within the trained model, not causal clinical relationships. They should be interpreted as model-behavior diagnostics, not medical insight.
graph TB
subgraph CLIENT["Client Layer"]
UI[Responsive Web UI<br/>HTML / CSS / JS]
end
subgraph API["API Layer — Flask"]
Router[REST Router]
Validator[Input Validator]
Preproc[Preprocessing Pipeline]
end
subgraph ML["ML Layer"]
Model[Serialized Model<br/>.pkl]
Explain[Explainability Module]
end
subgraph DATA["Data Layer"]
Dataset[(UCI Cleveland Dataset)]
Artifacts[(Trained Model Artifacts)]
end
UI -->|POST /api/predict| Router
Router --> Validator
Validator --> Preproc
Preproc --> Model
Model --> Explain
Model -->|Prediction + Probability| Router
Router -->|JSON Response| UI
Dataset -.->|training time| Artifacts
Artifacts -.-> Model
style CLIENT fill:#0B1120,color:#5EEAD4
style API fill:#1E293B,color:#5EEAD4
style ML fill:#134E4A,color:#5EEAD4
style DATA fill:#0B1120,color:#5EEAD4
CardioPredict-AI/
├── backend/
│ ├── app.py # Flask application entry point
│ ├── routes/
│ │ └── predict.py # /api/predict route handler
│ ├── ml/
│ │ ├── preprocess.py # Preprocessing pipeline (shared train/infer)
│ │ ├── train.py # Model training script
│ │ ├── evaluate.py # Evaluation & metrics generation
│ │ └── explain.py # Explainability utilities
│ ├── models/
│ │ └── production_model.pkl # Serialized selected model
│ └── requirements.txt
├── frontend/
│ ├── index.html # Prediction form UI
│ ├── css/
│ │ └── styles.css
│ └── js/
│ └── app.js # Fetch logic, form handling
├── data/
│ └── cleveland_heart_disease.csv
├── notebooks/
│ ├── eda.ipynb # Exploratory data analysis
│ └── model_comparison.ipynb # Model training & comparison
├── reports/
│ └── metrics.md # Generated evaluation report
├── docs/
│ └── assets/ # Diagrams, screenshots (placeholders)
├── .env.example
├── .gitignore
├── requirements.txt
├── LICENSE
└── README.md
graph TD
Root[CardioPredict-AI/] --> BE[backend/]
Root --> FE[frontend/]
Root --> Data[data/]
Root --> NB[notebooks/]
BE --> ML[ml/]
ML --> Preprocess[preprocess.py]
ML --> Train[train.py]
ML --> Evaluate[evaluate.py]
ML --> Explain[explain.py]
BE --> Models[models/]
FE --> Index[index.html]
FE --> JS[js/app.js]
style Root fill:#0B1120,color:#5EEAD4
| Module | File | Responsibility |
|---|---|---|
| Preprocessing Pipeline | backend/ml/preprocess.py |
Shared encoding/scaling logic used identically at train and inference time |
| Training Script | backend/ml/train.py |
Trains all four models and serializes artifacts |
| Evaluation Script | backend/ml/evaluate.py |
Generates confusion matrices and classification metrics |
| Explainability Module | backend/ml/explain.py |
Produces feature importance / coefficient reports |
| Prediction Route | backend/routes/predict.py |
Validates input and returns model predictions via REST |
| Flask App | backend/app.py |
Application bootstrap, route registration, CORS config |
| Frontend UI | frontend/index.html, frontend/js/app.js |
Patient input form and API integration |
flowchart TD
A[Incoming POST /api/predict] --> B[Validate JSON Schema]
B -->|Invalid| C[Return 400 Bad Request]
B -->|Valid| D[Apply Preprocessing Pipeline]
D --> E[Load Serialized Model]
E --> F[Run Inference]
F --> G[Format JSON Response]
G --> H[Return 200 OK]
style A fill:#0B1120,color:#5EEAD4
style H fill:#134E4A,color:#5EEAD4
style C fill:#7F1D1D,color:#fff
# backend/routes/predict.py (simplified)
from flask import Blueprint, request, jsonify
from backend.ml.preprocess import preprocess_input
from backend.ml.model_loader import load_model
predict_bp = Blueprint("predict", __name__)
model = load_model("models/production_model.pkl")
@predict_bp.route("/api/predict", methods=["POST"])
def predict():
payload = request.get_json()
features = preprocess_input(payload)
prediction = model.predict(features)[0]
probability = model.predict_proba(features)[0][1]
return jsonify({
"prediction": int(prediction),
"risk_label": "At Risk" if prediction == 1 else "Low Risk",
"probability": round(float(probability), 4)
})The frontend is a dependency-light, responsive interface built with vanilla HTML/CSS/JS — deliberately avoiding a heavy framework to keep the project approachable and fast-loading.
| Component | Description |
|---|---|
| Patient Input Form | Structured form covering all model input features |
| Client-Side Validation | Range and required-field checks before submission |
| Result Panel | Displays risk classification and probability score |
| Responsive Layout | CSS Grid/Flexbox layout adapting to mobile and desktop |
// frontend/js/app.js (simplified)
async function submitPrediction(formData) {
const response = await fetch("/api/predict", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
});
const result = await response.json();
renderResult(result);
}# 1. Clone the repository
git clone https://github.com/your-username/cardiopredict-ai.git
# 2. Move into the project directory
cd cardiopredict-ai
# 3. Create a virtual environment
python -m venv venv
# 4. Activate the virtual environment
# macOS / Linux:
source venv/bin/activate
# Windows:
venv\Scripts\activate
# 5. Install backend dependencies
pip install -r backend/requirements.txt| Requirement | Minimum Version |
|---|---|
| Python | 3.10 or later |
| pip | 23.x or later |
| Node (optional, for frontend tooling) | 18.x or later |
| OS | macOS, Linux, Windows (WSL recommended) |
# 1. Train the models (generates production_model.pkl)
python backend/ml/train.py
# 2. Evaluate all trained models
python backend/ml/evaluate.py
# 3. Run the Flask API
python backend/app.py
# 4. Open the frontend
# Navigate to frontend/index.html in your browser,
# or serve it via a simple static server:
python -m http.server 5500 --directory frontendExample Prediction Request:
POST /api/predict
Content-Type: application/json
{
"age": 58,
"sex": 1,
"cp": 2,
"trestbps": 130,
"chol": 246,
"fbs": 0,
"restecg": 1,
"thalach": 152,
"exang": 0,
"oldpeak": 1.2,
"slope": 1,
"ca": 0,
"thal": 2
}Example Response:
{
"prediction": 1,
"risk_label": "At Risk",
"probability": 0.7842
}# .env.example
FLASK_ENV=development
FLASK_APP=backend/app.py
FLASK_PORT=5000
MODEL_PATH=backend/models/production_model.pkl
CORS_ORIGIN=http://localhost:5500| Variable | Description | Required |
|---|---|---|
FLASK_ENV |
development or production |
✅ |
FLASK_APP |
Entry point for the Flask CLI | ✅ |
FLASK_PORT |
Port the API listens on | ❌ (defaults to 5000) |
MODEL_PATH |
Path to the serialized production model | ✅ |
CORS_ORIGIN |
Allowed origin for frontend requests | ✅ |
# Run the Flask dev server with auto-reload
export FLASK_ENV=development
flask run
# Run backend unit tests
pytest backend/tests/
# Re-generate EDA plots
jupyter nbconvert --to notebook --execute notebooks/eda.ipynb
# Lint Python code
flake8 backend/flowchart LR
A[Push to main branch] --> B[CI: Run Tests]
B --> C{Tests Pass?}
C -->|No| D[Block Deployment]
C -->|Yes| E[Deploy Backend to Render]
C -->|Yes| F[Deploy Frontend to Vercel]
E --> G[Live API Endpoint]
F --> H[Live Web Interface]
H -->|API calls| G
style A fill:#0B1120,color:#5EEAD4
style G fill:#134E4A,color:#5EEAD4
style H fill:#134E4A,color:#5EEAD4
style D fill:#7F1D1D,color:#fff
| Step | Platform | Notes |
|---|---|---|
| 1 | Render | Deploy backend/ as a Python web service; set environment variables from .env.example |
| 2 | Render | Configure build command: pip install -r backend/requirements.txt |
| 3 | Render | Configure start command: gunicorn backend.app:app |
| 4 | Vercel | Deploy frontend/ as a static site |
| 5 | Vercel | Set CORS_ORIGIN on the backend to match the deployed frontend URL |
# Example Render start command
gunicorn backend.app:app --bind 0.0.0.0:$PORTPlaceholder — add a real screenshot of the patient input form.
Placeholder — add a real screenshot of the prediction result panel.
| Decision | Rationale |
|---|---|
| Shared preprocessing module for train & inference | Guarantees train/serve consistency, avoiding train-serve skew |
| Multi-model comparison instead of a single algorithm | Mirrors real ML engineering practice and documents trade-offs honestly |
| Flask over a heavier framework | Minimal overhead for a focused, single-purpose inference API |
| Vanilla JS frontend | Keeps the demo lightweight and framework-independent |
Model serialized via pickle/joblib |
Simple, standard scikit-learn deployment pattern |
| Explicit metrics reporting template (no hardcoded numbers) | Prevents misleading claims; encourages reproducible evaluation |
CardioPredict AI's interface follows a calm, clinical, low-noise visual language — consistent with enterprise healthcare software rather than a flashy consumer app:
- Restrained color palette (deep navy, teal accents) evoking trust and clarity
- Generous whitespace around clinical input fields to reduce cognitive load
- Clear visual separation between input, prediction result, and disclaimers
- Accessibility-conscious contrast for readability across devices
Important
CardioPredict AI is built around the principle that an ML system's outputs are only as trustworthy as its transparency about uncertainty and limitations.
This project's approach to applied AI:
- No black boxes — every model's decision logic is at least partially explainable (see Explainable AI).
- No inflated claims — performance metrics are generated, not asserted; placeholders are used until real numbers exist.
- Probability, not certainty — outputs are framed as probability estimates, never as definitive diagnoses.
- Reproducibility first — the same input, model, and preprocessing pipeline will always produce the same output.
Caution
This section exists because applying ML to health-adjacent data carries responsibilities beyond typical software engineering.
| Consideration | How This Project Addresses It |
|---|---|
| Risk of misuse as a diagnostic tool | Prominent disclaimers throughout the README and UI |
| False negative cost | Documented explicitly in Classification Metrics as a priority concern |
| Dataset representativeness | UCI Cleveland dataset is a research dataset, not representative of a full modern patient population |
| Data privacy | No real patient data is collected, stored, or transmitted by this application |
| Bias awareness | Dataset demographic skew is not corrected for — flagged under Known Limitations |
| Regulatory status | This project makes no claim of FDA, CE, or any other regulatory clearance |
This project should never be used to:
- Make or influence an actual medical diagnosis
- Replace consultation with a licensed healthcare professional
- Inform real treatment or lifestyle decisions without professional medical guidance
| Optimization | Applied Where | Benefit |
|---|---|---|
| Model pre-loaded at app startup | backend/app.py |
Avoids reloading the model on every request |
| Lightweight JSON payloads | API contract | Minimizes request/response latency |
| Stateless Flask routes | backend/routes/predict.py |
Enables horizontal scaling without session affinity |
| Vanilla JS frontend (no framework overhead) | frontend/ |
Faster page load, smaller bundle size |
| Vectorized preprocessing (NumPy/Pandas) | backend/ml/preprocess.py |
Efficient batch-capable transformations |
| Concern | Current Status | Recommendation |
|---|---|---|
| Input validation | Basic schema validation on /api/predict |
Extend with strict type/range enforcement before production use |
| CORS configuration | Restricted via CORS_ORIGIN environment variable |
Lock down to exact deployed frontend origin |
| Patient data handling | No persistent storage of submitted data | Confirm compliance requirements (e.g., HIPAA) before handling real data |
| Dependency management | Pinned versions in requirements.txt |
Run pip-audit regularly for vulnerability scanning |
| Rate limiting | Not implemented | Add rate limiting (e.g., Flask-Limiter) before public deployment |
| Authentication | Not implemented (open demo endpoint) | Add API key or OAuth layer for any non-demo deployment |
Warning
This project does not implement healthcare-grade data protection (e.g., HIPAA-compliant storage/transmission). Do not submit real patient-identifiable data to any deployment of this demo.
| Feature | Status | Priority |
|---|---|---|
| SHAP-based explainability visualizations | Planned | High |
| Model versioning & experiment tracking (e.g., MLflow) | Planned | High |
| Dockerized deployment | Planned | Medium |
| Expanded dataset beyond UCI Cleveland subset | Under Consideration | Medium |
| Automated CI/CD pipeline with test gating | Planned | Medium |
| User authentication for saved prediction history | Under Consideration | Low |
| Mobile-native companion app | Under Consideration | Low |
timeline
title CardioPredict AI Roadmap
v1.0 : Core ML pipeline
: Flask REST API
: Responsive web UI
v1.1 : SHAP-based explainability
: MLflow experiment tracking
v1.2 : Dockerized deployment
: CI/CD pipeline
v2.0 : Expanded dataset support
: User authentication & history
- Trained on a relatively small, research-oriented dataset (303 records) — not representative of a broader modern patient population.
- No correction applied for demographic imbalance within the source dataset.
- No SHAP/LIME-based per-prediction explanations yet (feature importance is model-level, not prediction-level).
- No persistent storage, audit logging, or authentication layer.
- Not validated against real-world clinical outcomes or reviewed by medical professionals.
- Not tested for robustness against adversarial or malformed input beyond basic schema validation.
- Maintaining a single shared preprocessing function between training and inference eliminated an entire class of subtle bugs caused by train/serve skew.
- Comparing multiple models side-by-side — rather than committing early to one algorithm — surfaced meaningful trade-offs between interpretability and raw predictive capability.
- Writing the Healthcare Considerations section early in development, rather than as an afterthought, shaped several downstream engineering decisions (e.g., no persistent data storage).
- Keeping the frontend framework-free simplified deployment significantly and kept the project approachable for readers focused on the ML/backend engineering.
Contributions are welcome — bug fixes, new evaluation metrics, additional models, documentation improvements, and UI enhancements are all appreciated.
flowchart LR
A[Fork Repository] --> B[Create Feature Branch]
B --> C[Implement Change]
C --> D[Add/Update Tests]
D --> E[Run pytest]
E --> F{All Tests Pass?}
F -->|No| C
F -->|Yes| G[Open Pull Request]
G --> H[Code Review]
H --> I[Merge]
style A fill:#0B1120,color:#5EEAD4
style I fill:#134E4A,color:#5EEAD4
# 1. Fork and clone your fork
git clone https://github.com/your-username/cardiopredict-ai.git
# 2. Create a feature branch
git checkout -b feature/your-feature-name
# 3. Make your changes, then run the test suite
pytest backend/tests/
# 4. Commit using a clear, descriptive message
git commit -m "feat: add SHAP-based per-prediction explanations"
# 5. Push and open a pull request
git push origin feature/your-feature-name| Contribution Type | Guidelines |
|---|---|
| Bug fixes | Include a regression test that fails before your fix and passes after |
| New models/features | Open an issue first to discuss scope before submitting a large PR |
| Documentation | Keep tone and disclaimers consistent with the rest of this README |
| ML pipeline changes | Clearly document any change to preprocessing, training, or evaluation logic |
Important
Any change to backend/ml/preprocess.py, backend/ml/train.py, or the production model artifact should include updated evaluation metrics generated via evaluate.py, and must preserve the project's disclaimer language.
This project is licensed under the MIT License.
MIT License
Copyright (c) 2025 [Your Name]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
See the LICENSE file for the full text.
Caution
This license covers the software, not medical advice. Use of this software does not constitute, and is not a substitute for, professional medical judgment.
- UCI Machine Learning Repository & Cleveland Clinic Foundation — for maintaining and publishing the Heart Disease dataset used in this project.
- The broader open-source data science community — scikit-learn, pandas, NumPy, and Matplotlib maintainers, whose tools made this project possible.
- Public healthcare AI research and documentation practices from organizations such as Google Health and DeepMind, which informed this project's emphasis on explainability and responsible framing.
CardioPredict AI — AI-Powered Heart Disease Risk Prediction Platform
Built with scikit-learn, Flask, and a strong commitment to responsible, explainable applied machine learning. This is an educational and research project — not a certified medical device and not a substitute for professional medical diagnosis or advice.
⭐ If this project helped you understand applied healthcare ML, consider starring the repository. ⭐