<jupyter_start><jupyter_text><jupyter_code>#We have a data which classified if patients have heart disease or not according to features in it. 
#We will try to use this data to create a model which tries predict if a patient has this disease or not.
#We will use Random Forest (classification) algorithm.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier


#model evaluation
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.model_selection import RandomizedSearchCV, GridSearchCV
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.metrics import precision_score, recall_score, f1_score
from sklearn.metrics import plot_roc_curve



df=pd.read_csv("/content/heart.csv")
df.head()
df.target.value_counts()
df.isnull().sum()
df.describe()
df.info()
sns.countplot(x="target", data=df, palette="bwr")
plt.show()
countNoDisease = len(df[df.target == 0])
countHaveDisease = len(df[df.target == 1])
print("Percentage of Patients Haven't Heart Disease: {:.2f}%".format((countNoDisease / (len(df.target))*100)))
print("Percentage of Patients Have Heart Disease: {:.2f}%".format((countHaveDisease / (len(df.target))*100)))
sns.countplot(x='sex', data=df, palette="mako_r")
plt.xlabel("Sex (0 = female, 1= male)")
plt.show()
countFemale = len(df[df.sex == 0])
countMale = len(df[df.sex == 1])
print("Percentage of Female Patients: {:.2f}%".format((countFemale / (len(df.sex))*100)))
print("Percentage of Male Patients: {:.2f}%".format((countMale / (len(df.sex))*100)))
df.groupby('target').mean()
pd.crosstab(df.age,df.target).plot(kind="bar",figsize=(20,6))
plt.title('Heart Disease Frequency for Ages')
plt.xlabel('Age')
plt.ylabel('Frequency')
plt.savefig('heartDiseaseAndAges.png')
plt.show()
pd.crosstab(df.sex,df.target).plot(kind="bar",figsize=(15,6),color=['#1CA53B','#AA1111' ])
plt.title('Heart Disease Frequency for Sex')
plt.xlabel('Sex (0 = Female, 1 = Male)')
plt.xticks(rotation=0)
plt.legend(["Haven't Disease", "Have Disease"])
plt.ylabel('Frequency')
plt.show()
#Lest compare age, thalach(Max heart rate) and target
plt.figure(figsize=(10,6))

#scatter with positive examples
plt.scatter(df.age[df.target==1],
           df.thalach[df.target==1],
           c="salmon");

#scatter with negative example

plt.scatter(df.age[df.target==0],
           df.thalach[df.target==0],
           c="black");

plt.title("Heart Disease in function of age and thalach")
plt.xlabel("Age")
plt.ylabel("Thalache (max heart rate)")
plt.legend(["Disease","No Disease"]);
# check the dstribution of the age column with a histogram

df.age.plot.hist(figsize=(10,6));

pd.crosstab( df.cp,df.target)
#make thr cross tab visual

pd.crosstab(df.cp, df.target).plot(kind="bar", figsize=(10,6),
                                  color=["darkblue","lightblue"])

plt.title("Heart Disease frequency per chest pain type")
plt.xlabel("Chest Pain type")
plt.ylabel("Amount")
plt.legend(["No Disease","Disease"])
plt.xticks(rotation=0);
df.corr()
# Lets make our corelation matrix a bit prettier

corr_matrix= df.corr()
fig, ax= plt.subplots(figsize=(10,6))
ax= sns.heatmap(corr_matrix,
               annot= True,
               linewidths=0.5,
               fmt=".2f",
            cmap="twilight_r");
X=df.drop("target", axis=1)
y=df["target"]
#split data into training and test split
np.random.seed(42)

#Split into trin and test set

X_train, X_test, y_train,y_test= train_test_split(X,y,test_size=0.2)
len(X_train), len(y_train)
# Put models in a dictionary

models={"Logistic Regression": LogisticRegression(),
       "KNN":KNeighborsClassifier(),
       "Random Forest": RandomForestClassifier()}

#create a function to fit and score models
def fit_and_score(models,X_train, X_test, y_train, y_test):
    """
    Fits and evaluates given ML models.
    models: a dict of diff SciKit learn ML models
    X_test :  test set (no label)
    X_train: training set (no label)
    y_train : training labels
    y_test : test labels
    """
    
    #set random seed
    np.random.seed(42)
    #Make dictionary to keep model scores
    
    model_scores={}
    
    #Loop through models
    for name, model in models.items():
        #fit model to data
        model.fit(X_train, y_train)
        #evaluate the model and store in score dict
        model_scores[name]= model.score(X_test, y_test)
    return model_scores
model_scores= fit_and_score(models=models,
                           X_train=X_train,
                           X_test=X_test,
                           y_train=y_train,
                           y_test=y_test)

model_scores
model_compare =pd.DataFrame(model_scores, index=["accuracy"])
model_compare.T.plot.bar();
#lets tune KNN
train_scores = []
test_scores =  []

#Create a list of diff values of n_neighbours
neighbors = range(1,21)

#Setup KNN Instance
knn = KNeighborsClassifier()

#Loop thriugh diff n_neighbours
for i in neighbors:
    knn.set_params(n_neighbors = i)
    
    #Fit the algo
    knn.fit(X_train, y_train)
    
    #Update the training scores list
    train_scores.append(knn.score(X_train, y_train))
    
    #Update the test scores
    test_scores.append(knn.score(X_test, y_test))
    
