# A Unique Method for Machine Learning Interpretability: Game Theory & Shapley Values!

Now, if we talk in terms of Game Theory, the “game” here is the prediction task for a single instance of the dataset.

The “players” are the feature values of the instance that collaborate to play the game (predict a value) similar to the meal example where Pranav, Ram, and Abhiraj went for a meal together.

In our house example, the feature values has_pool, has_garageand area-50 worked together to achieve the prediction of INR 51,00,000.

Our goal is to explain the difference between the actual prediction (INR 51,00,000) and the average prediction (50,00,000): a difference of INR 1,00,000.

A possible explanation could be has_pool contributed INR 30,000, garage contributed INR 50,000, and area of 50 yards contributed INR 20,000.

The contributions add up to INR 1,00,000 – the final prediction minus the average predicted house price.

To summarise, the Shapley value for each variable (payout) is basically trying to find the correct weight such that the sum of all Shapley values is the difference between the predictions and average value of the model.

In other words, Shapley values correspond to the contribution of each feature towards pushing the prediction away from the expected value.

Now that we have understood the underlying intuition for Shapley values and how useful they can be in interpreting machine learning models, let us look at its implementation in Python.

Model Interpretation using SHAP in Python The SHAP library in Python has inbuilt functions to use Shapley values for interpreting machine learning models.

It has optimized functions for interpreting tree-based models and a model agnostic explainer function for interpreting any black-box model for which the predictions are known.

In the model agnostic explainer, SHAP leverages Shapley values in the below manner.

To get the importance of feature X{i}: Get all subsets of features S that do not contain X{i} Compute effect on our predictions of adding X{i} to all those subsets Aggregate all contributions to compute the marginal contribution of the feature Now, for these subsets, SHAP does not go on and retrain the model for each subset.

Instead, for the removed or left out feature, it just replaces it with the average value of the feature and generates the predictions.

It’s now time to work on a real dataset!.As we did in the previous article, we will use the Big Mart Sales problem hosted on our Datahack Platform.

The problem statement is about predicting sales for different items being sold at different outlets.

We will use Shapley values and also go through some visualizations to look at both local and global interpretations.

Note: You can go through this course to fully understand how to build models using this data.

Our focus here is to narrow down on the Shapley value interpretability part.

You can install the SHAP library using the terminal command: conda install -c conda-forge shap Now, let’s begin with building a model for predicting sales.

First, we will import the necessary libraries: # importing the required libraries import pandas as pd import numpy as np import shap from sklearn.

model_selection import train_test_split from sklearn.

metrics import mean_squared_error from sklearn.

linear_model import LinearRegression from sklearn.

tree import DecisionTreeRegressor from sklearn.

ensemble import RandomForestRegressor from xgboost.

sklearn import XGBRegressor from sklearn.

preprocessing import OneHotEncoder, LabelEncoder from sklearn import tree import matplotlib.

pyplot as plt %matplotlib inline import warnings warnings.

filterwarnings(ignore) Reading Data # reading the data df = pd.

csv) Missing Value Treatment # imputing missing values in Item_Weight by median and Outlet_Size with mode df[Item_Weight].

fillna(df[Item_Weight].

median(), inplace=True) df[Outlet_Size].

fillna(df[Outlet_Size].

mode()[0], inplace=True) Feature Engineering # creating a broad category of type of Items df[Item_Type_Combined] = df[Item_Identifier].

apply(lambda df: df[0:2]) df[Item_Type_Combined] = df[Item_Type_Combined].

map({FD:Food, NC:Non-Consumable, DR:Drinks}) df[Item_Type_Combined].

value_counts() # operating years of the store df[Outlet_Years] = 2013 – df[Outlet_Establishment_Year] # modifying categories of Item_Fat_Content df[Item_Fat_Content] = df[Item_Fat_Content].

replace({LF:Low Fat, reg:Regular, low fat:Low Fat}) df[Item_Fat_Content].

value_counts() Data Preprocessing # label encoding the ordinal variables le = LabelEncoder() df[Outlet] = le.

fit_transform(df[Outlet_Identifier]) var_mod = [Item_Fat_Content,Outlet_Location_Type,Outlet_Size,Item_Type_Combined,Outlet_Type,Outlet] le = LabelEncoder() for i in var_mod: df[i] = le.

fit_transform(df[i]) # one hot encoding the remaining categorical variables df = pd.

get_dummies(df, columns=[Item_Fat_Content,Outlet_Location_Type,Outlet_Size,Outlet_Type, Item_Type_Combined,Outlet]) Train-Test Split # dropping the ID variables and variables that have been used to extract new variables df.

drop([Item_Type,Outlet_Establishment_Year, Item_Identifier, Outlet_Identifier],axis=1,inplace=True) # separating the dependent and independent variables X = df.

drop(Item_Outlet_Sales,1) y = df[Item_Outlet_Sales] # creating the training and validation set X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.

25, random_state=42) Initialize Shap # Need to load JS vis in the notebook shap.

initjs() Fitting XGBoost xgb_model = XGBRegressor(n_estimators=1000, max_depth=10, learning_rate=0.

001, random_state=0) xgb_model.

fit(X_train, y_train) Generating Predictions y_predict = xgb_model.

predict(X_test) Evaluating Performance mean_squared_error(y_test, y_predict)**(0.

5) Local Interpretation using SHAP (for prediction at id number 4776) explainer = shap.

TreeExplainer(xgb_model) shap_values = explainer.

shap_values(X_train) i = 4776 shap.

force_plot(explainer.

expected_value, shap_values[i], features=X_train.

loc[4776], feature_names=X_train.

columns) In blue, we have negative Shap values that show everything that pushes the sales value in the negative direction.

While the Shap value in red represents everything that pushes it towards a positive direction.

Note that this is only for observation number 4776.

Next, let us look at a function that can generate a neat summary for us.

Global Interpretation using Shapley values Now that we can calculate Shap values for each feature of every observation, we can get a global interpretation using Shapley values by looking at it in a combined form.

Let’s see how we can do that: shap.

summary_plot(shap_values, features=X_train, feature_names=X_train.

columns)   We get the above plot by putting everything together under one roof.

This shows the Shap values on the x-axis.

Here, all the values on the left represent the observations that shift the predicted value in the negative direction while the points on the right contribute to shifting the prediction in a positive direction.

All the features are on the left y-axis.

So here, high MRP values are on the right side primarily because they contribute positively to the sales value for each item.

Similarly, for outlets with outlet type 0, they have a high impact on pushing the item sales in the negative direction.

End Notes Interpretability remains a very important aspect of machine learning and data science as more complex models are brought into production.

LIME and Shapley are two such methods that have started seeing some adoption in the industry.

With the advent of deep learning, there is more research being done on how to interpret Natural Language Processing (NLP) and computer vision models.

The interpretability aspect of computer vision has been covered to some extent I hope this was a helpful read for you.