【问题标题】:putting HTML output from SHAP into the Dash output layout callback将 SHAP 的 HTML 输出放入 Dash 输出布局回调中
【发布时间】:2019-01-21 14:37:19
【问题描述】:

我正在尝试制作一个仪表板,其中说明了 shap forceplot 的输出。 Shap.forceplot 是用 json 修饰的 HTML。例子是here

我使用教程制作了一个非常简单的仪表板,点击提交后应该会绘制所需的数字

这里是代码

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import pandas as pd
from sqlalchemy import create_engine
import shap
from sources import *
import xgboost

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    dcc.Input(id='input-cvr-state', type='text', value='12'),
    html.Button(id='submit-button', n_clicks=0, children='Submit'),
    html.Div(id='output-state'),
    html.Div(id='output-shap')
])


@app.callback(Output('output-shap', 'children'),
              [Input('submit-button', 'n_clicks')],
              [State('input-cvr-state', 'value')])

def update_shap_figure(n_clicks, input_cvr):
    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

    return(shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:])) # matplotlib=True

if __name__ == '__main__':
    app.run_server(debug=True)

【问题讨论】:

  • 我也在寻找 HTML 页面上的项目形状图。如果您找到答案,请发布答案。

标签: plotly-dash


【解决方案1】:

我通过以下步骤管理它:

import shap
from shap.plots._force_matplotlib import draw_additive_plot

# ... class dashApp
# ... callback as method 
# matplotlib=False => retrun addaptativevisualizer, 
# if set to True the visualizer will render the result is the stdout directly
# x is index of wanted input
# class_1 is ma class to draw

force_plot = shap.force_plot(
    self.explainer.expected_value[class_1],
    self.shap_values[class_1][x[0], :],
    self.data.iloc[x, :].drop(columns=["TARGET"], errors="ignore"),
    matplotlib=False
)
# set show=False to force the figure to be returned
force_plot_mpl = draw_additive_plot(force_plot.data, (30, 7), show=False)
return figure_to_html_img(force_plot_mpl)


def figure_to_html_img(figure):
    """ figure to html base64 png image """ 
    try:
        tmpfile = io.BytesIO()
        figure.savefig(tmpfile, format='png')
        encoded = base64.b64encode(tmpfile.getvalue()).decode('utf-8')
        shap_html = html.Img(src=f"data:image/png;base64, {encoded}")
        return shap_html
    except AttributeError:
        return ""

 

结果会这样

【讨论】:

    【解决方案2】:

    另一种方法是使用html.IFrame,这将产生更好看和完全互动的情节。

    这是一个可以直接作为输出的例子

    def _force_plot_html(*args):
        force_plot = shap.force_plot(*args, matplotlib=False)
        shap_html = f"<head>{shap.getjs()}</head><body>{force_plot.html()}</body>"
        return html.Iframe(srcDoc=shap_html,
                           style={"width": "100%", "height": "200px", "border": 0})
    

    【讨论】:

    • *args 包含什么?
    • 另外,你能提供一个带有html脚本的测试示例吗?是否发出此值?
    • *args 表示它接受与shap.force_plot function 相同的参数。 html.Iframe 对象可以从你的 Dash 函数中返回。
    猜你喜欢
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多