University of Wisconsin - Madison

Department of Industrial and Systems Engineering

ISyE 601: Machine Learning in Action

Fall 2020


Lab 2: Logistic Regression

In [3]:
#Load packages
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import statsmodels.api as sm
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 216, got 192
  return f(*args, **kwds)
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject
  return f(*args, **kwds)
In [4]:
#Load data
data = pd.read_csv('FraminghamClean.csv')
data.head()
Out[4]:
male age education currentSmoker cigsPerDay BPMeds prevalentStroke prevalentHyp diabetes totChol sysBP diaBP BMI heartRate glucose TenYearCHD
0 1 39 4.0 0 0.0 0.0 0 0 0 195.0 106.0 70.0 26.97 80.0 77.0 0
1 0 46 2.0 0 0.0 0.0 0 0 0 250.0 121.0 81.0 28.73 95.0 76.0 0
2 1 48 1.0 1 20.0 0.0 0 0 0 245.0 127.5 80.0 25.34 75.0 70.0 0
3 0 61 3.0 1 30.0 0.0 0 1 0 225.0 150.0 95.0 28.58 65.0 103.0 1
4 0 46 3.0 1 23.0 0.0 0 0 0 285.0 130.0 84.0 23.10 85.0 85.0 0

Exercise - Do it yourself !

Look for correlations

In [5]:
#-------------------------




#-------------------------
In [6]:
#Partition the data into 80% training and 20% testing (you can also do this using train_test_split from sklearn)
np.random.seed(1)
mask = np.random.rand(len(data)) < 0.8
dfTrain = data[mask]
dfTest = data[~mask]
In [7]:
#Train a logistic regression for explanation with all features
Y = dfTrain['TenYearCHD']
X = dfTrain.drop(['TenYearCHD'],axis=1)
model = sm.Logit(Y, sm.add_constant(X))
result = model.fit()
result.summary()
Optimization terminated successfully.
         Current function value: 0.377086
         Iterations 7
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numpy/core/fromnumeric.py:2495: FutureWarning: Method .ptp is deprecated and will be removed in a future version. Use numpy.ptp instead.
  return ptp(axis=axis, out=out, **kwargs)
Out[7]:
Logit Regression Results
Dep. Variable: TenYearCHD No. Observations: 2924
Model: Logit Df Residuals: 2908
Method: MLE Df Model: 15
Date: Sat, 21 Sep 2019 Pseudo R-squ.: 0.1207
Time: 15:05:41 Log-Likelihood: -1102.6
converged: True LL-Null: -1253.9
Covariance Type: nonrobust LLR p-value: 1.612e-55
coef std err z P>|z| [0.025 0.975]
const -8.4105 0.805 -10.444 0.000 -9.989 -6.832
male 0.5351 0.122 4.400 0.000 0.297 0.773
age 0.0693 0.008 9.224 0.000 0.055 0.084
education -0.0485 0.055 -0.888 0.375 -0.156 0.059
currentSmoker 0.1305 0.174 0.750 0.453 -0.211 0.472
cigsPerDay 0.0176 0.007 2.542 0.011 0.004 0.031
BPMeds 0.3125 0.272 1.147 0.251 -0.222 0.847
prevalentStroke 0.6820 0.597 1.143 0.253 -0.488 1.852
prevalentHyp 0.2834 0.154 1.840 0.066 -0.018 0.585
diabetes 0.1162 0.342 0.340 0.734 -0.553 0.786
totChol 0.0021 0.001 1.678 0.093 -0.000 0.005
sysBP 0.0125 0.004 2.896 0.004 0.004 0.021
diaBP -0.0024 0.007 -0.329 0.742 -0.017 0.012
BMI 0.0046 0.014 0.321 0.748 -0.024 0.033
heartRate -0.0012 0.005 -0.261 0.794 -0.010 0.008
glucose 0.0065 0.002 2.642 0.008 0.002 0.011
In [8]:
#Train an explanation model with the Framinham Risk Score Features
Y = dfTrain['TenYearCHD']
X = dfTrain[['age','male','diabetes','sysBP','totChol','currentSmoker']]
model = sm.Logit(Y, sm.add_constant(X))
result = model.fit()
result.summary()
Optimization terminated successfully.
         Current function value: 0.380739
         Iterations 7
