<jupyter_start><jupyter_text>Predicting heart disease using machine learning modelThis model looks into various Python-based machine learning and data science libraries in order to build a machine learning model capable to predicting wether or not someone has heart disease based on their medical attribute.  I am going to take following approach.1. problem definition2. Data3. Evaluation4. Features5. Modelling6. Experimentation  Problem DefinitionGiven medical record about a patient,can we predict wether or not they have heart disease  DataAttribute Information:1.    age: age in years2.   sex: sex (1 = male; 0 = female)3.    cp: chest pain type        Value 1: typical angina        Value 2: atypical angina        Value 3: non-anginal pain        Value 4: asymptomatic 4.    trestbps: resting blood pressure (in mm Hg on admission to the     hospital)5.    chol: serum cholestoral in mg/dl6.    fbs: fasting blood sugar > 120 mg/dl (1 = true; 0 = false)7.    restecg: resting electrocardiographic results        Value 0: normal        Value 1: having ST-T wave abnormality (T wave inversions and/or ST elevation or depression of > 0.05 mV)        Value 2: showing probable or definite left ventricular hypertrophy by Estes' criteria8.    thalach: maximum heart rate achieved9.    exang: exercise induced angina (1 = yes; 0 = no)10.   oldpeak: ST depression induced by exercise relative to rest11.   slope: the slope of the peak exercise ST segment          Value 1: upsloping          Value 2: flat          Value 3: downsloping12.    ca: number of major vessels (0-3) colored by flourosopy (for calcification of vessels)13.    thal: results of nuclear stress test (3 = normal; 6 = fixed defect; 7 = reversable defect)14.    num: target variable representing diagnosis of heart disease (angiographic disease status) in any major              vessel        Value 0: < 50% diameter narrowing        Value 1: > 50% diameter narrowing  Evaluation if we can reach 95% accuracy we will pursue this project in real life   We are going to use Numpy,pandas and1 matplotlib for our data analysis<jupyter_code>#import all thr tools we need 
import numpy as np 
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline   
#we want to draw plot on notebook itself
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
#For model evaluation
from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.metrics import accuracy_score,f1_score,recall_score,confusion_matrix,classification_report
from sklearn.model_selection import RandomizedSearchCV,GridSearchCV
from sklearn.metrics import plot_roc_curve
#load data 
df=pd.read_csv('7.1 heart-disease.csv')
df.head(7)
df.shape<jupyter_output><empty_output><jupyter_text>data analysis using pandas Know about data available to you in order to make a ML model1. what question are we trying to solve2. what kind of data do we have and how to treat different kind of data3. what is missing fro the data and how to deal with it4. what are the outliers and why shou;d we care about them5. how can we add and remove some features from our data to get more out of it<jupyter_code>df.tail(4)
df['target'].value_counts()

plt.plot(figsize=(20,10))
df['target'].value_counts().plot(kind ='bar',color=['red','green'],figsize=(10,5))
plt.show()
df.info()
#Are there any missing values
df.isna().sum()
df.describe()
# frequency according to sex
sns.set_theme()
df.sex.value_counts().plot(kind='bar',color=['lightgreen','lightblue']);
df.sex.value_counts()
# compare target column with sex column

pd.crosstab(df.target,df.sex).plot(kind='bar',figsize=(10,6))
plt.title('Heart disease frequency for sex')
plt.xlabel('0=no disease,1=disease')
plt.ylabel('sex_count')
plt.legend(['Female','Male']);
#create another figure for age vs thalach
plt.figure(figsize=(10,6))
#creating a scatter plot for positive targets
plt.scatter(df.age[df.target==1],df.thalach[df.target==1],color='fuchsia')
#creating another scatter plot for negetive cases
plt.scatter(df.age[df.target==0],df.thalach[df.target==0],color='darkblue')
plt.legend(['Disease','No Disease'])
plt.title('heart disease in function of age and max heart rate')


plt.show()


sns.set_theme(style='ticks')
df.age.plot.hist();<jupyter_output><empty_output><jupyter_text>Heart Disease per chest pain type1. cp: chest pain type        Value 1: typical angina        Value 2: atypical angina        Value 3: non-anginal pain        Value 4: asymptomatic<jupyter_code>df.cp.value_counts()
pd.crosstab(df.cp,df.target)
pd.crosstab(df.cp,df.target).plot(kind='bar',figsize=(10,6),color=['lightblue','salmon'])
plt.title('Heart Disease per chast pain type')
plt.xlabel('chest pain types')
plt.ylabel('Frequency')
plt.legend(['No Disease','Disease'])
plt.xticks(rotation=0)
plt.show()
df.head()
#Make a correlation matrix
df.corr()
#Plot it on a graph so that we can visualize it more throughly
cor_matrix=df.corr()
fig,ax=plt.subplots(figsize=(15,8))
ax=sns.heatmap(cor_matrix,annot=True,linewidths=0.5,fmt='0.2f',cmap='YlGnBu')
pd.crosstab(df.exang,df.target).plot(kind='bar');

