{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Migrating to the new \"Explanation\" API\n", "\n", "This notebook demonstrates some of the changes to the shap API that were introduced in shap `v0.36.0`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# An example dataset and model\n", "import xgboost\n", "\n", "import shap\n", "\n", "X, y = shap.datasets.adult(n_points=100)\n", "model = xgboost.XGBClassifier().fit(X, y)\n", "explainer = shap.TreeExplainer(model, X)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To summarise the main change in the API:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "shap_values = explainer.shap_values(X) # Old style\n", "explanation = explainer(X) # New style" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculating explanations\n", "\n", "### Old style\n", "\n", "In versions of shap before `v0.36.0`, explanations are represented as simple numpy arrays and calculated using the `.shap_values()` method of an explainer:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-0.54854601, 0.01639348, -0.46476041, 0.85896822, -1.36168788,\n", " -0.64692199, 0.0254638 , -0.58422904, -0.02344483, 0. ,\n", " 0.1224989 , 0.01079906],\n", " [-0.83802091, 0.01562196, 0.78349799, -1.10456323, -0.68524691,\n", " -0.84828204, 0.03734176, -0.86151311, -0.02564897, 0. ,\n", " -0.56183428, 0.00415988]])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "shap_values = explainer.shap_values(X)\n", "shap_values[:2] # a numpy array" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, legacy plotting functions like `shap.summary_plot` expected the `shap_values` as a numpy array." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### New style\n", "\n", "As of shap `v0.36.0`, explanations are now represented with the `Explanation` object, and are created by calling the explainer directly as a function:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ".values =\n", "array([[-0.54854601, 0.01639348, -0.46476041, 0.85896822, -1.36168788,\n", " -0.64692199, 0.0254638 , -0.58422904, -0.02344483, 0. ,\n", " 0.1224989 , 0.01079906],\n", " [-0.83802091, 0.01562196, 0.78349799, -1.10456323, -0.68524691,\n", " -0.84828204, 0.03734176, -0.86151311, -0.02564897, 0. ,\n", " -0.56183428, 0.00415988]])\n", "\n", ".base_values =\n", "array([-2.70354599, -2.70354599])\n", "\n", ".data =\n", "array([[27., 4., 10., 0., 1., 1., 4., 0., 0., 0., 44., 39.],\n", " [27., 4., 13., 4., 10., 0., 4., 0., 0., 0., 40., 39.]])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "explanation = explainer(X)\n", "explanation[:2] # a shap.Explanation object" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `shap.Explanation` object is a much richer representation that includes the shap values (accessible with the `.values` attribute) as well as supporting contextual information such as the background dataset and the feature names.\n", "\n", "The new-style plotting functions like `shap.plot.bar` and `shap.plots.beeswarm` accept these `Explanation` objections rather than numpy arrays." ] } ], "metadata": { "kernelspec": { "display_name": "shap", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 2 }