Out[8]:
Logit Regression Results
Dep. Variable: TenYearCHD No. Observations: 2924
Model: Logit Df Residuals: 2917
Method: MLE Df Model: 6
Date: Sat, 21 Sep 2019 Pseudo R-squ.: 0.1121
Time: 15:05:43 Log-Likelihood: -1113.3
converged: True LL-Null: -1253.9
Covariance Type: nonrobust LLR p-value: 8.568e-58
coef std err z P>|z| [0.025 0.975]
const -8.6870 0.521 -16.674 0.000 -9.708 -7.666
age 0.0698 0.007 9.703 0.000 0.056 0.084
male 0.6078 0.115 5.306 0.000 0.383 0.832
diabetes 0.6943 0.253 2.747 0.006 0.199 1.190
sysBP 0.0170 0.002 7.092 0.000 0.012 0.022
totChol 0.0022 0.001 1.748 0.081 -0.000 0.005
currentSmoker 0.4242 0.116 3.666 0.000 0.197 0.651
In [9]:
#Train with Qmodel features
Y_Q = dfTrain['TenYearCHD']
X_Q = dfTrain[['age','male','currentSmoker','diabetes','prevalentHyp']]
Qmodel = sm.Logit(Y_Q, sm.add_constant(X_Q))
Qresult = Qmodel.fit()
Qresult.summary()
Optimization terminated successfully.
         Current function value: 0.383753
         Iterations 7
Out[9]:
Logit Regression Results
Dep. Variable: TenYearCHD No. Observations: 2924
Model: Logit Df Residuals: 2918
Method: MLE Df Model: 5
Date: Sat, 21 Sep 2019 Pseudo R-squ.: 0.1051
Time: 15:05:53 Log-Likelihood: -1122.1
converged: True LL-Null: -1253.9
Covariance Type: nonrobust LLR p-value: 6.600e-55
coef std err z P>|z| [0.025 0.975]
const -6.4407 0.392 -16.450 0.000 -7.208 -5.673
age 0.0768 0.007 10.992 0.000 0.063 0.090
male 0.5140 0.112 4.603 0.000 0.295 0.733
currentSmoker 0.4284 0.115 3.717 0.000 0.203 0.654
diabetes 0.7695 0.250 3.078 0.002 0.280 1.260
prevalentHyp 0.7034 0.112 6.297 0.000 0.484 0.922

Exercise - Do it yourself !

Train a model with the DModel features from class

In [10]:
#-------------------------






#-------------------------
In [20]:
#Get test sets for each of the Q and D models
Xtest_Q = dfTest[['age','male','currentSmoker','diabetes','prevalentHyp']]
Xtest_D = dfTest[['age','male','cigsPerDay','glucose','sysBP']]

#Predict test set probabilities
yhatQ = Qmodel.predict(Qresult.params,sm.add_constant(Xtest_Q))
yhatD = Dmodel.predict(Dresult.params,sm.add_constant(Xtest_D))
In [21]:
#Plot the ROC curve
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
from matplotlib.pyplot import plot, show, savefig, xlim, figure, \
                ylim, legend, boxplot, setp, axes

#Compute all points along the curve (by varying the threshold and determining the FPR and TPR)
fprQ, tprQ, threshQ = roc_curve(dfTest.TenYearCHD, yhatQ)
roc_auc_Q= roc_auc_score(dfTest.TenYearCHD, yhatQ)

fprD, tprD, threshD = roc_curve(dfTest.TenYearCHD, yhatD)
roc_auc_D= roc_auc_score(dfTest.TenYearCHD, yhatD)
                         
#Plot the ROC curves! 
fig = figure(figsize=(10, 6))
plt.plot([0, 1], [0, 1], linestyle='--')
plt.plot(fprQ, tprQ, label='QModel (AUC = %0.2f)' % roc_auc_Q)
plt.plot(fprD, tprD, label='DModel (AUC = %0.2f)' % roc_auc_D)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc='lower right');
plt.show()
#fig.savefig('QvsD_ModelROC.pdf', bbox_inches='tight')
In [22]:
#Manually round the predictions according to the threshold with a TPR of 0.8

