explainerdashboard

repository·master·Indexed 25 days ago

https://github.com/oegedijk/explainerdashboard

A library for quickly deploying interactive web dashboards to explain machine learning models. It supports scikit-learn, xgboost, catboost, lightgbm, and skorch, providing tools such as SHAP values, partial dependence plots, feature importance visualizations, and performance metrics for classifiers and regressors. The library includes specialized components like ClassifierExplainer and RegressionExplainer, supports deployment to static HTML or SageMaker Studio, and offers an ExplainerHub for managing multiple dashboards.

Tokens
44.8K
Snippets
85
Records
219
Agent score
81%

What's inside explainerdashboard

  1. Overview of explainerdashboard capabilities

    master

    explainerdashboard is a tool for deploying web applications that explain machine learning models (compatible with scikit-learn, xgboost, catboost, lightgbm, skorch, etc.).

    Key features include:

    • Feature Importance & Contributions: SHAP values (individual predictions), SHAP interaction values, and Permutation importances.
    • Model Behavior: Partial dependence plots and "what if" analysis.
    • Model-Specific Visualizations: Individual decision tree visualizations (for Random Forest, XGBoost, and LightGBM).
    • Performance Metrics:
      • Classifiers: Precision plots, confusion matrix, ROC AUC, and PR AUC.
      • Regressors: Goodness-of-fit and residual plots.
    • Deployment: Dashboards can be exported to static HTML or managed via a modular design for custom layouts and ExplainerHub for combining multiple dashboards.
  2. How lazy calculation works in Explainers

    master

    Explainers use lazy calculation. Properties (like SHAP values) are not calculated until they are explicitly requested for an output.

    • The first time you request a plot or value involving SHAP, it may take significant time to compute.
    • Subsequent requests for the same property will be nearly instant as the result is cached.

    To pre-calculate all properties at once and avoid delays during dashboard interaction, call:

    explainer.calculate_properties()

    Note: ExplainerComponents use component.calculate_dependencies() for a similar purpose.

  3. Use the default ExplainerDashboard tabs

    master

    The default ExplainerDashboard is composed of seven standard composite tabs. You can import these from explainerdashboard.custom to design your own custom dashboards or use them as building blocks.

    The seven default tabs are:

    • ImportancesComposite
    • ModelSummaryComposite (Note: listed as ClassifierModelStatsComposite or RegressionModelStatsComposite in specific contexts)
    • IndividualPredictionsComposite
    • WhatIfComposite
    • ShapDependenceComposite
    • ShapInteractionsComposite
    • DecisionTreesComposite
    from explainerdashboard.custom import (
        ImportancesComposite,
        ModelSummaryComposite,
        IndividualPredictionsComposite,
        WhatIfComposite,
        ShapDependenceComposite,
        ShapInteractionsComposite,
        DecisionTreesComposite
    )
  4. How ExplainerComponents work together

    master

    The dashboard is built using ExplainerComponents, which are self-contained, reusable elements (like plots, tables, sliders, or dropdowns).

    Key concepts:

    • Composition: You can build custom dashboards by subclassing ExplainerComponent and defining a layout() method that returns a collection of components (using html.Div or similar).
    • Connectivity: Components can be linked using connectors. When an index is selected in one component, it can automatically update the index in another.
    • Customization: You can control which components are visible, their layout, which interactive toggles/sliders are shown, and their initial values to restrict what end-users can manipulate.

    To use these components in a custom dashboard, import them via from explainerdashboard.custom import *.

    from explainerdashboard.custom import *
    
    class CustomDashboard(ExplainerComponent):
       def __init__(self, explainer, title="Custom Dashboard", name="None"):
          super().__init__(explainer, title, name=name)
          self.shap_dependence = ShapDependenceComponent(explainer, name=self.name+"dep",
                             hide_title=True, hide_cats=True, hide_highlight=True,
                             cats=True, col='Fare')
    
       def layout(self):
          return html.Div([
             self.shap_dependence.layout()
          ])
    
    ExplainerDashboard(explainer, CustomDashboard).run()
  5. Use ExplainerHub to host multiple dashboards

    master

    To combine multiple dashboards into a single interface, use ExplainerHub. This allows you to manage multiple models (e.g., a classifier and a regressor) in one place.

    db1 = ExplainerDashboard(explainer1, title="Classifier Explainer",
             description="Model predicting survival on H.M.S. Titanic")
    db2 = ExplainerDashboard(explainer2, title="Regression Explainer",
             description="Model predicting ticket price on H.M.S. Titanic")
    hub = ExplainerHub([db1, db2])
    hub.run()
  6. How ExplainerHub works for hosting multiple dashboards

    master

    If you need to host multiple dashboards simultaneously, use ExplainerHub. You pass a list of ExplainerDashboard instances to the hub.

    Each dashboard is hosted at its own unique URL path (e.g., localhost:8050/dashboard1), while the ExplainerHub provides a central front-end landing page with links and descriptions for all hosted dashboards.

    db1 = ExplainerDashboard(explainer1)
    db2 = ExplainerDashboard(explainer2)
    hub = ExplainerHub([db1, db2])
    hub.run()
  7. Configure Dash pathname prefixes for reverse proxies and path prefixes

    master

    When deploying behind a reverse proxy, ingress (like Azure, Kubernetes, AWS ALB), or any platform using sub-paths (like Fly.io or Databricks), you must ensure that the Dash base paths and the proxy routing are synchronized. If they do not match, you will see Loading... errors and 404 responses for /_dash-layout and /_dash-dependencies.

    To fix this, set the following three parameters to the same shared base path in the ExplainerDashboard constructor:

    1. url_base_pathname
    2. routes_pathname_prefix
    3. requests_pathname_prefix
    db = ExplainerDashboard(
        explainer,
        url_base_pathname="/dashboard/",
        routes_pathname_prefix="/dashboard/",
        requests_pathname_prefix="/dashboard/",
    )
    app = db.flask_server()
  8. Connect components using Connectors

    master

    Connectors allow different components to interact. For example, selecting a feature in one component can automatically update another.

    Commonly used connectors include:

    • ShapSummaryDependenceConnector: Connects a ShapSummaryComponent and a ShapDependenceComponent so that selecting a feature in the summary updates the dependence plot.
    • IndexConnector: Connects an index selector (like ClassifierRandomIndexComponent) to other components (like ShapContributionsGraphComponent or DecisionTreesComponent) so they all view the same data point.
    • PosLabelConnector
    • CutoffConnector
    • HighlightConnector
  9. How to set and use the positive label (pos_label)

    master

    In ClassifierExplainer, you can specify which class is treated as the positive class. This affects almost all properties and methods.

    Setting the label

    You can set the global pos_label on the explainer instance:

    explainer.pos_label = 0
    # or using string labels
    explainer.pos_label = 'Survived'

    Overriding the label

    You can also pass a specific pos_label to individual methods without changing the global setting:

    # Uses the global explainer.pos_label
    explainer.plot_dependence("Fare") 
    
    # Overrides for this specific call only
    explainer.plot_dependence("Fare", pos_label=0) 

    In the ExplainerDashboard UI, a dropdown menu allows you to change the pos_label, which updates all plots in the dashboard simultaneously.

    explainer.pos_label = 0
    explainer.plot_dependence("Fare") # will show plot for pos_label=0
    
    explainer.pos_label = 'Survived'
    explainer.plot_dependence("Fare") # will now show plot for pos_label=1
    
    explainer.plot_dependence("Fare", pos_label=0) # show plot for label 0, without changing explainer.pos_label
  10. Construct layouts using dash_bootstrap_components and dash_html_components

    master

    Custom layouts in explainerdashboard are built using the underlying Dash ecosystem:

    • dash_bootstrap_components (aliased as dbc): Used for responsive grid layouts. The layout is structured using dbc.Row and dbc.Col. The total width of columns in a single row should add up to 12.
    • dash_html_components (aliased as html): Used for standard HTML elements like headers (html.H1, html.H3), divs, etc.

    When using from explainerdashboard.custom import *, these libraries are automatically imported for you as dbc and html respectively.

  11. Group one-hot encoded features using the `cats` parameter

    master

    If your categorical variables are one-hot encoded, they appear as multiple independent features. You can group them back into a single categorical feature using the cats parameter in the Explainer constructor. This allows you to use the grouped name in plotting methods (e.g., explainer.plot_dependence("GroupedName")), which will generate violin plots instead of scatter plots.

    Ways to specify cats:

    1. Dictionary: Map the group name to a list of one-hot encoded column names. cats={'Gender': ['Sex_male', 'Sex_female']}
    2. List of prefixes: If columns follow the Prefix_Category pattern (e.g., from pd.get_dummies), pass a list of prefixes. cats=['Sex', 'Deck', 'Embarked']
    3. Mixed: Combine both methods. cats=[{'Gender': ['Sex_male', 'Sex_female']}, 'Deck', 'Embarked']
  12. Handle component state in custom HTML exports

    master

    If your custom components depend on Dash input values (like toggles or sliders), you must map these to component parameters so they are correctly captured during HTML export.

    1. Define _state_props: Add a _state_props class attribute as a dictionary. The keys should be the names of the __init__ parameters, and the values should be a tuple containing the Dash component ID prefix and the property name (e.g., 'value').
      • Note: Do not include self.name in the ID prefix; explainerdashboard automatically appends it.
    2. Retrieve State: Inside your to_html method, call args = self.get_state_args(state_dict). This returns a dictionary of the current parameter values.
    3. State Flow: When a user clicks 'download' on a live dashboard, the current state is collected into state_dict. You must pass this state_dict down to all sub-components in their to_html calls to ensure the exported HTML reflects the user's current settings.
    class ConfusionMatrixComponent(ExplainerComponent):
        # Maps parameter names to (dash_id_prefix, property)
        _state_props = dict(
            cutoff=('confusionmatrix-cutoff-', 'value'),
            percentage=('confusionmatrix-percentage-', 'value'),
            normalize=('confusionmatrix-normalize-', 'value'),
            binary=('confusionmatrix-binary-', 'value'),
            pos_label=('pos-label-', 'value')
        )
    
        def to_html(self, state_dict=None, add_header=True):
            # Retrieve current values from state_dict or instance properties
            args = self.get_state_args(state_dict)
            
            # Use args to drive the plotting logic
            fig = self.explainer.plot_confusion_matrix(
                cutoff=args['cutoff'],
                percentage=bool(args['percentage']),
                binary=bool(args['binary']),
                normalize=args['normalize'],
                pos_label=args['pos_label']
            )
    
            html = to_html.card(to_html.fig(fig), title=self.title, subtitle=self.subtitle)
            if add_header:
                return to_html.add_header(html)
            return html