pd.crosstab(df.exang,df.target)
cor_matrix['target']
matrix=pd.DataFrame(cor_matrix)
# how each variable correlate with the target variable out of 1
%matplotlib inline
matrix['target'].plot.bar(figsize=(10,4),color='firebrick')
x=[-1,14]
y=[0,0]
plt.plot(x,y)
xlab=ax.get_xticklabels()
lo=ax.get_xticklabels(which='major')
plt.show()<jupyter_output><empty_output><jupyter_text>Modelling<jupyter_code>#Split the data into features and target
X=df.drop('target',axis=1)
y=df.target
X
y
#Split the data into train and test sets
# We want to split our data in way so that we can generate same random data again sometime later
np.random.seed(42)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2)
X_train.shape,y_train.shape<jupyter_output><empty_output><jupyter_text>Now that we have splitted our data into train and test sets,It's time to choose a model and train it and also test on itI will try Three different model1. logistic regression2. K-NearestNeighbour 3. RandomForestClassifier<jupyter_code>#put the models into dictinary
models={'Logistic Regressio':LogisticRegression(max_iter=1000),
        'KNN':KNeighborsClassifier(),
        'Random Firest':RandomForestClassifier()}

#Also create a function to fit and test 
def fit_and_score(model,X_train,X_test,y_train,y_test):
    """This Function Fits and Evaluate the Models
       models: A dict of three different models
       X_train: Data to traing the models
       y_train:Data for training the model
       X_test:Model testing Data
       y_test:Data for evaluating the model"""
    #Set Random seed to get the same result as before
    np.random.seed(42)
    #create a dictionary for storing the models score
    model_score={}
    #Now Look through each model 
    for name,model in model.items():
        #fit each model to the data
        model.fit(X_train,y_train)
        #Evaluate the model and append the result in model_score
        predict=model.predict(X_test)
        model_score[name]=accuracy_score(y_test,predict)
    return model_score
model_score=fit_and_score(models,X_train,X_test,y_train,y_test)
model_score<jupyter_output><empty_output><jupyter_text>Model comparision<jupyter_code>model_compare=pd.DataFrame(model_score,index=['accuracy'])
sns.set_theme()
model_compare.T.plot.bar();<jupyter_output><empty_output><jupyter_text>Now that we have our base model and their resul we will next go to improve our model by tuning them Now we will look into the following1. Hyperparameter tuning2. feature importance 3. confusion matrix4. precision5. Recall6. ROC curve7. F1_score8. classification report9. cross_validation10. Areaunder the curve(AUc)  Hyperparameter Tuning<jupyter_code>#let's tune KNN
train_score=[]
test_score=[]
#create list of N_Neighbour 
neighbors=np.array(range(1,21))
KNN=KNeighborsClassifier()
for i in neighbors:
    KNN=KNeighborsClassifier(n_neighbors=i)
    KNN.fit(X_train,y_train)
    #update the train score list
    train_score.append(KNN.score(X_train,y_train))
    #update the training score list
    test_score.append(KNN.score(X_test,y_test))
    
train_score
test_score
neighbors
plt.plot(neighbors,train_score,label='training score')
plt.plot(neighbors,test_score,label='test score')
plt.xlabel("Number of neighbors")
plt.xticks(np.arange(1,21,1))
plt.ylabel("model score");<jupyter_output><empty_output><jupyter_text>HyperParameter Tuning with RandomizedSearchCV1. LogisticRegression model2. RandomForestClassifier model<jupyter_code>#create hyperparameter grid for randomizedsearchCV
logistic_grid={'C':np.logspace(-4,4,20),
               'solver':['liblinear']
    }
Random_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 Logistic regression
rs_log_reg=RandomizedSearchCV(LogisticRegression(),param_distributions=logistic_grid,
                             cv=5,n_iter=20,verbose=True)
