Diving Deeper into Model Interpretability: A Hands-On Comparison of LIME and SHAP

Wilson
3 min readNov 12, 2024

In our previous article, we introduced the concept of model interpretability and briefly compared LIME (Local Interpretable Model-agnostic Explanations) and SHAP (SHapley Additive exPlanations). Now, let’s dive deeper into these techniques with a practical, code-based tutorial that will help you understand how to implement and compare these methods.

Setting Up Our Environment

First, let’s set up our Python environment with the necessary libraries and prepare our dataset:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.datasets import load_iris
import lime
import lime.lime_tabular
import shap

# Load iris dataset
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Train a Gradient Boosting model
gb_model = GradientBoostingClassifier(n_estimators=100, random_state=42)
gb_model.fit(X_train, y_train)

In this setup, we’re using the classic Iris dataset and training a Gradient Boosting Classifier. This will serve as our base model for interpretation.

Implementing LIME

Now, let’s use LIME to interpret our model’s predictions:

# Initialize LIME explainer
lime_explainer = lime.lime_tabular.LimeTabularExplainer(
X_train.values,
feature_names=X_train.columns,
class_names=iris.target_names,
mode='classification'
)

# Get LIME explanation for a single instance
instance_to_explain = X_test.iloc[0]
lime_explanation = lime_explainer.explain_instance(
instance_to_explain.values,
gb_model.predict_proba,
num_features=4
)

print("LIME Explanation:")
lime_explanation.show_in_notebook(show_table=True)

LIME creates a model to approximate our Gradient Boosting Classifier’s predictions in the neighborhood of the chosen instance. The output shows how each feature contributes to the prediction for this specific instance.

LIME Explanation:

Predicting probability of class: setosa

Feature Contribution
petal width (cm) <= 0.31 +0.42
petal length (cm) <= 1.45 +0.38
sepal length (cm) <= 5.10 +0.15
sepal width (cm) > 3.15 +0.05

Prediction probabilities:
setosa: 0.95
versicolor: 0.04
virginica: 0.01

Implementing SHAP

Next, let’s see how SHAP approaches the same task:

# Initialize SHAP explainer
shap_explainer = shap.TreeExplainer(gb_model)

# Get SHAP values for the test set
shap_values = shap_explainer.shap_values(X_test)

# Plot SHAP summary
shap.summary_plot(shap_values, X_test, plot_type="bar", class_names=iris.target_names)

# Get SHAP explanation for a single instance
shap.force_plot(shap_explainer.expected_value[0], shap_values[0][0], X_test.iloc[0], feature_names=X_test.columns)

SHAP calculates Shapley values to determine feature importance. It provides both a global view of feature importance across all classes and a detailed breakdown of how features contribute to a single prediction.

Feature          SHAP Value
petal length |----------------------|
petal width |-------------------|
sepal length |------------|
sepal width |-----|

Color scale: Blue (negative impact) to Red (positive impact)
base value                                   output value
| |
V V
0.33 ----------------------------------------------> 0.95
petal width ==============================>
petal length =========================>
sepal length =========>
sepal width =>

Red bars push prediction higher, blue bars push it lower

Comparing LIME and SHAP Results

To better understand the differences between LIME and SHAP, let’s compare their explanations for the same instance:

print("\nComparison of LIME and SHAP:")
print("LIME feature importance:")
for feature, importance in lime_explanation.as_list():
print(f"{feature}: {importance}")

print("\nSHAP feature importance:")
feature_importance = pd.DataFrame(list(zip(X_test.columns, np.abs(shap_values[0][0]))),
columns=['feature', 'importance'])
feature_importance = feature_importance.sort_values('importance', ascending=False)
print(feature_importance)

This comparison allows us to see how LIME and SHAP may prioritize different features or assign different levels of importance to the same features.

Comparison of LIME and SHAP:

LIME feature importance:
petal width (cm) <= 0.31: 0.42
petal length (cm) <= 1.45: 0.38
sepal length (cm) <= 5.10: 0.15
sepal width (cm) > 3.15: 0.05

SHAP feature importance:
feature importance
petal length (cm) 0.3876
petal width (cm) 0.3654
sepal length (cm) 0.1523
sepal width (cm) 0.0947

In practice, we can find some interesting comparisons between LIME and SHAP:

1. LIME provides a clear, intuitive explanation of how each feature contributes to the prediction for a specific instance.
2. The SHAP summary plot shows the overall importance of each feature across all predictions, with color indicating the direction of impact.
3. The SHAP force plot visualizes how each feature pushes the prediction away from the base value for a single instance.
4. The comparison shows that while LIME and SHAP generally agree on the most important features, they may assign slightly different importance values.

My thought…

Remember, model interpretation is not just about choosing between LIME and SHAP. It’s about understanding your model’s decision-making process, identifying potential biases, and building trust in your AI systems. By mastering these techniques, you’re taking a significant step towards more transparent and accountable machine learning models.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Wilson
Wilson

Written by Wilson

I am a friendly youth from Formosa(Taiwan) with passion and enthusiasm. I seek to integrate technology and finance to bring more fresh things to people’s lives.

No responses yet

Write a response