#Dmodel
yhatDround = []
for i in yhatD:
    if i > threshD[next(x[0] for x in enumerate(tprD) if x[1] > 0.8)]:
        yhatDround.append(1)
    else:
        yhatDround.append(0)
        
#Qmodel
yhatQround = []
for i in yhatQ:
    if i > threshQ[next(x[0] for x in enumerate(tprQ) if x[1] > 0.8)]:
        yhatQround.append(1)
    else:
        yhatQround.append(0)
In [23]:
#Print the thresholds corresponding to the above rounding scheme
print(threshQ[next(x[0] for x in enumerate(tprQ) if x[1] > 0.8)])
print(threshD[next(x[0] for x in enumerate(tprQ) if x[1] > 0.8)])
0.10621801063425716
0.1216964436561329
In [41]:
#Create a confusion matrix for D model
from sklearn.metrics import confusion_matrix

#Get the confusion matrix
cMatrix = confusion_matrix(y_true = dfTest.TenYearCHD, y_pred = yhatDround)

#Plot the confusion matrix
fig = figure(figsize=(10, 6))
plt.imshow(cMatrix, cmap=plt.cm.Blues)
plt.text(0, 0, '{}'.format(cMatrix[0, 0]), horizontalalignment='center',fontsize = 'xx-large')
plt.text(0, 1, '{}'.format(cMatrix[1, 0]), horizontalalignment='center',fontsize = 'xx-large')
plt.text(1, 0, '{}'.format(cMatrix[0, 1]), horizontalalignment='center',fontsize = 'xx-large')
plt.text(1, 1, '{}'.format(cMatrix[1, 1]), horizontalalignment='center',fontsize = 'xx-large')
tick_marks = [0,1]
labels = ['Healthy', 'Heart Disease']
plt.xticks(tick_marks, labels, rotation=90,fontsize = 'x-large')
plt.ylim([-0.5,1.5])
plt.yticks(tick_marks, labels,fontsize = 'x-large')
plt.ylabel('True label',fontsize = 'xx-large')
plt.xlabel('Predicted label',fontsize = 'xx-large')
plt.show()
#fig.savefig('Dmodel_CM.pdf', bbox_inches='tight')

Exercise - Do it yourself !

Create the confusion matrix for the Q model

In [13]:
#Create the confusion matrix for the Q model
In [8]:
#Train a regularized logistic regression model using grid search
from sklearn.model_selection import GridSearchCV

#Pick a model
model = LogisticRegression(solver='liblinear')

#Choose some hyperparameters to search over
params = {'C':[0.0001,0.001,0.01,0.1,1,10,100,250,500,750,1000],'penalty':['l1','l2']}

#Run gridsearch (there is also a specific grid search function for logistic regression - LogisticRegressionCV)
clf = GridSearchCV(model,params, cv=10,scoring='roc_auc') #10 fold CV with AUC as the accuracy metric
clf.fit(dfTrain.drop(['TenYearCHD'],axis=1),dfTrain.TenYearCHD)

