<jupyter_start><jupyter_text>Installing and importing the packages<jupyter_code>!pip install alibi
!pip install lazypredict
!pip install eli5
!pip install pyforest
from collections import defaultdict
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy.stats import spearmanr
from scipy.cluster import hierarchy
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.metrics import accuracy_score, roc_curve, auc
from xgboost import XGBClassifier, plot_importance
import warnings
import eli5
from eli5.sklearn import PermutationImportance
from sklearn.tree import DecisionTreeClassifier
warnings.filterwarnings('ignore')
plt.style.use('fivethirtyeight')
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Understanding the data<jupyter_code>data = pd.read_csv('/content/diabetes.csv')
data.head(5)
data.describe()
data.shape
diab = data.copy()
target = 'CLASS'
features_list = list(diab.columns)
features_list.remove(target)<jupyter_output><empty_output><jupyter_text>Histogram<jupyter_code>diab[features_list].hist(bins=40, edgecolor='b', linewidth=1.0,
                          xlabelsize=8, ylabelsize=8, grid=False, 
                          figsize=(16,6), color='red')    
plt.tight_layout(rect=(0, 0, 1.2, 1.2))   
plt.suptitle('diab', x=0.65, y=1.25, fontsize=14);<jupyter_output><empty_output><jupyter_text>Correlation heatmap<jupyter_code>f, ax = plt.subplots(figsize=(10, 6))
corr = diab.corr()
hm = sns.heatmap(round(corr,2), annot=True, ax=ax, cmap="Reds",fmt='.2f',
            linewidths=.05)
f.subplots_adjust(top=0.93)
t= f.suptitle('diab Attributes Correlation Heatmap', fontsize=14)<jupyter_output><empty_output><jupyter_text>Using LazyPredict for model selection<jupyter_code>y = diab.pop('CLASS')
X_train, X_test, y_train, y_test = train_test_split(diab, y, test_size=0.2, random_state=33)
X_train.shape, X_test.shape
import pyforest
import warnings
warnings.filterwarnings("ignore")
from sklearn import metrics
from sklearn.metrics import accuracy_score
import lazypredict
from lazypredict.Supervised import LazyClassifier
clf = LazyClassifier(verbose=0, ignore_warnings=True)
models, predictions = clf.fit(X_train, X_test, y_train, y_test)
models<jupyter_output>100%|██████████| 29/29 [00:01<00:00, 16.79it/s]<jupyter_text>XGB<jupyter_code>%%time
xgb = XGBClassifier(objective='binary:logistic', random_state=33, n_jobs=-1)
xgb.fit(X_train, y_train)
xgb_predictions = xgb.predict(X_test)
def evaluation_scores(test, prediction, target_names=None):
    print('Accuracy:', np.round(metrics.accuracy_score(test, prediction), 4)) 
    print('-'*60)
    print('classification report:\n\n', metrics.classification_report(y_true=test, y_pred=prediction, target_names=target_names)) 
    
    classes = [0, 1]
    total_classes = len(classes)
    level_labels = [total_classes*[0], list(range(total_classes))]
evaluation_scores(y_test, xgb_predictions, target_names=['Diabetic', 'Non-Diabetic', 'Predict-Diabetic'])
# ploting XGBoost default feature importances
fig = plt.figure(figsize = (18, 10))
title = fig.suptitle("Native Feature Importances from XGBoost", fontsize=14)

ax1 = fig.add_subplot(2, 2, 1)
plot_importance(xgb, importance_type='weight', ax=ax1, color='red')
ax1.set_title("Feature Importance with Feature Weight");<jupyter_output><empty_output><jupyter_text>Feature Importance<jupyter_code>import eli5
from eli5.sklearn import PermutationImportance
eli5.show_weights(xgb.get_booster(), top=30)
tgt = 4
print('Reference:', y_test.iloc[tgt])
print('Predicted:', xgb_predictions[tgt])
eli5.show_prediction(xgb.get_booster(), X_test.iloc[tgt], 
                     feature_names=list(diab.columns), show_feature_values=True)
tgt = 1
print('Reference:', y_test.iloc[tgt])
print('Predicted:', xgb_predictions[tgt])
eli5.show_prediction(xgb.get_booster(), X_test.iloc[tgt], 
                     feature_names=list(diab.columns), show_feature_values=True)
