Heart Disease Risk Predictor

Train an ML model and serve predictions through an interactive Streamlit web app.

Introduction

30 Second Summary

Heart disease is the leading cause of death worldwide. Doctors assess risk using patient data like cholesterol, blood pressure, and heart rate. What if you could train a computer to spot patterns in that data and predict risk instantly?

In this project, you will build a machine learning web app that predicts heart disease risk from real patient health data. You'll train a classifier on medical records and serve predictions through an interactive browser interface that anyone can use.

What You'll Build

When you run your finished app, a browser opens with a medical form where you enter patient information, click "Predict Risk," and instantly see a color-coded risk assessment with a probability percentage and a chart showing which health factors matter most.

By the end of this project, you'll have:

  • Enter patient health data through a web form and receive an instant risk prediction with a probability percentage, powered by a trained Random Forest model whose accuracy score is visible in the sidebar.
  • See a color-coded risk level (Low, Moderate, or High) that makes the model's output meaningful to anyone, served through a polished Streamlit app that requires zero code knowledge to use.
  • View a feature importance bar chart that reveals exactly which health factors drove each prediction.
  • Secret Mission: Compare multiple ML algorithms side-by-side and display which one performs best for this dataset.

Are there any prerequisites?

You should be comfortable with basic Python (variables, functions, and loops). You should also know how to install packages using pip. No prior machine learning or web development experience is needed.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters. A trained ML model is powerful on its own, but it only becomes useful to non-developers when it's wrapped in an interface anyone can interact with.

Load Data and Train Your First Model

Your environment is ready and your dataset is waiting. Now it is time to find out if a machine learning model can actually learn useful patterns from your health data.

Before building any UI, you need to confirm the dataset loads correctly and that a model can learn from it. This step gives you a baseline accuracy number to validate against later.

In this step, get ready to:
  • Load the heart disease dataset and inspect its structure.
  • Train a Random Forest classifier and measure its accuracy.
  • Test a single prediction and observe raw model output.
Create train.py and load the dataset

The first thing any data science project does is load and inspect the data. You need to confirm the CSV reads correctly and see what columns you are working with.

  • In IntelliJ IDEA, right-click your heart-predictor folder in the Project panel and select New then File.
  • Name the file train.py and press Enter.
  • Add the following code to import your libraries and load the dataset:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# Load dataset
df = pd.read_csv("heart.csv")
print(f"Dataset shape: {df.shape}")
print(f"Columns: {list(df.columns)}")
print(df.head())

What does this code do?

The imports bring in pandas for data handling and three scikit-learn tools: one to split data, one for the model, and one to measure accuracy.

The pd.read_csv() call loads your heart disease CSV into a DataFrame. The three print statements show you how many rows and columns you have, what those columns are called, and what the first few rows look like.

  • Save train.py.
  • Run the script to confirm your data loads by entering this command in the IntelliJ terminal:
python train.py

You should see the dataset shape (something like (303, 14)), a list of column names, and a table showing the first five rows of patient data.

Seeing a FileNotFoundError?

This means Python cannot find heart.csv in the current directory. Make sure the CSV file is saved directly inside your heart-predictor folder, not in a subfolder.

Also check that the terminal is pointed at your project folder. You can confirm with ls (macOS/Linux) or dir (Windows) to see if heart.csv appears in the listing.

Still stuck? Help me debug my FileNotFoundError when loading heart.csv

Split data and train a Random Forest model

Now that you can see the data, it is time to teach a model to recognize patterns in it. A Random Forest works by building many decision trees and combining their votes into a single prediction.

  • In train.py, add the following code below print(df.head()):
# Separate features and target
X = df.drop("target", axis=1)
y = df["target"]

# Split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Train Random Forest
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# Evaluate
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nModel Accuracy: {accuracy:.2%}")

What does this code do?

  • X holds all the health measurements (features) and y holds the answer column (does this patient have heart disease or not).
  • train_test_split holds back 20% of the data for testing. The model never sees these rows during training, so the accuracy score is an honest measure of how well it generalizes.
  • RandomForestClassifier(n_estimators=100) builds 100 decision trees. Each tree sees a random subset of the data, and their combined vote becomes the final prediction.
  • accuracy_score compares the model's guesses to the real answers and gives you a percentage of correct predictions.

Why random_state=42?

Setting random_state=42 makes the random splits and tree construction reproducible. Every time you run the script you get the same accuracy number, which makes debugging easier. The value 42 is arbitrary.

  • Save train.py and run it again:
python train.py

Below the dataset info, you should now see a line showing your model's accuracy. For heart disease data with a Random Forest, this is typically 80-90%.

Seeing a KeyError for 'target'?

Your CSV might use a different name for the target column (like condition or num). Check the column names printed in the first run and update df.drop("target", axis=1) and df["target"] to match your dataset's actual column name.

Need help? Help me fix a KeyError when splitting my heart disease dataset

Test a sample prediction

You know the model is accurate overall. Now see what a single prediction actually looks like when it comes out of the model.

  • In train.py, add the following code below the print(f"\nModel Accuracy: {accuracy:.2%}") line:
# Test a single prediction
sample = X_test.iloc[[0]]
prediction = model.predict(sample)[0]
probability = model.predict_proba(sample)[0]
print(f"\nSample prediction: {prediction}")
print(f"Probability array: {probability}")
print("Notice: these raw numbers mean nothing without context!")

What does this code do?

  • X_test.iloc[[0]] grabs one patient from the test set as a sample input.
  • model.predict() returns a hard 0 or 1 (no disease / has disease).
  • model.predict_proba() returns an array of two probabilities: [chance of no disease, chance of disease]. The model is more nuanced than a simple yes/no.
  • Save train.py.

Before you run this, think about what a non-developer user would understand if they saw the model's raw output. Would they know what [0.73, 0.27] means for their health?

  • Run the script one more time:
python train.py

At the bottom of the output, you see something like Sample prediction: 1 and Probability array: [0.27 0.73]. These numbers are technically correct but completely unusable. A user seeing this in a terminal has no idea what it means for their health.

Why does this matter?

This is the gap you will close over the next two steps. A trained model is useless if nobody can understand its output. You need a visual interface that translates [0.27, 0.73] into something like "73% risk of heart disease" with color-coded severity and a chart showing which factors drove the prediction.

Script not printing anything new?

Make sure the new code is below the accuracy print statement, not inside an indented block. All lines should be at the top level of the file (no indentation).

Need help? Help me figure out why my sample prediction code isn't printing output

✔️ Awesome, I've got everything!

Great. Double check you have saved train.py and you can move on.

ⓧ I'd like to double check the full code

Scroll up through your file and confirm these sections appear in order:

  • Imports (pandas, train_test_split, RandomForestClassifier, accuracy_score).
  • Load dataset section with pd.read_csv("heart.csv") and three print statements for shape, columns, and head.
  • Feature/target separation with df.drop("target", axis=1) and df["target"].
  • Train/test split with test_size=0.2 and random_state=42.
  • Model training with RandomForestClassifier(n_estimators=100, random_state=42).
  • Evaluation section printing accuracy.
  • Sample prediction section printing prediction, probability array, and the "raw numbers mean nothing" message.

Your model works and you have proof. Next up, you will build a visual interface so that a real user can enter their own health data and get a prediction they can actually understand.

Build the Prediction Interface

Your trained model can predict heart disease risk, but the only way to use it is by running a Python script and reading raw numbers in the terminal. That is not something you could hand to a doctor or a patient.

In this step, you will build a web interface using Streamlit where a user can enter patient health data and receive a prediction. You will deliberately wire up only the bare prediction output first to feel how unhelpful a raw "1" or "0" is without context.

In this step, get ready to:
  • Create app.py with cached data loading and model training.
  • Build a two-column input form with sliders, dropdowns, and number inputs for patient data.
  • Wire up a prediction button that displays the raw model output.
Create app.py with page config and data loading

Streamlit apps are regular Python scripts that Streamlit re-runs from top to bottom every time the user interacts with a widget. You need a stable foundation: page configuration, cached data loading, and a cached model so the app does not retrain on every click.

  • Create a new file called app.py in your heart-predictor folder.
  • Add the imports and page configuration by pasting this code:
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# Page configuration
st.set_page_config(
    page_title="Heart Disease Risk Predictor",
    layout="centered"
)

What does this code do?

The imports bring in Streamlit for the web UI, pandas for data handling, numpy for array manipulation, and scikit-learn for model training.

st.set_page_config sets the browser tab title and centers the page layout. This must be the first Streamlit command in the file.

  • Below the page config, add the cached data and model functions by pasting this code:
