Source code for xailib.xailib_tabular

"""
Tabular data explainability classes for XAI-Lib.

This module provides base classes for explaining predictions on tabular
(structured) data. It extends the base :class:`~xailib.xailib_base.Explainer`
and :class:`~xailib.xailib_base.Explanation` classes with tabular-specific
functionality, including interactive feature importance visualization.

Tabular data explanations are commonly used for:
    - Understanding feature contributions to predictions
    - Generating human-readable decision rules
    - Identifying similar and contrasting examples
    - Creating counterfactual explanations

Classes:
    TabularExplanation: Base class for tabular data explanations.
    TabularExplainer: Base class for tabular data explainers.

Example:
    Using LIME for tabular explanation::

        from xailib.explainers.lime_explainer import LimeXAITabularExplainer
        from xailib.models.sklearn_classifier_wrapper import sklearn_classifier_wrapper

        # Wrap your model
        bb = sklearn_classifier_wrapper(your_sklearn_model)

        # Create and fit explainer
        explainer = LimeXAITabularExplainer(bb)
        explainer.fit(df, 'target_column', config={})

        # Generate explanation
        explanation = explainer.explain(instance)
        explanation.plot_features_importance()

See Also:
    :mod:`xailib.explainers.lime_explainer`: LIME implementation for tabular data.
    :mod:`xailib.explainers.shap_explainer_tab`: SHAP implementation for tabular data.
    :mod:`xailib.explainers.lore_explainer`: LORE implementation for tabular data.
"""

from abc import abstractmethod
from xailib.xailib_base import Explainer, Explanation
import pandas as pd
import numpy as np

import altair as alt
from altair import expr
from IPython.display import HTML


[docs] class TabularExplanation(Explanation): """ Abstract base class for tabular data explanations. This class extends the base :class:`~xailib.xailib_base.Explanation` class with functionality specific to tabular (structured) data, including interactive visualization of feature importance using Altair charts. Subclasses should implement the abstract methods to provide access to different types of explanation information (feature importance, rules, exemplars, etc.). Attributes: Defined by subclasses. Common attributes include the raw explanation object from the underlying library. See Also: :class:`xailib.explainers.lime_explainer.LimeXAITabularExplanation`: LIME explanation. :class:`xailib.explainers.shap_explainer_tab.ShapXAITabularExplanation`: SHAP explanation. :class:`xailib.explainers.lore_explainer.LoreTabularExplanation`: LORE explanation. """ def __init__(self): """Initialize the TabularExplanation base class.""" super().__init__()
[docs] @abstractmethod def getFeaturesImportance(self): """ Get feature importance values for the explained instance. Returns: Feature importance as a list of tuples, numpy array, or pandas DataFrame. The exact format depends on the explanation method. Returns None if feature importance is not available. """ pass
[docs] @abstractmethod def getExemplars(self): """ Get exemplar instances similar to the explained instance. Returns: Exemplar instances with the same prediction, or None if not supported by this explanation method. """ pass
[docs] @abstractmethod def getCounterExemplars(self): """ Get counter-exemplar instances with different predictions. Returns: Counter-exemplar instances, or None if not supported by this explanation method. """ pass
[docs] @abstractmethod def getRules(self): """ Get decision rules explaining the prediction. Returns: Decision rules as a dictionary or list, or None if not supported by this explanation method. """ pass
[docs] @abstractmethod def getCounterfactualRules(self): """ Get counterfactual rules for alternative outcomes. Returns: Counterfactual rules describing how to change the prediction, or None if not supported by this explanation method. """ pass
[docs] def plot_features_importance_from(self, dataToPlot: pd.DataFrame, fontDimension=10): """ Create an interactive feature importance visualization using Altair. This method generates an interactive bar chart showing feature importance values with a slider to filter features by importance threshold. Features are color-coded by their importance value (positive vs negative). Args: dataToPlot (pd.DataFrame): DataFrame containing feature importance data with columns: - 'name': Feature names (string) - 'value': Importance values (float) fontDimension (int, optional): Base font size for the chart. Defaults to 10. Returns: None. Displays the interactive chart using IPython display. Note: This method is intended to be called within a Jupyter notebook environment for proper rendering of the interactive chart. Example: >>> import pandas as pd >>> data = pd.DataFrame({ ... 'name': ['feature1', 'feature2', 'feature3'], ... 'value': [0.5, -0.3, 0.1] ... }) >>> explanation.plot_features_importance_from(data, fontDimension=12) """ fontSize = fontDimension step = fontSize * 1.5 maxValue = dataToPlot['value'].max() minValue = dataToPlot['value'].min() maxRange = max(abs(maxValue), abs(minValue)) # selector slider = alt.binding_range(min=0, max=maxRange, step=maxRange / 50, name='Importance cutoff value (±) ') selector = alt.selection_single(name="Cutter", fields=['cutoff'], bind=slider, init={'cutoff': 0.0}) # charting bar = alt.Chart( dataToPlot ).transform_filter( (alt.datum.value > selector.cutoff) | (alt.datum.value < -(selector.cutoff)) ).mark_bar().encode( x=alt.X('value:Q', title=None), y=alt.Y('name:N', title=None, sort=alt.EncodingSortField(field='value', op='mean', order='descending')), color=alt.Color( 'value:Q', scale=alt.Scale( scheme='blueorange', domain=[-maxRange, maxRange], domainMid=0, ), legend=None ), tooltip=[ alt.Tooltip(field='name', type='nominal', title='Feature'), alt.Tooltip(field='value', type='quantitative', title='Importance') ] ).add_selection( selector ) line = alt.Chart(pd.DataFrame({'x': [0]})).mark_rule().encode(x='x') # Legend Chart legendData = np.arange(-maxRange, maxRange, maxRange / 100).tolist() legendDF = pd.DataFrame({'xValue': legendData}) legendChart = alt.Chart( legendDF ).mark_rule( strokeWidth=3 ).encode( x=alt.X( field='xValue', type='quantitative', title='Select a cutoff range for Feature Importance values ', axis=alt.Axis(orient='top', titleFontSize=fontSize) ), color=alt.Color( 'xValue:Q', scale=alt.Scale( scheme='redyellowblue', domain=[-maxRange, maxRange], domainMid=0, ), legend=None ) ) cuttedChart = alt.Chart( pd.DataFrame({'y': [0], 'x': [-0.5], 'x2': [0.5]}) ).transform_calculate( x_min=-(selector.cutoff), x_max=selector.cutoff ).mark_rect( color='black', height=20, tooltip=True, opacity=0.4 ).encode( x='x_min:Q', x2='x_max:Q', y=alt.Y(field="y", type="quantitative", axis=None) ).add_selection( selector ) legend = (legendChart + cuttedChart).properties( height=20 ) chart = (legend & (bar + line)).properties( padding=10, ).configure_axis( labelLimit=step * 15, labelFontSize=fontSize ) # HTML injection using IPython.display display(HTML(""" <style> .vega-bind { position: absolute; left: 0px; top: 0px; background-color:#eee; padding:10px; font-size:%spx; } .chart-wrapper{ padding-top: 70px; } </style> """ % (fontSize) )) display(chart)
[docs] class TabularExplainer(Explainer): """ Abstract base class for tabular data explainers. This class extends the base :class:`~xailib.xailib_base.Explainer` class with functionality specific to tabular (structured) data. Tabular explainers work with pandas DataFrames and provide explanations for predictions on structured data. Subclasses implement specific explanation methods such as LIME, SHAP, or LORE for tabular data. Attributes: Defined by subclasses. Common attributes include the black-box model wrapper and configuration parameters. See Also: :class:`xailib.explainers.lime_explainer.LimeXAITabularExplainer`: LIME implementation. :class:`xailib.explainers.shap_explainer_tab.ShapXAITabularExplainer`: SHAP implementation. :class:`xailib.explainers.lore_explainer.LoreTabularExplainer`: LORE implementation. """ def __init__(self): """Initialize the TabularExplainer base class.""" super().__init__()
[docs] @abstractmethod def fit(self, X, y, config): """ Fit the explainer to the tabular training data. Args: X (pd.DataFrame): Training data as a pandas DataFrame. y: Target column name (str) or target values. config (dict): Configuration dictionary with method-specific parameters. Common keys include: - 'feature_selection': Feature selection method - 'discretize_continuous': Whether to discretize continuous features - 'sample_around_instance': Sampling strategy - Additional method-specific parameters Returns: None. The explainer is fitted in-place. """ pass
[docs] @abstractmethod def explain(self, b, x) -> TabularExplanation: """ Generate an explanation for a tabular data instance. Args: b: Black-box model or prediction function (depends on implementation). x: Instance to explain as a numpy array or pandas Series. Returns: TabularExplanation: An explanation object containing feature importance, rules, or other explanation information. """ pass