train_scores
test_scores
#Visualize

plt.plot(neighbors, train_scores, label="Train score")
plt.plot(neighbors, test_scores, label="Test score")
plt.xticks(np.arange(1,21,1))
plt.xlabel("Number of neighbors")
plt.ylabel("Model score")
plt.legend()

print(f"Maximum KNN score on the test data :{max(test_scores)*100:.2f}%")
#  Create a hyperparameter grid for LogisticRegression
log_reg_grid = {"C" : np.logspace(-4, 4, 20),
            "solver": ["liblinear"]}

#Create a hyperparam grid for RandomForestClassifier
rf_grid = {"n_estimators" : np.arange(10, 1000, 50),
         "max_depth" : [None,3,5,10],
         "min_samples_split" : np.arange(2, 20, 2),
         "min_samples_leaf": np.arange(1, 20, 2)}

# Tune LogisticRegression

np.random.seed(42)

#Setup random hyperparams search for LogisticRegression

rs_log_reg= RandomizedSearchCV(LogisticRegression(),
                              param_distributions = log_reg_grid,
                              cv=5,
                              n_iter=20,
                              verbose=True)

#Fit random hyperparam search model for LogisticRegression
rs_log_reg.fit(X_train, y_train)
rs_log_reg.best_params_
rs_log_reg.score(X_test, y_test)
np.random.seed(42)

#Setup random hyperparam search for RandomFOrestClassifier
rs_ref = RandomizedSearchCV(RandomForestClassifier(),
                          param_distributions = rf_grid,
                          cv=5,
                          n_iter= 20,
                          verbose=True)
# Fit random hyperparam search model for RandomForestCLassifier

rs_ref.fit(X_train, y_train)
#Finding best params
rs_ref.best_params_
#Evaluate RandomSearchCV search on RandomForestClassifier model
rs_ref.score(X_test, y_test)
# Different hyperparameters for LR Model
log_reg_grid = {"C": np.logspace(-4,4,30),
               "solver": ["liblinear"]}

#Setup grid hyperparameter search for LogisticRegression
gs_log_reg = GridSearchCV(LogisticRegression(),
                         param_grid= log_reg_grid,
                         cv=5,
                         verbose=True)
#Fit grid hyperparam search model

gs_log_reg.fit(X_train, y_train);
gs_log_reg.best_params_
# Evaluate GridSearchCV for LR model
gs_log_reg.score(X_test, y_test)
model_scores
# make predictions
y_preds=gs_log_reg.predict(X_test)
y_preds
# Import ROC curve fucntion but we have done this previously.
#  roc curve and calculate AUC metric
plot_roc_curve(gs_log_reg, X_test, y_test)
sns.set(font_scale=1.5)

def plot_conf_mat(y__test, y_preds):
    """
    Plots a confusion matrix using Seaborn's heatmap().
    """
    fig, ax = plt.subplots(figsize=(3, 3))
    ax = sns.heatmap(confusion_matrix(y_test, y_preds),
                     annot=True, # Annotate the boxes
                     cbar=False)
    plt.xlabel("Predicted label") # predictions go on the x-axis
    plt.ylabel("True label") # true labels go on the y-axis 
    
plot_conf_mat(y_test, y_preds)
print(classification_report(y_test, y_preds))
# check our best hyperparams
gs_log_reg.best_params_
# create a new classifier with best params

clf= LogisticRegression(C=0.20433597178569418,
                       solver="liblinear")
# Cross validated accuracy
cv_acc= cross_val_score(clf,
                       X,
                       y,
                       cv=5,
                       scoring="accuracy")
cv_acc
cv_acc=np.mean(cv_acc)
cv_acc

# Cross validated precision
cv_precision= cross_val_score(clf,
                       X,
                       y,
                       cv=5,
                       scoring="precision")

cv_precision=np.mean(cv_precision)
cv_precision
# Cross validated recall
cv_recall= cross_val_score(clf,
                       X,
                       y,
                       cv=5,
                       scoring="recall")

cv_recall=np.mean(cv_recall)
cv_recall
# Cross validated f1
cv_f1= cross_val_score(clf,
                       X,
                       y,
                       cv=5,
                       scoring="f1")

cv_f1=np.mean(cv_f1)
cv_f1

# putting it in a graph visualize 
cv_metrics= pd.DataFrame({"Accuracy": cv_acc,
                         "Precision": cv_precision,
                         "Recall": cv_recall,
                         "f1": cv_f1},
                        index=[0])

cv_metrics.T.plot.bar(title="Cross validated classification metrics", legend=False)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11278195488721804, 'fraction_numerical': 0.015342410079252184, 'mean_word_length': 3.1132469703301298, 'pattern_counts': {'":': 11, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '319303', 'license': 'MIT', 'n_tokens_mistral': 3457, 'n_tokens_neox': 3185, 'n_words': 773, 'path': 'HeartDiseaseLogisticRegression_model.ipynb', 'repo_name': 'nimbalkar/Breast-Cancer-Prediction', 'size': '9842'}