#Print out the results
clf.cv_results_
Out[8]:
{'mean_fit_time': array([0.00423951, 0.00626721, 0.00749111, 0.00712445, 0.03836172,
        0.01168787, 0.04484537, 0.01665752, 0.06371779, 0.02207286,
        0.06759419, 0.02431953, 0.06744239, 0.0229836 , 0.06694632,
        0.02460275, 0.06672344, 0.02227583, 0.06727374, 0.02320707,
        0.06619179, 0.02293408]),
 'std_fit_time': array([0.00073838, 0.00074631, 0.00064458, 0.00062623, 0.00241321,
        0.00088881, 0.0029515 , 0.00238684, 0.00266042, 0.0024226 ,
        0.00737698, 0.00140985, 0.00253946, 0.0026333 , 0.0069872 ,
        0.00199657, 0.00306292, 0.00102843, 0.00688792, 0.00216797,
        0.00264465, 0.00117587]),
 'mean_score_time': array([0.00189984, 0.00163536, 0.00158527, 0.00147865, 0.00174861,
        0.00187995, 0.0020937 , 0.00169771, 0.00178819, 0.00181346,
        0.0017385 , 0.00165558, 0.00180163, 0.00162613, 0.00167148,
        0.00173249, 0.001757  , 0.00157378, 0.00173185, 0.00155385,
        0.00172329, 0.00161736]),
 'std_score_time': array([2.97471380e-04, 1.59168208e-04, 2.55025277e-04, 9.08005162e-05,
        2.15139044e-04, 2.82903862e-04, 8.96431957e-04, 2.82828375e-04,
        3.69676672e-04, 4.22166382e-04, 1.54174174e-04, 1.16026494e-04,
        1.44455698e-04, 1.33903832e-04, 7.37977756e-05, 1.71916765e-04,
        1.97648059e-04, 5.74734628e-05, 7.56912304e-05, 6.13215227e-05,
        1.20277341e-04, 6.08501060e-05]),
 'param_C': masked_array(data=[0.0001, 0.0001, 0.001, 0.001, 0.01, 0.01, 0.1, 0.1, 1,
                    1, 10, 10, 100, 100, 250, 250, 500, 500, 750, 750,
                    1000, 1000],
              mask=[False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False],
        fill_value='?',
             dtype=object),
 'param_penalty': masked_array(data=['l1', 'l2', 'l1', 'l2', 'l1', 'l2', 'l1', 'l2', 'l1',
                    'l2', 'l1', 'l2', 'l1', 'l2', 'l1', 'l2', 'l1', 'l2',
                    'l1', 'l2', 'l1', 'l2'],
              mask=[False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False],
        fill_value='?',
             dtype=object),
 'params': [{'C': 0.0001, 'penalty': 'l1'},
  {'C': 0.0001, 'penalty': 'l2'},
  {'C': 0.001, 'penalty': 'l1'},
  {'C': 0.001, 'penalty': 'l2'},
  {'C': 0.01, 'penalty': 'l1'},
  {'C': 0.01, 'penalty': 'l2'},
  {'C': 0.1, 'penalty': 'l1'},
  {'C': 0.1, 'penalty': 'l2'},
  {'C': 1, 'penalty': 'l1'},
  {'C': 1, 'penalty': 'l2'},
  {'C': 10, 'penalty': 'l1'},
  {'C': 10, 'penalty': 'l2'},
  {'C': 100, 'penalty': 'l1'},
  {'C': 100, 'penalty': 'l2'},
  {'C': 250, 'penalty': 'l1'},
  {'C': 250, 'penalty': 'l2'},
  {'C': 500, 'penalty': 'l1'},
  {'C': 500, 'penalty': 'l2'},
  {'C': 750, 'penalty': 'l1'},
  {'C': 750, 'penalty': 'l2'},
  {'C': 1000, 'penalty': 'l1'},
  {'C': 1000, 'penalty': 'l2'}],
 'split0_test_score': array([0.36899642, 0.57392473, 0.45044803, 0.58646953, 0.57858423,
        0.61827957, 0.67939068, 0.65456989, 0.70654122, 0.69086022,
        0.70689964, 0.70546595, 0.70707885, 0.70582437, 0.70698925,
        0.70636201, 0.70707885, 0.70707885, 0.70707885, 0.70663082,
        0.70707885, 0.70725806]),
 'split1_test_score': array([0.43660394, 0.58297491, 0.46505376, 0.59265233, 0.58422939,
        0.6203405 , 0.67724014, 0.65896057, 0.71774194, 0.70179211,
        0.71908602, 0.715681  , 0.71953405, 0.71550179, 0.71953405,
        0.71863799, 0.71953405, 0.71854839, 0.71953405, 0.715681  ,
        0.71944444, 0.7188172 ]),
 'split2_test_score': array([0.48140681, 0.6047491 , 0.48933692, 0.62482079, 0.61478495,
        0.64560932, 0.69462366, 0.67553763, 0.72831541, 0.72213262,
        0.72831541, 0.72858423, 0.72858423, 0.72849462, 0.72849462,
        0.72768817, 0.72858423, 0.72822581, 0.72831541, 0.72822581,
        0.72849462, 0.72849462]),
 'split3_test_score': array([0.48382616, 0.62983871, 0.51693548, 0.65555556, 0.63736559,
        0.68207885, 0.72410394, 0.71290323, 0.73109319, 0.73611111,
        0.73019713, 0.73315412, 0.73055556, 0.73154122, 0.73028674,
        0.73055556, 0.73055556, 0.73046595, 0.73037634, 0.73055556,
        0.73037634, 0.73082437]),
 'split4_test_score': array([0.50170251, 0.66550179, 0.49426523, 0.67822581, 0.66854839,
        0.70035842, 0.72320789, 0.7124552 , 0.72060932, 0.72329749,
        0.71747312, 0.71908602, 0.7171147 , 0.71747312, 0.71702509,
        0.71738351, 0.71702509, 0.71765233, 0.7171147 , 0.7172043 ,
        0.71684588, 0.71756272]),
 'split5_test_score': array([0.40697256, 0.54089069, 0.40611786, 0.56158345, 0.54916779,
        0.59577148, 0.66720648, 0.64705353, 0.71363023, 0.69311741,
        0.71740891, 0.71255061, 0.71767881, 0.71839856, 0.71767881,
        0.71848853, 0.71758884, 0.71803869, 0.71776878, 0.7154296 ,
        0.71767881, 0.71839856]),
 'split6_test_score': array([0.46225821, 0.63175888, 0.46153846, 0.65353126, 0.63067926,
        0.70391363, 0.75798471, 0.74997751, 0.77768781, 0.77552857,
        0.77795771, 0.77903734, 0.77831759, 0.7788574 , 0.77822762,
        0.77804768, 0.77804768, 0.77894737, 0.77822762, 0.77831759,
        0.77831759, 0.77813765]),
 'split7_test_score': array([0.44669366, 0.60611786, 0.45092218, 0.634278  , 0.61682411,
        0.67737292, 0.72496626, 0.71641925, 0.73918129, 0.73891138,
        0.74062078, 0.74062078, 0.74071075, 0.74008097, 0.74071075,
        0.74044085, 0.74071075, 0.74053081, 0.74071075, 0.74035088,
        0.74071075, 0.74053081]),
 'split8_test_score': array([0.37179487, 0.59064327, 0.43634728, 0.60368871, 0.59100315,
        0.63850652, 0.70841206, 0.69221772, 0.73783176, 0.73351327,
        0.7382816 , 0.73873144, 0.7380117 , 0.73909132, 0.73819163,
        0.73882141, 0.73819163, 0.73846154, 0.7380117 , 0.73846154,
        0.7382816 , 0.73900135]),
 'split9_test_score': array([0.39064225, 0.62182554, 0.4708318 , 0.66323151, 0.63654766,
        0.68825911, 0.7131947 , 0.70104895, 0.73997056, 0.73040118,
        0.74337505, 0.74365109, 0.74337505, 0.74420317, 0.74337505,
        0.74346706, 0.74337505, 0.74365109, 0.74337505, 0.74438719,
        0.74328303, 0.74365109]),
 'mean_test_score': array([0.43513814, 0.60482798, 0.46420996, 0.62539442, 0.61077478,
        0.65703201, 0.70701843, 0.69209551, 0.73123951, 0.72454791,
        0.73193785, 0.7316329 , 0.73207257, 0.73192164, 0.73202768,
        0.73196506, 0.73204562, 0.73213603, 0.73202767, 0.73149974,
        0.73202751, 0.73224379]),
 'std_test_score': array([0.04580794, 0.03323852, 0.02981014, 0.03623843, 0.03329805,
        0.03628118, 0.02626964, 0.03110877, 0.01887338, 0.02387438,
        0.01894978, 0.01998239, 0.01897801, 0.01955566, 0.01898476,
        0.01902797, 0.01893209, 0.01916126, 0.01895594, 0.01955921,
        0.01901169, 0.01891235]),
 'rank_test_score': array([22, 20, 21, 18, 19, 17, 15, 16, 13, 14,  9, 11,  3, 10,  5,  8,  4,
         2,  6, 12,  7,  1], dtype=int32)}
In [9]:
#Plot the grid search results
def plot_grid_search(cv_results, grid_param_1, grid_param_2, name_param_1, name_param_2):
    # Get Test Scores Mean and std for each grid search
    scores_mean = cv_results['mean_test_score']
    scores_mean = np.array(scores_mean).reshape(len(grid_param_2),len(grid_param_1))

    scores_sd = cv_results['std_test_score']
    scores_sd = np.array(scores_sd).reshape(len(grid_param_2),len(grid_param_1))

    # Plot Grid search scores
    _, ax = plt.subplots(1,1)

    # Param1 is the X-axis, Param 2 is represented as a different curve (color line)
    for idx, val in enumerate(grid_param_2):
        ax.plot(grid_param_1, scores_mean[idx,:], '-o', label= name_param_2 + ': ' + str(val))

    ax.set_xlabel(name_param_1, fontsize=16)
    ax.set_ylabel('Average AUC', fontsize=16)
    ax.legend(loc="best", fontsize=15)
    ax.grid('on')
    plt.show()

# Calling Method 
plot_grid_search(clf.cv_results_, params['C'], params['penalty'], 'Hyperparameter value (C)', 'Regularization type')

Exercise - Do it yourself !

Pick the best model and initalize as 'model'. See here for documentation.

In [59]:
#Pick and define the best model
model = LogisticRegression(solver = 'liblinear',penalty='l2',C=10)
In [60]:
#Train the model
model.fit(dfTrain.drop(['TenYearCHD'],axis=1),dfTrain.TenYearCHD)

