Predicting Heart Attacks with Python: A Comprehensive Guide to Classification Algorithms

Heart disease is the leading cause of death worldwide, and heart attacks are one of its most severe manifestations. Early prediction of heart attacks can save lives by enabling timely interventions and lifestyle changes. In this article, we‘ll explore how to use classification algorithms in Python to predict the likelihood of heart attacks based on patient data.

We‘ll be working with a dataset from Kaggle containing various clinical and demographic features for patients, along with a binary label indicating whether they suffered a heart attack. Throughout this guide, we‘ll walk through the entire machine learning workflow, from data preprocessing to model evaluation, and share best practices and insights along the way.

Data Cleaning and Preprocessing

Before diving into modeling, it‘s crucial to ensure the quality and integrity of our data. Real-world datasets often contain missing values, outliers, and inconsistencies that can hinder the performance of machine learning algorithms. Let‘s start by loading our dataset and examining its structure:

import pandas as pd

data = pd.read_csv(‘heart_attack_data.csv‘)
print(data.head())
print(data.info())

Output:

   age  sex  cp  trestbps  chol  fbs  restecg  thalach  exang  oldpeak  slope  ca  thal  target
0   63    1   3       145   233    1        0      150      0      2.3      0   0     1       1
1   37    1   2       130   250    0        1      187      0      3.5      0   0     2       1
2   41    0   1       130   204    0        0      172      0      1.4      2   0     2       1
3   56    1   1       120   236    0        1      178      0      0.8      2   0     2       1
4   57    0   0       120   354    0        1      163      1      0.6      2   0     2       1

<class ‘pandas.core.frame.DataFrame‘>
RangeIndex: 303 entries, 0 to 302
Data columns (total 14 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       303 non-null    int64  
 1   sex       303 non-null    int64  
 2   cp        303 non-null    int64  
 3   trestbps  303 non-null    int64  
 4   chol      303 non-null    int64  
 5   fbs       303 non-null    int64  
 6   restecg   303 non-null    int64  
 7   thalach   303 non-null    int64  
 8   exang     303 non-null    int64  
 9   oldpeak   303 non-null    float64
 10  slope     303 non-null    int64  
 11  ca        303 non-null    int64  
 12  thal      303 non-null    int64  
 13  target    303 non-null    int64  
dtypes: float64(1), int64(13)
memory usage: 33.3 KB

Luckily, our dataset doesn‘t have any missing values. However, let‘s check for duplicate rows and remove them if present:

print(f"Duplicate rows: {data.duplicated().sum()}")
data.drop_duplicates(inplace=True)

Next, we‘ll handle outliers using the interquartile range (IQR) method. For each feature, we‘ll define the lower and upper bounds as Q1 – 1.5 IQR and Q3 + 1.5 IQR, respectively, and remove data points falling outside this range.

Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1

data = data[~((data < (Q1 - 1.5 * IQR)) | (data > (Q3 + 1.5 * IQR))).any(axis=1)]

Feature Selection and Correlation Analysis

Now that our data is clean, let‘s explore the relationships between features and the target variable. We‘ll compute the Pearson and Spearman correlation coefficients and visualize them using heatmaps.

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(12, 10))
corr_matrix = data.corr()

mask = np.triu(np.ones_like(corr_matrix, dtype=bool))
cmap = sns.diverging_palette(230, 20, as_cmap=True)

sns.heatmap(corr_matrix, mask=mask, cmap=cmap, vmax=.3, center=0, annot=True, 
            square=True, linewidths=.5, cbar_kws={"shrink": .5})

plt.title(‘Pearson Correlation Matrix‘)
plt.show()

Pearson Correlation Heatmap

plt.figure(figsize=(12, 10))
corr_matrix = data.corr(method=‘spearman‘)

sns.heatmap(corr_matrix, mask=mask, cmap=cmap, vmax=.3, center=0, annot=True,
            square=True, linewidths=.5, cbar_kws={"shrink": .5})

plt.title(‘Spearman Correlation Matrix‘) 
plt.show()

Spearman Correlation Heatmap

The heatmaps reveal that features like cp (chest pain type), thalach (maximum heart rate achieved), and oldpeak (ST depression induced by exercise relative to rest) have a stronger correlation with the target variable. We can consider dropping weakly correlated features like fbs (fasting blood sugar) and chol (serum cholesterol) to reduce dimensionality and potentially improve model performance.

Training Classification Models

With our data preprocessed and features selected, it‘s time to train some classification models! We‘ll start by splitting our data into training and testing sets:

from sklearn.model_selection import train_test_split

X = data.drop(‘target‘, axis=1)
y = data[‘target‘]

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

Now, let‘s implement and evaluate several popular classification algorithms:

Logistic Regression

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

lr = LogisticRegression()
lr.fit(X_train, y_train)

y_pred = lr.predict(X_test)

print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}") 
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1 Score: {f1_score(y_test, y_pred):.3f}")

Decision Trees

from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(max_depth=5, random_state=42)
dt.fit(X_train, y_train)

y_pred = dt.predict(X_test)

print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}") 
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1 Score: {f1_score(y_test, y_pred):.3f}")

Random Forest

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf.fit(X_train, y_train)

y_pred = rf.predict(X_test)

print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")  
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall: {recall_score(y_test, y_pred):.3f}") 
print(f"F1 Score: {f1_score(y_test, y_pred):.3f}")

K-Nearest Neighbors

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)

y_pred = knn.predict(X_test)

print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}") 
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1 Score: {f1_score(y_test, y_pred):.3f}")  

We can continue implementing other algorithms like Support Vector Machines, Naive Bayes, XGBoost, and Neural Networks in a similar fashion.

Model Comparison and Hyperparameter Tuning

After training multiple models, we can compare their performance metrics to identify the best-performing ones. We can visualize the results using a bar chart:

models = [‘Logistic Regression‘, ‘Decision Tree‘, ‘Random Forest‘, ‘KNN‘]
accuracies = [0.85, 0.79, 0.87, 0.82]

plt.figure(figsize=(10, 6))
plt.bar(models, accuracies)
plt.title(‘Model Accuracy Comparison‘)
plt.xlabel(‘Model‘)
plt.ylabel(‘Accuracy‘)
plt.ylim(0, 1)
plt.show()

Model Accuracy Comparison

To further improve the performance of our top models, we can perform hyperparameter tuning using techniques like grid search or random search with cross-validation.

from sklearn.model_selection import GridSearchCV

param_grid = {
    ‘n_estimators‘: [50, 100, 200],
    ‘max_depth‘: [3, 5, 7],
    ‘min_samples_split‘: [2, 5, 10],
    ‘min_samples_leaf‘: [1, 2, 4]
}

rf_tuned = GridSearchCV(RandomForestClassifier(random_state=42), param_grid, cv=5, scoring=‘accuracy‘)
rf_tuned.fit(X_train, y_train)

print(f"Best parameters: {rf_tuned.best_params_}")
print(f"Best accuracy: {rf_tuned.best_score_:.3f}")

Feature Importance

Understanding the relative importance of features can provide valuable insights into the factors contributing to heart attack risk. We can visualize feature importance using a horizontal bar chart:

importances = rf_tuned.best_estimator_.feature_importances_
indices = np.argsort(importances)[::-1]

plt.figure(figsize=(10, 6))
plt.title("Feature Importance")
plt.barh(range(X.shape[1]), importances[indices])
plt.yticks(range(X.shape[1]), X.columns[indices]) 
plt.xlabel("Relative Importance")
plt.show()

Feature Importance

Considerations and Real-World Applications

When selecting a classification algorithm for heart attack prediction, it‘s essential to consider factors such as interpretability, training time, and the ability to handle high-dimensional data. In a healthcare setting, interpretability is crucial for understanding the reasoning behind predictions and making informed decisions.

Logistic Regression and Decision Trees offer good interpretability, while ensemble methods like Random Forest can provide higher accuracy at the cost of some interpretability. Neural Networks, on the other hand, can handle complex non-linear relationships but are often considered "black boxes."

Real-world applications of heart attack prediction models include:

  1. Risk assessment and stratification: Identifying high-risk patients for targeted interventions and follow-up care.
  2. Personalized treatment planning: Tailoring treatment strategies based on individual risk factors.
  3. Resource allocation: Optimizing healthcare resources by prioritizing patients with higher predicted risk.
  4. Early warning systems: Integrating prediction models into electronic health records for real-time alerts.

Conclusion

In this comprehensive guide, we explored the use of classification algorithms in Python for heart attack prediction. We covered data preprocessing, feature selection, model training, evaluation, and hyperparameter tuning. We also discussed the importance of interpretability and potential real-world applications.

By leveraging machine learning techniques, healthcare professionals can make data-driven decisions and improve patient outcomes. However, it‘s crucial to remember that these models are intended to assist and augment human expertise, not replace it entirely.

For those interested in further learning, consider exploring advanced techniques like ensemble methods, deep learning, and model interpretability frameworks like SHAP or LIME.

Additional Resources

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts