from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
import tensorflow as tf

"""
Explanation: Explainability design pattern
In the Explainability design pattern, we look at approaches to understanding how and why models make predictions, with the goal of improving user trust in ML systems.
End of explanation
"""


!gsutil cp gs://ml-design-patterns/auto-mpg.csv .

data = pd.read_csv('auto-mpg.csv', na_values='?')
data = data.dropna()

data = data.drop(columns=['car name'])

data = pd.get_dummies(data, columns=['origin'])

data.head()

labels = data['mpg']
data = data.drop(columns=['mpg', 'cylinders'])

x,y = data,labels
x_train,x_test,y_train,y_test = train_test_split(x,y)

"""
Explanation: Explaining simpler models
Here we'll use the learned coefficients from a linear regression model as an explainability approach. Note: be cautious when drawing conclusions from learned weights, see the Explainability section in the book for more details.
End of explanation
"""


model = LinearRegression().fit(x_train, y_train)

coefficients = model.coef_
coefdf = pd.DataFrame(coefficients, index=data.columns.tolist(), columns=['Learned coefficients'])

coefdf

"""
Explanation: Train a Scikit-learn linear regression model on the data and print the learned coefficients
End of explanation
"""


model = tf.keras.Sequential([
  tf.keras.layers.Dense(16, activation='relu', input_shape=[len(x_train.iloc[0])]),
  tf.keras.layers.Dense(16, activation='relu'),
  tf.keras.layers.Dense(1)
])

optimizer = tf.keras.optimizers.RMSprop(0.001)

model.compile(loss='mse',
              optimizer=optimizer,
              metrics=['mae', 'mse'])

model.fit(x_train, y_train, epochs=1000)

!pip install shap

import shap

# Create an explainer object and get feature attributions for the first 10 examples in our test dataset
explainer = shap.DeepExplainer(model, x_train[:200])
shap_values = explainer.shap_values(x_test.values[:10])

# Print the feature attributions for the first example in our test set
shap_values[0][0]

# This is the baseline value shap is using
explainer.expected_value.numpy()

shap.initjs()
shap.force_plot(explainer.expected_value[0].numpy(), shap_values[0][0,:], x_test.iloc[0,:])

shap.summary_plot(shap_values, feature_names=data.columns.tolist(), class_names=['MPG'])

"""
Explanation: Feature attributions with SHAP
Using the same dataset, we'll train a deep neural net with TensorFlow and use the SHAP library to get feature attributions.
End of explanation
"""


