HealthLens
Multi-model clinical prediction platform for doctors and clinicians.
Year
2025
Status
GitHub — deployment in progress
Stack
Python · FastAPI · Random Forest · TensorFlow · Next.js · PostgreSQL · Docker
Problem
Clinical decision support tools are either inaccessible to junior clinicians or so opaque that senior ones don't trust them. Readmission risk, X-ray interpretation, and sepsis detection are addressed by separate siloed systems — where they exist at all. The gap isn't models. It's a system a clinician can actually use and interpret.
Why it matters
30-day readmissions cost the US healthcare system over $26B annually. The CMS Hospital Readmissions Reduction Program penalises hospitals for excess readmissions, making risk prediction operationally valuable beyond clinical outcomes. On the imaging side, in resource-constrained settings radiologist availability is often the bottleneck. A screening tool that catches 97.4% of pneumonia cases reduces that bottleneck directly.
Approach
Started as a college mini project. The coursework required ML model implementations. What the actual engineering demanded was a full-stack system: a FastAPI backend with lazy model loading, a Next.js frontend split into two completely separate modes — clinical and research — SHAP explainability at the API level, clinical override rules derived from published HRRP literature, and a PostgreSQL audit trail persisting every prediction with outcome tracking. The central design decision was the dual-mode frontend split. Clinical and research modes share the same backend but surface completely different views. A doctor sees a risk level and a plain-English recommendation. A researcher sees raw probabilities, SHAP waterfall charts, and training curves. The backend always returns full technical output. The frontend applies the appropriate translation layer. Clinical communication and statistical communication are different languages.
Architecture
FastAPI backend with lazy model loading — models load on first inference request to avoid memory crashes under constrained compute. Four model types: Random Forest for 30-day readmission prediction with SHAP TreeExplainer (primary model), ResNet-based CNN for chest X-ray classification, LSTM for vitals time-series forecasting and sepsis risk stratification, Autoencoder for X-ray denoising. PostgreSQL audit trail via SQLAlchemy + Alembic — every prediction row persisted with outcome fields for clinician recording. Full Docker Compose stack.
Model Performance
CNN — chest X-ray: AUC 0.963, F1 0.908, Recall 0.974. The recall figure leads: missing a sick patient is the worst outcome. Random Forest — 30-day readmission: AUC 0.679. Honest performance on a hard problem. Dataset has 89/11 class split. Published research on the same dataset reports AUC 0.65–0.72. Accuracy (88%) is not used as the headline metric — misleading on imbalanced data. LSTM — vitals forecasting: Normalised MAE 0.036, test MSE 0.0023. Sepsis detection AUC: 0.525 — documented as a current limitation requiring retraining with better class imbalance handling. ANN: F1 0.26 — disqualified due to feature mismatch (trained on 3,256 features vs the 109-feature contract used everywhere else). Documented as a lesson in establishing feature contracts before training.
System flow
Patient data input→Preprocessing (VarianceThreshold → StandardScaler)→Random Forest inference → SHAP top risk factors→Clinical mode: risk level + plain-English recommendation→Research mode: raw probability + SHAP waterfall→Prediction persisted to PostgreSQL audit trail→Outcome recording available for follow-up
Tradeoffs
Lazy model loading makes the first inference request slow — acceptable for a dashboard, unacceptable for real-time alerting. The dual-mode frontend adds significant component complexity. The 89/11 class imbalance is a hard constraint that SMOTE and class-weighted training partially address — the sepsis result demonstrates this problem isn't fully solved.
Learnings
The ANN feature mismatch was the most expensive lesson: establish feature contracts before training, not after. The dual-mode split taught me that decisions about how to communicate model outputs are as architecturally significant as decisions about which model to use. A model that produces correct outputs but communicates them in the wrong language for its audience is not a working product.