Shap: Saving SHAP plots programmatically in Python

Created on 12 Jul 2018  ·  20Comments  ·  Source: slundberg/shap

First off, thanks a lot for such an awesome tool!

I think I might be missing something obvious, but I'm trying to save SHAP plots from Python, that I'm displaying with the shap plotting functions. I tried a couple ways:

import matplotlib.pyplot as plt
...
shap.summary_plot(shap_values, final_model_features)
plt.savefig('scratch.png')

and...

import matplotlib.pyplot as plt
...
fig = shap.summary_plot(shap_values, final_model_features)
plt.savefig('scratch.png')

but each just saves a blank image. Is there something obvious I'm missing to programmatically save these awesome plots from Python? Or should I just be re-generating them in matplotlib off the SHAP values matrix to do that? Thanks!

Most helpful comment

By default summary_plot calls plt.show() to ensure the plot displays.
But if you pass show=False to summary_plot then it won't, and think
that might fix the blank figure issue you are having.

On Thu, Jul 12, 2018 at 7:36 AM Max Epstein notifications@github.com
wrote:

First off, thanks a lot for such an awesome tool!

I think I might be missing something obvious, but I'm trying to save SHAP
plots from Python, that I'm displaying with the shap plotting functions. I
tried a couple ways:

import matplotlib.pyplot as plt
...
shap.summary_plot(shap_values, final_model_features)
plt.savefig('scratch.png')

and...

import matplotlib.pyplot as plt
...
fig = shap.summary_plot(shap_values, final_model_features)
plt.savefig('scratch.png')

but each just saves a blank image. Is there something obvious I'm missing
to programmatically save these awesome plots from Python? Or should I just
be re-generating them in matplotlib off the SHAP values matrix to do that?
Thanks!


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/slundberg/shap/issues/153, or mute the thread
https://github.com/notifications/unsubscribe-auth/ADkTxceFgvnQkAAYwNiea4Tb4u3aLlF2ks5uF17jgaJpZM4VM-FL
.

All 20 comments

By default summary_plot calls plt.show() to ensure the plot displays.
But if you pass show=False to summary_plot then it won't, and think
that might fix the blank figure issue you are having.

On Thu, Jul 12, 2018 at 7:36 AM Max Epstein notifications@github.com
wrote:

First off, thanks a lot for such an awesome tool!

I think I might be missing something obvious, but I'm trying to save SHAP
plots from Python, that I'm displaying with the shap plotting functions. I
tried a couple ways:

import matplotlib.pyplot as plt
...
shap.summary_plot(shap_values, final_model_features)
plt.savefig('scratch.png')

and...

import matplotlib.pyplot as plt
...
fig = shap.summary_plot(shap_values, final_model_features)
plt.savefig('scratch.png')

but each just saves a blank image. Is there something obvious I'm missing
to programmatically save these awesome plots from Python? Or should I just
be re-generating them in matplotlib off the SHAP values matrix to do that?
Thanks!


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/slundberg/shap/issues/153, or mute the thread
https://github.com/notifications/unsubscribe-auth/ADkTxceFgvnQkAAYwNiea4Tb4u3aLlF2ks5uF17jgaJpZM4VM-FL
.

hey thanks! that did it.

shap.summary_plot(shap_values, X, show=False)
This is not working for me. The plot still shows and plt.savefig only gives blank.

@JoshKoh perhaps you have something like %matplotlib inline in your notebook? That might change things.

Is there a way to store the figure into a variable instead of saving it to file?
Thanks

@hmanz after running shap.summary_plot(shap_values, X, show=False) you can run import matplotlib.pyplot as pl; f = pl.gcf() to get the current figure in the variable f. What you do with it after that depends on matplotlib and not shap.

@slundberg thank you for your great solution! I was able to use that solution for all SHAP plots except for the multiple-sample force-plots since there is no support for matplotlib=True. Is there a way to accomplish the same task for the multiple-sample force-plots?

More specifically, I am trying to store the plot as a variable so it can be handled by another class's method that will save it to file as a png or jpeg.