#Predict test set probabilities
preds = model.predict_proba(dfTest.drop(['TenYearCHD'],axis=1)).T[1]
In [61]:
#Create the ROC curve 
fprLR, tprLR, threshLR = roc_curve(dfTest.TenYearCHD, preds)
roc_auc_LR= roc_auc_score(dfTest.TenYearCHD, preds)

#Plot and compare with the Q and D models
fig = figure(figsize=(10, 6))
plt.plot([0, 1], [0, 1], linestyle='--')
plt.plot(fprQ, tprQ, label='QModel (AUC = %0.2f)' % roc_auc_Q)
plt.plot(fprD, tprD, label='DModel (AUC = %0.2f)' % roc_auc_D)
plt.plot(fprLR, tprLR, label='Regularized (AUC = %0.2f)' % roc_auc_LR)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc='lower right');
plt.show()
fig.savefig('QvsDvsLR_ModelROC.pdf', bbox_inches='tight')
In [62]:
#Round the output using a threshold corresponding to a TPR of 0.8
yhatLRround = []
for i in preds:
    if i > threshLR[next(x[0] for x in enumerate(tprLR) if x[1] > 0.8)]:
        yhatLRround.append(1)
    else:
        yhatLRround.append(0)
In [65]:
#Create a confusion matrix
cMatrix = confusion_matrix(y_true = dfTest.TenYearCHD, y_pred = yhatLRround)
fig = figure(figsize=(10, 6))
plt.imshow(cMatrix, cmap=plt.cm.Blues)
plt.text(0, 0, '{}'.format(cMatrix[0, 0]), horizontalalignment='center',fontsize = 'xx-large')
plt.text(0, 1, '{}'.format(cMatrix[1, 0]), horizontalalignment='center',fontsize = 'xx-large')
plt.text(1, 0, '{}'.format(cMatrix[0, 1]), horizontalalignment='center',fontsize = 'xx-large')
plt.text(1, 1, '{}'.format(cMatrix[1, 1]), horizontalalignment='center',fontsize = 'xx-large')
tick_marks = [0,1]
plt.ylim([-0.5,1.5])
labels = ['Healthy', 'Heart Disease']
plt.xticks(tick_marks, labels, rotation=90,fontsize = 'x-large')
plt.yticks(tick_marks, labels,fontsize = 'x-large')
plt.ylabel('True label',fontsize = 'xx-large')
plt.xlabel('Predicted label',fontsize = 'xx-large')
plt.show()
fig.savefig('LR_CM.pdf', bbox_inches='tight')

Exercise - Do it yourself !

Pick a different "best" model and repeat the above steps

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]: