Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output to file #3

Closed
coulls opened this issue Oct 24, 2017 · 27 comments
Closed

Output to file #3

coulls opened this issue Oct 24, 2017 · 27 comments

Comments

@coulls
Copy link

coulls commented Oct 24, 2017

Currently, the SHAP module uses a mix of matplotlib and IML to visualize the prediction explanations. It would be great if there was an easy way to save these to a file. For the matplotlib charts, that is easy enough to just call savefig, but saving the IML output is almost impossible.

Is there any way we can achieve this without having to make changes deep within the IML code?

@slundberg
Copy link
Collaborator

That's tricky, but might not be too bad. The right way to do it is to save an SVG file with SVG tags that get displayed by React. Perhaps there is a way in iPython to get the html contents of the output cell?

When I needed to do it myself I either took a screen capture or for paper-quality figures manually snipped out the SVG tags from the document tree in the browser.

@coulls
Copy link
Author

coulls commented Oct 24, 2017

I guess I should have been a bit more specific. I'm looking to use these visualizations at a much larger scale than would be supported in a Jupyter notebook -- something that requires running a script through thousands of samples at the command line.

That pretty much eliminates anything that uses iPython's rendering engine.

@slundberg
Copy link
Collaborator

slundberg commented Oct 24, 2017 via email

@coulls
Copy link
Author

coulls commented Oct 25, 2017

That is what I figured after looking through the code. The best I could expect without a huge amount of effort is to essentially make a custom fork of IML that saves the HTML to a file instead of using the iPython display. Thanks for the note!

@ritviksahajpal
Copy link

@coulls any luck with outputting to a file? This is an excellent package and I am running into the same issue as you i.e. how to use it in a context where ipython cannot be used

@ivan-marroquin
Copy link

Hi @coulls ,

I was wondering if you managed to find the way to generate outputs from command line.

Ivan

@coulls
Copy link
Author

coulls commented Jan 23, 2019

Hey everyone!

When I first asked this question, I did some digging into the interpretable ML package (https://github.com/interpretable-ml/iml) that these visualizations are based on. Unfortunately, when I looked at it, there was some pretty heavy reliance on Javascript output directly into the Jupyter notebook, so there was no easy way to move it to another graphics backend.

If anyone happens to have a solution, please feel free to chime in!

@ivan-marroquin
Copy link

Hi all!

I found a similar application to shap. In this package, the images can be exported to html (including a notebook):

https://marcotcr.github.io/lime/tutorials/Lime%20-%20basic%20usage%2C%20two%20class%20case.html

May be this can help us?

Ivan

@coulls
Copy link
Author

coulls commented Jan 23, 2019

Indeed, LIME was around even before SHAP. However, the approach is slightly different (parameterizations are different in some key ways). In my experience, SHAP has been more 'accurate' or in-line with human interpretation than LIME.

@slundberg
Copy link
Collaborator

I should note that that dependence_plot and summary_plot are already in matplotlib and so can be saved to a file. force_plot is by default drawn using javascript, but someone has contributed a matplotlib version that can obtained by using the matplotlib=True option. Hope that helps clarify the current state of things :)

@ivan-marroquin
Copy link

Thanks @coulls for your comments. but do you think that the approach used by LIME to generate an HTML file could be applied to SHAP?

@ivan-marroquin
Copy link

Thaks @slundberg for letting me know that it is possible to save dependence_plot() and summary_plot() to a file. Please let me know if I got this right. After the command dependence_plot(), can I use plt.savefig() to generate a graphic output?

Regarding LIME capability to generate an HTML file. From a DOS terminal, I can use the command "explainer.save_to_file(path + filename)" - I attached an example for your reference.

Many thanks,
Ivan

example.zip

slundberg added a commit that referenced this issue Jan 24, 2019
@slundberg
Copy link
Collaborator

@ivan-marroquin That's right. You can also pass show=False if you want to keep manipulating the matplotlib plot. I also just added a shap.save_html(file, output_of_force_plot) function since it does seem useful.

@ivan-marroquin
Copy link

Hi @slundberg thanks a lot for adding this functionality!

@ivan-marroquin
Copy link

Hi @slundberg ,

Following your advice, I used these commands:

s_plot= plt.figure()
shap.summary_plot(shap_values_1[0], features= X_test, title= "Toy")
s_plot.savefig('C:\Users\IMarroquin\Documents\SHAP_Model_1_55_summary.png')

The file got created. But the title is missing - and also in the displayed image. Do you have suggestions?

Then, I decided to do the following (since I have a multi-class classifier):

s_plot= plt.figure()
plt.subplot(311)
shap.summary_plot(shap_values_1[0], features= X_test, title= "Toy")
plt.title("Toy")
plt.subplot(312)
shap.summary_plot(shap_values_1[1], features= X_test, title= "Bike")
plt.title("Bike")
plt.subplot(313)
shap.summary_plot(shap_values_1[2], features= X_test, title= "Shoes")
plt.title("Shoes")
s_plot.savefig('C:\Users\IMarroquin\Documents\SHAP_Model_1_55_summary.png')

Failed with these messages:
raise ValueError("'box_aspect' and 'fig_aspect' must be positive")
ValueError: 'box_aspect' and 'fig_aspect' must be positive

Any ideas?

Many thanks,

Ivan

@slundberg
Copy link
Collaborator

Try using show=False in summary_plot to prevent it from displaying the figure before you save it :)

@ivan-marroquin
Copy link

Hi @slundberg ,

Thanks for the suggestion. Unfortunately, I still have the same issue. So, I decided to create individual plots.

Kind regards,

Ivan

@slundberg
Copy link
Collaborator

Ah. Well if you happen to find a solution at some point please share it back here!

@michael1albq
Copy link

@slundberg

First off, great library and I very much appreciate the continually improving functionality.

I was able to get the output from the forceplots - both the initjs() and matplotlib variations, but got and error when I tried to use save_html() for both formats. Any idea as to what's going on here?

Screen Shot 2019-05-29 at 11 17 16 AM

@cbeauhilton
Copy link

cbeauhilton commented May 30, 2019

@michael1albq I had the same problem, had to make the following change to force.py (just added encoding="utf-8" to the open command for the out_file). I thought maybe it was just a problem with my install, so I didn't open an issue, but maybe it's worth seeing if it's a general problem?@slundberg

I included a large part of the save_html command below for context.

def save_html(out_file, plot_html):
    """ Save html plots to an output file.
    """

    internal_open = False
    if type(out_file) == str:
        out_file = open(out_file, "w", encoding="utf-8") # <--- change here
        # out_file = open(out_file, "w")
        internal_open = True
    out_file.write("<html><head><script>\n")

    # dump the js code
    bundle_path = os.path.join(os.path.split(__file__)[0], "resources", "bundle.js")
    with io.open(bundle_path, encoding="utf-8") as f:
        bundle_data = f.read()
    out_file.write(bundle_data)
    out_file.write("</script></head><body>\n")

    out_file.write(plot_html.data)

    out_file.write("</body></html>\n")

@michael1albq
Copy link

This worked!

@slundberg
Copy link
Collaborator

#668 fixes this :)

@kjanko
Copy link

kjanko commented Aug 23, 2019

@slundberg is there a release on PyPi with the fix available?

@slundberg
Copy link
Collaborator

@kjanko I'm planning to get a new release out this week that will have this

@franktoffel
Copy link

franktoffel commented Jul 26, 2020

I wonder how to export to csv the values used for the dot plot (default) and bar plot (global).

For the moment I can get the raw data for the SHAP values.

df_shap_values = pd.DataFrame(shap_values, index=X.index, columns=X.columns)
df_shap_values.to_csv('df_shap_values.csv')

But this of course lacks any transformation, normalization or cleaning that these plots are doing.

Is there any way to export these?

Is all the code behind here https://github.com/slundberg/shap/blob/master/shap/plots/_summary.py?

slundberg pushed a commit that referenced this issue Nov 3, 2020
@jennykathambi90
Copy link

Enabling saving of shap values as a CSV would be great feature to have.

@connortann
Copy link
Collaborator

Closing as save_html addresses the original issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants