Display SHAP diagrams with Streamlit

Hi,

I am building a dashboard for a ML model, using Streamlit.
For the interpretability of the model, I would like to use the SHAP library.

Is there a way to display the SHAP diagrams on my Streamlit dashboard ? (And if yes, how… ;-))

Right now, I run the following minimal code:

import streamlit as st
import xgboost
import shap

# 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, scikit-learn and spark models)
explainer = shap.TreeExplainer(model)

shap_values = explainer.shap_values(X)

# visualize the first prediction's explanation (use matplotlib=True to avoid Javascript)
st.write(shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:], matplotlib=True), unsafe_allow_html=True)

I got this in my navigator, instead of the diagram:
**ValueError** : signal only works in main thread

File "C:\Users\Lebrun\AppData\Roaming\Python\Python37\site-packages\streamlit\ScriptRunner.py", line 311, in _run_script exec(code, module.__dict__)

File "D:\OneDrive\OpenClassrooms\Parcours Data Scientist\projet7\dashboard\shap_streamlit.py", line 24, in <module> st.write(shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:], matplotlib=True), unsafe_allow_html=True)

File "C:\Users\Lebrun\AppData\Roaming\Python\Python37\site-packages\shap\plots\force.py", line 138, in force_plot return visualize(e, plot_cmap, matplotlib, figsize=figsize, show=show, text_rotation=text_rotation)

File "C:\Users\Lebrun\AppData\Roaming\Python\Python37\site-packages\shap\plots\force.py", line 295, in visualize return AdditiveForceVisualizer(e, plot_cmap=plot_cmap).matplotlib(figsize=figsize, show=show, text_rotation=text_rotation)

File "C:\Users\Lebrun\AppData\Roaming\Python\Python37\site-packages\shap\plots\force.py", line 393, in matplotlib fig = draw_additive_plot(self.data, figsize=figsize, show=show, text_rotation=text_rotation)

File "C:\Users\Lebrun\AppData\Roaming\Python\Python37\site-packages\shap\plots\force_matplotlib.py", line 395, in draw_additive_plot plt.show()

File "c:\users\lebrun\anaconda3\envs\ds_projet7\lib\site-packages\matplotlib\pyplot.py", line 269, in show return _show(*args, **kw)

File "c:\users\lebrun\anaconda3\envs\ds_projet7\lib\site-packages\matplotlib\cbook\deprecation.py", line 413, in wrapper return func(*args, **kwargs)

File "c:\users\lebrun\anaconda3\envs\ds_projet7\lib\site-packages\matplotlib\backend_bases.py", line 3302, in show cls.mainloop()

File "c:\users\lebrun\anaconda3\envs\ds_projet7\lib\site-packages\matplotlib\backends\backend_qt5.py", line 1094, in mainloop signal.signal(signal.SIGINT, signal.SIG_DFL)

File "c:\users\lebrun\anaconda3\envs\ds_projet7\lib\signal.py", line 47, in signal handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))

Thank you very much !

1 Like

https://boston-xgb-app.herokuapp.com
please give it a moment on first load (ETA: 45 seconds boot time)
:slight_smile:

2 Likes

Great work !

Is it possible to access the source code of it ?
I have the feeling that for the SHAP diagrams, they are registered and displayed as images. Right ?

Thank you in advance !

1 Like

Sure,


:slight_smile:

1 Like

Thank you ! These lines did the trick :


def main():
    
    # My previous code here
    # […]

    st.pyplot(bbox_inches='tight')
    plt.clf()

if __name__== '__main__':
   main()
1 Like

I was also struggling with this, especially to make the force_plot look nice. With the following I could make it look a bit nicer:

shap.force_plot(expected_value, shap_values[idx,:], features = X.iloc[idx,4:], 
link='logit', matplotlib=True, figsize=(12,3))
st.pyplot(bbox_inches='tight',dpi=300,pad_inches=0)
plt.clf()

Do you think we will eventually be able to include the javascript based plots?

1 Like

Thank you for your suggestion. Just pushed the new force plot :slight_smile:, hope you appreciate it.