Back to work
2025·Healthcare · ML DiagnosticsBETA

INTELLIHEALTHCARE

A structured second opinion, powered by machine learning.

A Final Year Project built with two teammates and a faculty supervisor: a healthcare web app that analyzes patient-reported symptoms with a trained Decision Tree classifier and separately screens clinical report values for heart disease risk with a Random Forest model — giving a fast, structured second opinion in regions where specialists are scarce.

INTELLIHEALTHCARE — live site screenshot
Duration
Academic year 2024–2025
Team
3-person student team + faculty supervisor
My role
ML pipeline, backend & full front-end
Client context

Numbers about the client's business — useful context, not my engineering output.

Conditions covered
15
Tracked symptoms
49
Detection modules
2
Avg. response time
<2s
My engineering output

Numbers I produced — measurable, attributable to the work I did.

Symptom classifier accuracy
83%
Decision Tree, stratified 80/20 test split
Heart-risk model accuracy
80%
Random Forest, stratified 80/20 test split
Hosting cost / month
$0 (Vercel free tier)
Stats page numbers
Computed live, not hardcoded
The story

From brief to production system.

Challenge

Accurate, timely diagnosis is a real bottleneck in under-resourced healthcare settings — doctors handling high patient volumes make more errors, and many areas simply lack access to specialists. No existing tool combined a plain-language, doctor-usable interface with a transparent, urgency-ranked machine learning verdict.

Solution

Built as a Flask web app with two independent ML modules behind a shared UI: a Decision Tree classifier trained on a 49-symptom, 15-disease dataset for the Symptom Tracker, and a Random Forest classifier trained on 13 clinical inputs (blood pressure, cholesterol, ECG results, etc.) for the Heart Disease Detector. Every prediction returns with an urgency label — emergency, see a doctor, or self-care — so the next step is never ambiguous.

Outcome

Live at intellihealthcare.vercel.app. The symptom classifier holds ~83% accuracy and the heart-risk model ~80%, both computed on a held-out test split and displayed live on the site's own stats page rather than hardcoded.

Real constraints

The boundaries that shaped the build.

Honest tradeoffs

What I chose, and what I gave up.

Decision

Custom-built symptom/heart-risk datasets instead of a public Kaggle dataset

What we gave up

A larger, pre-vetted sample size. Won a dataset whose symptom-disease relationships we could design and verify against the report's exact disease list — at the cost of clinical validity, which is why the site is explicit that this is diagnostic assistance, not a certified medical tool.

Decision

Decision Tree / Random Forest instead of a neural network

What we gave up

The heavier 'deep learning' pitch. Won a model that's interpretable and fast enough for sub-2-second predictions on free-tier serverless hosting — the right trade for a structured, tabular symptom dataset at this scale.

Process · Academic year 2024–2025

How it shipped, week by week.

Phase 1
01 / 5

Domain research

Requirements analysis, use cases, and stakeholder mapping for a symptom-analysis tool aimed at resource-limited healthcare settings.

Phase 2
02 / 5

Data + models

Built the symptom/heart-risk datasets and trained the Decision Tree and Random Forest classifiers.

Phase 3
03 / 5

Web app

Flask backend, prediction endpoints, and the full front-end — Symptom Tracker, Heart Detector, stats page, AI assistant.

Phase 4
04 / 5

Testing

Decision-table test cases across multiple symptom combinations, verifying predicted vs. expected disease.

Phase 5
05 / 5

Deploy + polish

Shipped to Vercel, then a full visual pass — typography system, animated background, scroll reveals.

Inside the system

What it does. How it's built.

Features

  • Symptom Tracker — searchable 49-symptom picker across 15 supported conditions
  • Heart Disease Detector — 13 clinical inputs (BP, cholesterol, ECG, etc.) scored by a Random Forest model
  • Urgency-labeled results (emergency / see a doctor / self-care) on every prediction
  • Lightweight AI health assistant with an optional live Gemini API connection
  • Live model-accuracy stats page — not a fixed number

Architecture

  • 01Flask backend serving both the UI (Jinja templates) and JSON prediction endpoints
  • 02Two independently trained scikit-learn models pickled and loaded once at boot
  • 03Vanilla JS frontend — no framework, kept deliberately light for a serverless deploy
  • 04Deployed on Vercel's Python runtime, GitHub-connected for auto-redeploy on push
Stack
PythonFlaskscikit-learnpandasNumPyHTMLCSSJavaScriptVercel
From the codebase

Annotated excerpts.

01 · The symptom-prediction endpoint: builds a feature vector from the selected symptoms, runs it through the pickled Decision Tree, and returns an urgency-labeled verdict.
app.pypython
@app.route("/predict-symptoms", methods=["POST"])
def predict_symptoms():
    payload = request.get_json(silent=True) or {}
    selected = set(payload.get("symptoms", []))

    if not selected:
        return jsonify({"error": "Please select at least one symptom."}), 400

    input_vector = pd.DataFrame(
        [[1 if s in selected else 0 for s in SYMPTOMS]], columns=SYMPTOMS
    )
    prediction = DISEASE_MODEL.predict(input_vector)[0]

    confidence = None
    if hasattr(DISEASE_MODEL, "predict_proba"):
        proba = DISEASE_MODEL.predict_proba(input_vector)[0]
        confidence = round(float(max(proba)) * 100, 1)

    description, advice, urgency = DISEASE_INFO.get(
        prediction, ("", "Please consult a healthcare professional.", "see-doctor")
    )

    return jsonify({
        "disease": prediction,
        "description": description,
        "advice": advice,
        "urgency": urgency,
        "confidence": confidence,
    })
02 · Training script: stratified 80/20 split so accuracy is measured on unseen data, not the training set — the number shown on the stats page comes straight from this run.
train_disease_model.pypython
def main():
    df = pd.read_csv(DATA_PATH)
    symptoms = list(df.columns[1:])
    diseases = sorted(df["Disease"].unique())

    X = df[symptoms]
    y = df["Disease"]

    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42, stratify=y
    )

    model = DecisionTreeClassifier(max_depth=12, random_state=42)
    model.fit(X_train, y_train)

    accuracy = accuracy_score(y_test, model.predict(X_test))

    with open(MODEL_PATH, "wb") as f:
        pickle.dump({
            "model": model,
            "symptoms": symptoms,
            "diseases": diseases,
            "accuracy": accuracy,
        }, f)

Have a project like this in mind? Let's talk.

Send me a brief and I'll respond within 24 hours.

← Home© 2025 Ali RazzaqContact →