%%time
xgb_array = XGBClassifier(objective='binary:logistic', random_state=33, n_jobs=-1)
xgb_model=xgb_array.fit(X_train.values, y_train)
model = DecisionTreeClassifier(random_state=1)
model = model.fit(X_train, y_train)<jupyter_output><empty_output><jupyter_text>Permutation Importance<jupyter_code>permutation = PermutationImportance(model, random_state=21).fit(X_train, y_train)
eli5.show_weights(permutation, feature_names = features_list, top=30)<jupyter_output><empty_output><jupyter_text>**Anchors**<jupyter_code>from alibi.explainers import AnchorTabular
predict_func=lambda x:xgb_model.predict_proba(x)
explainer=AnchorTabular(predict_func,features_list)
xgb_model.predict_proba(X_test.values)
x_train=X_train.to_numpy()
x_test=X_test.to_numpy()
explainer.fit(x_train)
inst=17
target_label=['diabetic','Non diabetic','predicted Diabetic']
print('Person is',target_label[explainer.predictor(x_test[inst].reshape(1, -1))[0]])
anchor=explainer.explain(x_test[inst])
print('Anchor generated feature(/s)',anchor.anchor)<jupyter_output>Person is Non diabetic
Anchor generated feature(/s) ['HbA1c > 6.50']<jupyter_text>**Counterfactuals**<jupyter_code>import tensorflow as tf
tf.get_logger().setLevel(40) # suppress deprecation messages
tf.compat.v1.disable_v2_behavior() # disable TF2 behaviour as alibi code still relies on TF1 constructs
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model, load_model
from tensorflow.keras.utils import to_categorical
df = pd.read_csv('/content/diabetes.csv')
df.head(5)
target = 'CLASS'
features_list = list(diab.columns)
# features_list.remove(target)
data = df[features_list]
target = df[target]
mu = data.mean(axis=0)
sigma = data.std(axis=0)
data = (data - mu) / sigma
x_train, x_test, y_train, y_test = train_test_split(data, target, random_state=0)
# y_train = to_categorical(y_train)
# y_test = to_categorical(y_test)
x_train
y_test
np.random.seed(0)
tf.random.set_seed(0)
def nn_model():
    x_in = Input(shape=(11,))
    x = Dense(40, activation='relu')(x_in)
    x = Dense(40, activation='relu')(x)
    x_out = Dense(3, activation='softmax')(x)
    nn = Model(inputs=x_in, outputs=x_out)
    nn.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
    return nn
y_train
nn = nn_model()
nn.summary()
nn.fit(x_train, y_train, batch_size=64, epochs=500, verbose=0)
nn.save('nn_heart.h5', save_format='h5')
nn = load_model('nn_heart.h5')
score = nn.evaluate(x_test, y_test, verbose=0)
print('Test accuracy: ', score[1])
x_test=x_test.to_numpy()
x_train=x_train.to_numpy()
X = x_test[2].reshape((1,) + x_test[3].shape)
shape = X.shape
from alibi.explainers import CounterFactualProto

nn = load_model('nn_heart.h5')

cf = CounterFactualProto(nn, shape, use_kdtree=True, theta=10., max_iterations=1000,
                         feature_range=(x_train.min(axis=0), x_train.max(axis=0)),
                         c_init=1., c_steps=10)

cf.fit(x_train)
explanation = cf.explain(X)
sigma=sigma.to_numpy()
mu=mu.to_numpy()
print('Original prediction: {}'.format(explanation.orig_class))
print('Counterfactual prediction: {}'.format(explanation.cf['class']))

orig = X * sigma + mu
counterfactual = explanation.cf['X'] * sigma + mu
delta = counterfactual - orig
for i, f in enumerate(features_list):
    if np.abs(delta[0][i]) > 1e-4 and (f!='AGE' and f!='GENDER'):
      # print('{}: {}'.format(f, delta[0][i]))
      print("Change",f,"from",orig[0][i],"to",counterfactual[0][i])<jupyter_output>Original prediction: 1
Counterfactual prediction: 0
Change HbA1c from 6.8 to 5.250233436169516
Change TG from 2.5 to 2.2413257497111942
Change BMI from 32.0 to 25.38997659853263<jupyter_text>**ALE**<jupyter_code>y = diab.pop('CLASS')
X_train, X_test, y_train, y_test = train_test_split(diab.values, y.values, test_size=0.25, random_state=42)
lr_ale = ALE(xgb_model.predict, feature_names=features_list, target_names=['CLASS'])
# rf_ale = ALE(rf.predict, feature_names=feature_names, target_names=['CLASS'])
lr_exp = lr_ale.explain(X_train)
from alibi.explainers import ALE, plot_ale
plot_ale(lr_exp, fig_kw={'figwidth':10, 'figheight': 10})<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1333092919822094, 'fraction_numerical': 0.02764755379252314, 'mean_word_length': 6.992315081652257, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '379472', 'license': 'Apache-2.0', 'n_tokens_mistral': 3231, 'n_tokens_neox': 3038, 'n_words': 547, 'path': 'FeatureBasedTech.ipynb', 'repo_name': 'HetNaik/ExplainableAI_for_Diabetes', 'size': '8319'}