# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: 'Python 3.9.4 64-bit (''python39'': conda)'
#     name: python3
# ---

# # Diagnosing Coronary Artery Disease 
#

# **Data Set Information:**
#
# This dataset contains 76 attributes, but all published experiments refer to using a subset of 14 of them. In particular, the Cleveland database is the only one that has been used by ML researchers to this date. The "goal" field refers to the presence of heart disease in the patient. It is integer valued from 0 (no presence) to 4. Experiments with the Cleveland database have concentrated on simply attempting to distinguish presence (values 1,2,3,4) from absence (value 0).
#
# The names and social security numbers of the patients were recently removed from the database, replaced with dummy values.
#
# One file has been "processed", that one containing the Cleveland database. All four unprocessed files also exist in this directory.

# **Attribute Information:**
#
# Only 14 attributes used:
# 1. #3 (age)
# 2. #4 (sex)
# 3. #9 (cp)
# 4. #10 (trestbps)
# 5. #12 (chol)
# 6. #16 (fbs)
# 7. #19 (restecg)
# 8. #32 (thalach)
# 9. #38 (exang)
# 10. #40 (oldpeak)
# 11. #41 (slope)
# 12. #44 (ca)
# 13. #51 (thal)
# 14. #58 (num) (the predicted attribute)

# ## Import Libraries

# +
import sys

# Data Science Tools
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pandas.plotting import scatter_matrix

# Machine Learning Tools
import sklearn
from sklearn import model_selection
from sklearn.metrics import classification_report, accuracy_score

# Deep Learning Tools
import keras
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras.layers import Dense
from tensorflow.keras.optimizers import Adam

# -

# ## Loading data

# +
# Import the heart disease dataset
url = "http://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data"

# the names will be the names of each column in our pandas DataFrame
names = ["age", "sex", "cp", "trestbps", "chol", "fbs", "restecg", "thalach", "exang", "oldpeeak", "slope", "ca", "thal", "class"]
# -

# read the csv
cleveland_data = pd.read_csv(url, names = names)

cleveland_data.head()

# +
# print the shape of the Dataframe, so we can see how many examples we have

print("Shape of Dataframe: {}".format(cleveland_data.shape))
print(cleveland_data.loc[1])
# -

# print the lsat twenty or so data points
cleveland_data.loc[280:]

# ## Data Preparation

# remove missing data (indicated with a "?")
data = cleveland_data[~cleveland_data.isin(['?'])]
data.loc[280:]

# drop rows with NaN values from DataFrame
data = data.dropna(axis=0)
data.loc[280:]

# print the shape and data type of the dataframe
print(data.shape)
print(data.dtypes)

# transform data to numeric to enable further analysis
data = data.apply(pd.to_numeric)
data.dtypes

# print data characteristics, usings pandas built-in describe() function
data.describe()


# plot histogram for each variables
data.hist(figsize=(12, 12))
plt.show()

# ## Data Splitting (Train / Test)
#
# Now that we have preprocessed the data appropriately, we can split it into training and testings datasets. We will use Sklearn's train_test_split() function to generate a training dataset (80 percent of the total data) and testing dataset (20 percent of the total data). 
#
# Furthermore, the class values in this dataset contain multiple types of heart disease with values ranging from 0 (healthy) to 4 (severe heart disease). Consequently, we will need to convert our class data to categorical labels. For example, the label 2 will become [0, 0, 1, 0, 0].

# +
# create X and y datasets for training

X = np.array(data.drop(["class"],1))
y = np.array(data["class"])

X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.2)

# +
# convert the data to categorical labels

Y_train = to_categorical(y_train, num_classes=None)
Y_test = to_categorical(y_test, num_classes = None)
print(Y_train.shape)
print(Y_train[:10])


# -

# ## Modelling

# +
# define a function to build the keras model
def create_model():
    # create model
    model = Sequential()
    model.add(Dense(8, input_dim = 13, kernel_initializer = "normal", activation= "relu"))
    model.add(Dense(4, kernel_initializer= "normal", activation = "relu"))
    model.add(Dense(5, activation = "softmax"))

    # compile model
    adam = Adam(learning_rate = 0.001)
    model.compile(optimizer = adam, loss = "categorical_crossentropy", metrics = ["accuracy"])
    return model

model = create_model()

print(model.summary())
# -

# fit the model to the training data
model.fit(X_train, Y_train, epochs=100, batch_size=10, verbose=1)

# +
# convert into binary classification problem  - heart disease or no heart disease
Y_train_binary = y_train.copy()
Y_test_binary = y_test.copy()

Y_train_binary[Y_train_binary > 0] = 1
Y_test_binary[Y_test_binary > 0] = 1

print(Y_train_binary[:20])


# +
# define a new keras model for binary classification
def create_binary_model():
    # create model
    model = Sequential()
    model.add(Dense(8, input_dim=13, kernel_initializer='normal', activation='relu'))
    model.add(Dense(4, kernel_initializer='normal', activation='relu'))
    model.add(Dense(1, activation='sigmoid'))

    # Compile model
    adam = Adam(lr=0.001)
    model.compile(loss='binary_crossentropy',
                  optimizer=adam, metrics=['accuracy'])
    return model


binary_model = create_binary_model()

print(binary_model.summary())

# -

# fit the binary model on the training data
binary_model.fit(X_train, Y_train_binary, epochs=100, batch_size=10, verbose=1)


# +
# generate classification report using predictions for categorical model

categorical_pred = np.argmax(model.predict(X_test), axis=1)

print('Results for Categorical Model')
print(accuracy_score(y_test, categorical_pred))
print(classification_report(y_test, categorical_pred))


# +
# generate classification report using predictions for binary model
binary_pred = np.round(binary_model.predict(X_test)).astype(int)

print('Results for Binary Model')
print(accuracy_score(Y_test_binary, binary_pred))
print(classification_report(Y_test_binary, binary_pred))


StarcoderdataJupyterScriptsDedupFiltered