# Load data
@st.cache_data
def load_data():
    df = pd.read_csv("heart.csv")
    return df

# Train model
@st.cache_resource
def train_model(_df):
    X = _df.drop("target", axis=1)
    y = _df["target"]
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    model = RandomForestClassifier(n_estimators=100, random_state=42)
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    acc = accuracy_score(y_test, y_pred)
    return model, acc, X.columns.tolist()

# Load and train
df = load_data()
model, accuracy, feature_names = train_model(df)

# Main content
st.title("Heart Disease Risk Predictor")
st.write("Enter patient information below to predict heart disease risk.")

What does this code do?

  • @st.cache_data caches the DataFrame so Streamlit does not reload the CSV on every interaction.
  • @st.cache_resource caches the trained model in memory. The underscore prefix on _df tells Streamlit to skip hashing that parameter, since DataFrames can be expensive to hash.
  • The function returns three values: the trained model, its accuracy score, and the list of feature column names.
  • st.title and st.write render the page heading and description text.
  • Save app.py.
  • Launch the app by running this command in your terminal:
streamlit run app.py
  • Your browser opens to localhost:8501. You should see the title "Heart Disease Risk Predictor" and a single line of description text.

Don't see the title?

  • Make sure heart.csv is in the same folder as app.py. If the file is missing, the app crashes on data load.
  • Confirm your virtual environment is still active (you should see (venv) in your terminal prompt).
  • help me debug my Streamlit app not loading
Build the input form with widgets

The form needs to collect 13 health features that match the columns in your dataset. You will split them across two columns so the page does not scroll endlessly.

  • In app.py, add the first column of input widgets below the st.write line:
# Input form
st.header("Patient Information")
col1, col2 = st.columns(2)

with col1:
    age = st.number_input("Age", min_value=1, max_value=120, value=50)
    sex = st.selectbox("Sex", options=[0, 1], format_func=lambda x: "Female" if x == 0 else "Male")
    cp = st.selectbox(
        "Chest Pain Type",
        options=[0, 1, 2, 3],
        format_func=lambda x: ["Typical Angina", "Atypical Angina", "Non-anginal Pain", "Asymptomatic"][x]
    )
    trestbps = st.number_input("Resting Blood Pressure (mm Hg)", min_value=80, max_value=250, value=120)
    chol = st.number_input("Serum Cholesterol (mg/dl)", min_value=100, max_value=600, value=200)
    fbs = st.selectbox(
        "Fasting Blood Sugar > 120 mg/dl",
        options=[0, 1],
        format_func=lambda x: "No" if x == 0 else "Yes"
    )
    restecg = st.selectbox(
        "Resting ECG Results",
        options=[0, 1, 2],
        format_func=lambda x: ["Normal", "ST-T Abnormality", "Left Ventricular Hypertrophy"][x]
    )

What does this code do?

  • st.columns(2) splits the page into two side-by-side columns.
  • st.number_input creates a numeric field with min/max bounds and a default value.
  • st.selectbox creates a dropdown. The format_func parameter converts raw integers (what the model expects) into readable labels (what the user sees).
  • Directly below the with col1: block, add the second column of widgets:
with col2:
    thalach = st.number_input("Max Heart Rate Achieved", min_value=60, max_value=250, value=150)
    exang = st.selectbox(
        "Exercise Induced Angina",
        options=[0, 1],
        format_func=lambda x: "No" if x == 0 else "Yes"
    )
    oldpeak = st.number_input("ST Depression (Oldpeak)", min_value=0.0, max_value=10.0, value=1.0, step=0.1)
    slope = st.selectbox(
        "Slope of Peak Exercise ST",
        options=[0, 1, 2],
        format_func=lambda x: ["Upsloping", "Flat", "Downsloping"][x]
    )
    ca = st.selectbox("Number of Major Vessels (0-3)", options=[0, 1, 2, 3])
    thal = st.selectbox(
        "Thalassemia",
        options=[0, 1, 2, 3],
        format_func=lambda x: ["Normal", "Fixed Defect", "Reversible Defect", "Unknown"][x]
    )

What does this code do?

The second column captures exercise and cardiovascular measurements. Each widget stores the user's selection in a variable (thalach, exang, etc.) that you will pass to the model later.

The step=0.1 on oldpeak allows decimal precision, since ST depression is measured in tenths.

  • Save app.py and switch to your browser.
  • The app auto-refreshes. You should now see a "Patient Information" header with two columns of form fields: age, sex, chest pain type, blood pressure, cholesterol, fasting blood sugar, and ECG on the left. Max heart rate, exercise angina, ST depression, slope, vessels, and thalassemia on the right.

Form fields not showing up?

  • Check that the with col1: and with col2: blocks are properly indented. All widgets inside a column must be indented under its with statement.
  • If you see a "DuplicateWidgetID" error, make sure each widget has a unique label string.
  • help me fix my Streamlit form layout
Wire up the prediction (bare output)

Now you will connect the form inputs to the trained model. For now, you will display only the raw prediction number to experience exactly what makes it inadequate.

  • Below the with col2: block, add the prediction button by pasting this code:
# Prediction
if st.button("Predict Risk", type="primary"):
    input_data = np.array([[age, sex, cp, trestbps, chol, fbs, restecg,
                            thalach, exang, oldpeak, slope, ca, thal]])
    prediction = model.predict(input_data)[0]
    st.write(f"Prediction: {prediction}")

What does this code do?

  • st.button creates a clickable button. The code inside the if block only runs when the user clicks it.
  • np.array packs all 13 widget values into a 2D array shaped for the model's predict() method.
  • st.write renders the raw integer prediction (0 or 1) to the page.
  • Save app.py and switch to your browser.

Before you click the button, think about this: what will a user understand when they see "Prediction: 1" on a health app?

  • Leave the default form values and click Predict Risk.

You see "Prediction: 1" (or "Prediction: 0") appear below the button. That is the entire output.

This is the problem. A user has no idea whether 1 means danger or safety, how confident the model is, or what factors drove the result.

Why is this output a problem?

A bare 0 or 1 is worse than no answer for a health prediction. Users need three things: how confident the model is (probability), what risk level that maps to (interpretation), and which health factors matter most (explanation).

In the next step, you will replace this bare output with probability percentages, color-coded risk levels, and a feature importance chart.

✔️ Awesome, I've got everything!

Great. Double check you have saved app.py and the app is running without errors at localhost:8501.

ⓧ I'd like to double check the full code

Your app.py should contain these sections in order. Scroll up and confirm each is present:

  • Imports (streamlit, pandas, numpy, sklearn modules).
  • Page configuration with st.set_page_config.
  • Cached load_data() function with @st.cache_data.
  • Cached train_model(_df) function with @st.cache_resource, returning model, accuracy, and feature names.
  • Load and train calls: df = load_data() and model, accuracy, feature_names = train_model(df).
  • Title and write lines.
  • Input form with col1 (7 widgets) and col2 (6 widgets).
  • Prediction button that calls model.predict() and displays the raw integer with st.write.

Your prediction interface is live, but the output is practically useless. Next up, you will transform that bare number into a color-coded risk assessment with probability percentages, risk bands, and a chart showing which health factors drive each prediction.

Add Risk Interpretation and Visualization

In the last step, you saw the problem firsthand. Clicking "Predict Risk" shows Prediction: 1 or Prediction: 0. A patient looking at that screen learns nothing about their actual health risk.

A useful health prediction needs three things: HOW confident the model is (a percentage), WHAT risk level that maps to (Low, Moderate, or High), and WHICH factors are driving the prediction (a chart). This step transforms that bare number into all three.

In this step, get ready to:
  • Replace the raw 0/1 output with a color-coded probability message.
  • Add risk band labels and a feature importance bar chart.
  • Display model accuracy and dataset info in the sidebar.
Replace bare output with probability-based risk display

Instead of showing a meaningless integer, you will use the model's predict_proba() method to get the actual confidence level. Then you will display it as a color-coded message that anyone can understand at a glance.

  • In app.py, scroll to the bottom of the file and find the # Prediction section.
  • Find these lines:
# Prediction
if st.button("Predict Risk", type="primary"):
    input_data = np.array([[age, sex, cp, trestbps, chol, fbs, restecg,
                            thalach, exang, oldpeak, slope, ca, thal]])
    prediction = model.predict(input_data)[0]
    st.write(f"Prediction: {prediction}")
  • Delete that entire block and replace it with the following code:
# Prediction
if st.button("Predict Risk", type="primary"):
    input_data = np.array([[age, sex, cp, trestbps, chol, fbs, restecg,
                            thalach, exang, oldpeak, slope, ca, thal]])

    prediction = model.predict(input_data)[0]
    probability = model.predict_proba(input_data)[0]

    st.divider()
    st.header("Prediction Results")

    # Convert probability to a percentage
    risk_percentage = probability[1] * 100

    # Show color-coded message based on prediction
    if prediction == 1:
        st.error(f"High Risk of Heart Disease ({risk_percentage:.1f}% probability)")
    else:
        st.success(f"Low Risk of Heart Disease ({risk_percentage:.1f}% probability)")

What does this code do?

predict_proba() returns an array with two values: the probability of class 0 (no disease) and class 1 (disease). You grab probability[1] to get the heart disease probability, then multiply by 100 for a human-readable percentage.

st.error() renders a red banner and st.success() renders a green one. The user instantly sees whether the result is concerning or reassuring.

  • Save app.py.
  • Switch back to your browser showing the Streamlit app. The app auto-reloads on save.
  • Fill in the form and click Predict Risk. You should now see either a red or green banner with a probability percentage instead of a bare number.

Still seeing the old output?

Make sure you deleted the original st.write(f"Prediction: {prediction}") line. If both the old and new output appear, that old line is still in your file.

If you see a Python error, check that the indentation of probability = model.predict_proba(input_data)[0] matches the prediction line above it (both should be indented one level inside the if block).

Help me debug my Streamlit prediction display

Add a risk level classification and feature importance chart

A percentage alone still requires interpretation. Classifying it into Low, Moderate, or High gives the user an instant category. And showing which health factors matter most helps them understand WHY the model made its decision.

  • In app.py, find the st.success line you just added. Add the following code directly below it, still inside the if st.button block:
    # Risk level indicator
    st.subheader("Risk Level")
    st.progress(risk_percentage / 100)

    if risk_percentage < 30:
        st.write("Risk Level: LOW")
    elif risk_percentage < 60:
        st.write("Risk Level: MODERATE")
    else:
        st.write("Risk Level: HIGH")

    # Feature importance
    st.subheader("Key Risk Factors")
    importance = model.feature_importances_
    importance_df = pd.DataFrame({
        "Feature": feature_names,
        "Importance": importance
    }).sort_values("Importance", ascending=False).head(5)

    st.bar_chart(importance_df.set_index("Feature"))

    st.caption("This tool is for educational purposes only. Always consult a medical professional.")

What does this code do?

st.progress() accepts a float between 0.0 and 1.0. Dividing the percentage by 100 gives the correct range for the progress bar.

The risk bands classify the probability into three buckets: under 30% is LOW, 30-60% is MODERATE, and over 60% is HIGH. These thresholds are educational simplifications.

feature_importances_ is a Random Forest attribute that scores how much each feature contributed to the model's decisions. Sorting and taking the top 5 shows the user which health factors matter most.

  • Save app.py and switch back to your browser.
  • Click Predict Risk again. Below the color-coded message, you should now see a progress bar, a risk level label (LOW, MODERATE, or HIGH), and a bar chart showing the top 5 health factors by importance.

Chart not appearing?

Check that all lines from st.subheader("Risk Level") through st.caption(...) are indented with 4 spaces (one level inside the if st.button block). If any line is at the wrong indentation, Streamlit either skips it or throws an error.

If you see IndentationError, make sure you did not accidentally mix tabs and spaces. Use spaces only.

Help me fix my feature importance chart

Add model performance to the sidebar

Users should know how reliable this model is before trusting its predictions. Adding the accuracy score and training details to the sidebar gives that context without cluttering the main form.

  • In app.py, scroll up and find this line:
model, accuracy, feature_names = train_model(df)
  • Directly below that line, and above the # Main content comment, add the following sidebar code:
# Sidebar - model info
st.sidebar.header("Model Performance")
st.sidebar.metric("Accuracy", f"{accuracy:.1%}")
st.sidebar.write(f"Trained on {len(df)} patient records")
st.sidebar.write("Algorithm: Random Forest (100 trees)")

What does this code do?

st.sidebar places content in a collapsible panel on the left side of the app. st.sidebar.metric() renders a large, prominent number that stands out visually. The accuracy percentage and training details give users confidence in the model's predictions.

  • Save app.py.
  • Switch back to your browser. You should see a sidebar on the left showing the model's accuracy score, the number of patient records it trained on, and the algorithm name.

Sidebar not showing?

On narrow browser windows, the sidebar may be collapsed by default. Look for a small arrow or hamburger icon in the top-left corner of the app and click it to expand the sidebar.

If you see an error, confirm the sidebar code sits between the model, accuracy, feature_names = train_model(df) line and the # Main content comment. It should not be inside any function or indented block.

Help me debug my Streamlit sidebar

Before you run your final check, what do you expect to see when you click Predict Risk with the default form values? Will the result be high risk or low risk?

  • Run your app by entering this command in the terminal:
streamlit run app.py

Enter patient values in the form and click Predict Risk. You should see a color-coded risk message with a percentage, a progress bar showing the risk level, a LOW/MODERATE/HIGH label, a bar chart of the top contributing health factors, and a sidebar with the model's accuracy score.

✔️ Awesome, I've got everything!

Great. Double check you have saved app.py and that both the sidebar and the full prediction results panel are working.

ⓧ I'd like to double check the full code

Your app.py is now too long to display in a single block. Scroll through your file and confirm these sections are present in this order:

  • Imports (streamlit, pandas, numpy, sklearn modules).
  • Page configuration with st.set_page_config.
  • load_data() function with @st.cache_data.
  • train_model() function with @st.cache_resource.
  • df = load_data() and model, accuracy, feature_names = train_model(df).
  • Sidebar block with st.sidebar.header, st.sidebar.metric, and two st.sidebar.write calls.
  • Main content title and input form with two columns.
  • Prediction button block containing: predict_proba, risk_percentage, color-coded st.error/st.success, progress bar, risk level label, feature importance chart, and disclaimer caption.

Your app now delivers a complete health insight instead of a meaningless number. Next up, you will take on a Secret Mission to compare multiple ML algorithms and find the best performer for this dataset.

Secret mission

Compare Multiple Algorithms

Right now your app uses a single Random Forest model. But how do you know it is the best choice for this dataset? In this secret mission, you will train multiple ML algorithms side-by-side, display a comparison table, and let users choose which model powers the predictions.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally, so there are no ongoing costs.

Resources you used:

  • The heart-predictor project folder on your local machine (contains app.py, train.py, heart.csv).
  • A Python virtual environment (venv folder) inside heart-predictor with scikit-learn, Streamlit, pandas, and numpy installed.
  • A Streamlit app process running locally (if you haven't stopped it yet).

Keep everything running

No action needed. Choose this if you're still actively building or want to experiment with the app further.

  • Your heart-predictor folder stays on your machine. Costs nothing.
  • Run streamlit run app.py anytime to restart the app.
  • The virtual environment and all installed packages remain available.

Pause - I'll come back to this later

Shut down the running Streamlit process to free up memory. Your files and virtual environment stay intact for later.

  • If your Streamlit app is still running, press Ctrl+C in the terminal to stop it.
  • Deactivate your virtual environment by running:
deactivate

When you come back, reactivate the virtual environment and restart the app:

venv\Scripts\activate
streamlit run app.py

Delete - I don't want to use this again

Remove all project files and start fresh. Since everything runs locally, there is nothing else to clean up.

  • If your Streamlit app is still running, press Ctrl+C in the terminal to stop it.
  • Deactivate your virtual environment by running:
deactivate
  • Navigate out of the project folder and delete it. On macOS/Linux:
cd ~/Desktop
rm -rf heart-predictor
  • On Windows:
cd ~\Desktop
rmdir /s /q heart-predictor

This removes the virtual environment, all installed packages, your code files, and the dataset. Nothing else on your system is affected.

That's a Wrap!

That's a Wrap!

Nice work! You just built a fully interactive Heart Disease Risk Predictor that loads real health data, trains a machine learning model, and serves predictions through a polished web interface.

You've learned how to:

  • Trained a Random Forest classifier on real-world heart disease data using scikit-learn and measured its accuracy with an 80/20 train-test split.
  • Built a complete interactive web app with Streamlit that collects patient data through form widgets and displays color-coded risk assessments with probability percentages and risk bands.
  • Visualized feature importance as a bar chart so users understand which health factors drive each prediction.
  • Secret Mission: Compared multiple ML algorithms side-by-side and let users choose which trained model powers the prediction form.

Ready to quiz yourself?