Multiple-sample force-plots are Javascript/HTML. So in order to save those programmatically you will need to have some kind of browser-like renderer. Those exist but I can't comment on all the details to get them running.

Why that not work for me?

My code just like the follow, @slundberg
the code just come from your official demo ,and i just want to save the demo image

import xgboost
import shap
import matplotlib.pyplot as plt
# load JS visualization code to notebook
shap.initjs()
# train XGBoost model
X,y = shap.datasets.boston()
model = xgboost.train({"learning_rate": 0.01}, xgboost.DMatrix(X, label=y), 100)

# explain the model's predictions using SHAP values
# (same syntax works for LightGBM, CatBoost, and scikit-learn models)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)

# visualize the first prediction's explanation (use matplotlib=True to avoid Javascript)
# fig = plt.gcf()
# shap._*plot本质上就是调用 plt.show(), 所有我们的思路就是如何在下面的文件进行保存
shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:],show=False)
plt.savefig('scratch.png')

@wabc1994 I was able to save your plot by replacing the last two lines with:

shap.force_plot(explainer.expected_value, shap_values[0,:], 
    X.iloc[0,:],show=False,matplotlib=True)
    .savefig('scratch.png')

Basically, it enables rendering with matplotlib instead of JavaScript and calls savefig on figure returned by force_plot().

,show=False,matplotlib=True)
.savefig('scratch.png')

shap.force_plot(explainer.expected_value, shap_values, X,show=False,matplotlib=True).savefig('scratch.png')

I tried the code above and I get this error:
Exception: matplotlib = True is not yet supported for force plots with multiple samples!

plt.savefig worked for me. Thanks!
but.. can't I save it to HTML like I can after running force_plot?

shap.save_html('explainer.html', shap.force_plot(...))

Note that when matplotlib=True is set then you can't save an HTML version because no HTML version exists (it is now a matplotlib figure, which is typically best exported as a PDF not HTML)

shap.force_plot(explainer.expected_value, shap_values[0,:],
X.iloc[0,:],show=False,matplotlib=True)
.savefig('scratch.png')

This works for me. But by specifying "matplotlib" = True, the resolution of the plot was downgraded, and a more serious issue is some parts of the original plot were cropped. Anyone had a similar issue?

@charlatteD this should solve your resolution and cropping issue:
shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:],show=False,matplotlib=True).savefig('scratch.png',format = "png",dpi = 150,bbox_inches = 'tight')

I can save my force plots with:
shap.force_plot(explainer.expected_value[1], shap_values[1][0,:], top_11.iloc[0,:],show=False,matplotlib=True).savefig('test.png')

But when I include link="logit" as an argument, I get "posx and posy should be finite values" a bunch of times and a blank plot. Does anyone know how to solve this?

I can save my force plots with:
shap.force_plot(explainer.expected_value[1], shap_values[1][0,:], top_11.iloc[0,:],show=False,matplotlib=True).savefig('test.png')

But when I include link="logit" as an argument, I get "posx and posy should be finite values" a bunch of times and a blank plot. Does anyone know how to solve this?

Same with you. Only that I found it occurs in version 0.36.0, but works well in 0.35.0. Hope it will be fixed sooner.

When using plot_image, I can not save image because it does not return anything. I think plotting in shap is quite poor! Does someone have any experiences?

I got this error for force_plot Exception: matplotlib = True is not yet supported for force plots with multiple samples!

The following workaround did the trick for me:

I first exported the interactive chart to HTML, then I saved the HTML file to a high-resolution pdf file.

Here is the code snippet I used:

f=shap.force_plot(explainer.expected_value, shap_values, X, show=False)
shap.save_html("index.htm", f)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Nithanaroy picture Nithanaroy  ·  4Comments

saurabhhjjain picture saurabhhjjain  ·  3Comments

Nithanaroy picture Nithanaroy  ·  4Comments

cbeauhilton picture cbeauhilton  ·  3Comments

yolle103 picture yolle103  ·  3Comments