#fit random hyperparameter search model for logistic regression
rs_log_reg.fit(X_train,y_train)
rs_log_reg.best_params_
rs_log_reg.score(X_test,y_test)
#fit random hyperparameter search model for logistic regression
rs_rf=RandomizedSearchCV(RandomForestClassifier(),
                        param_distributions=Random_grid,
                        cv=5,
                        n_iter=20,verbose=True)
rs_rf.fit(X_train,y_train)

#Find the best Hyperparameter
rs_rf.best_params_
rs_rf.score(X_test,y_test)
model_score<jupyter_output><empty_output><jupyter_text>Hyperparameter Tuning using GridSearchCV    Since Logistic regression is performing better that other two models<jupyter_code>log_grid={'C': np.logspace(-4,4,30),
          'solver': ['liblinear']
    
}
gs_cv=GridSearchCV(LogisticRegression(),param_grid=log_grid,
                  cv=5,
                  verbose=True)
gs_cv.fit(X_train,y_train)
gs_cv.best_params_
#Evaluate Grid Search regression model
gs_cv.score(X_test,y_test)
model_score

predic=gs_cv.predict(X_test)<jupyter_output><empty_output><jupyter_text>Evaluation matrix for classification models1. ROC curve2. confusion matrix3. f1_score4. recall5. precision<jupyter_code>plot_roc_curve(gs_cv,X_test,y_test);
confusion_matrix(y_test,predic)
sns.set(font_scale=1.5)
def plot_heatmap(y_test,predic):
    """plot a nice looking heatmap using confusion matrix"""
    fig,ax=plt.subplots(figsize=(10,6))
    sns.heatmap(confusion_matrix(y_test,predic),annot=True)
    plt.xlabel('True labels')
    plt.ylabel('predicted value')
     
plot_heatmap(y_test,predic)<jupyter_output><empty_output><jupyter_text>Now let's get classification report<jupyter_code>print(classification_report(y_test,predic))<jupyter_output>precision    recall  f1-score   support

           0       0.89      0.86      0.88        29
           1       0.88      0.91      0.89        32

    accuracy                           0.89        61
   macro avg       0.89      0.88      0.88        61
weighted avg       0.89      0.89      0.89        61<jupyter_text>Calculate evaluation matrix using cross validated score<jupyter_code>acc=cross_val_score(gs_cv,X,y,scoring='accuracy',cv=5)
np.mean(acc)
cv_precision=cross_val_score(gs_cv,X,y,scoring='precision',cv=5)
np.mean(cv_precision)
np.random.seed(100)
recall=cross_val_score(gs_cv,X,y,scoring='recall',cv=5)
np.round(np.mean(recall),2)
F1_score=cross_val_score(gs_cv,X,y,scoring='f1',cv=5)
np.mean(F1_score)
cross_val=pd.DataFrame({'accuracy': acc.mean(),
                        'recall': recall.mean(),
                        'precision': cv_precision.mean(),
                       'f1': F1_score.mean()},index=[0])
cross_val.T.plot.bar(figsize=(10,6),legend=False,color='lightgreen',title='cross_validated_classification_report');
import pickle
pickle.dump(gs_cv,open('Heart_Disease_classification_model.APK','wb'))
loaded_model=pickle.load(open('Heart_Disease_classification_model.APK','rb'))
loaded_model.predict(X_test)<jupyter_output><empty_output><jupyter_text>Fearure Importance<jupyter_code>#Which feature contributed the most to the outcome of the model and how did they contribute
#Finding feature importance is different for different models
gs_cv.best_params_
clf=LogisticRegression(C=0.20433597178569418,solver='liblinear')
clf.fit(X_train,y_train)
cl=clf.coef_
feature_dict=dict(zip(df.columns,list(clf.coef_[0])))
feature_dict
cl[0]
feature_df=pd.DataFrame(feature_dict,index=[0])
feature_df
feature_df.T.plot.bar(legend=False);<jupyter_output><empty_output><jupyter_text>experimentation 1. can we collect more data2. can we try a better model3. can we improve the current model (beyond what is now!)4. is our model good enough for the projecdeployment<jupyter_code>pickle.dump(gs_cv,open('Heart_Disease_classification _model.pkl','wb'))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10167013007003771, 'fraction_numerical': 0.02231971061340722, 'mean_word_length': 4.9880184331797235, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '94485', 'license': 'MIT', 'n_tokens_mistral': 4489, 'n_tokens_neox': 4201, 'n_words': 1102, 'path': 'Supervised_Heart_Disease_classification_project.ipynb', 'repo_name': 'hiralal-majhiya/My_Project', 'size': '12993'}