Source code for xaicompare.adapters.explainers.explainer_base

# xaicompare/adapters/explainer_base.py
from abc import ABC, abstractmethod
from typing import Any, Dict, Iterable, List, Sequence, Tuple, Union, Optional

import numpy as np


[docs] class ExplainerAdapter(ABC): """ Base class that standardizes how different explainers are called and what they return. Concrete implementations (e.g., SHAP Tree for XGBoost/LightGBM, SHAP Kernel for generic models, LIME-Text, etc.) should subclass this. Contract: - global_importance(X, rows_limit) -> (mean_abs, feature_names) * mean_abs: 1D np.ndarray of length n_features (mean absolute importance) * feature_names: List[str] of length n_features (ordering aligns with mean_abs) - local_explanations(X_row) -> 1D np.ndarray of length n_features (signed values) * X_row represents a single sample (shape (1, ...)); caller may pass a slice X[i:i+1] """ def __init__(self, model_adapter: Any, config: Optional[Dict[str, Any]] = None) -> None: """ Parameters ---------- model_adapter : Any A model wrapper exposing at least: - predict(X), predict_proba(X) (optional) - feature_names() -> List[str] - class_names() -> List[str] - is_sparse_input() -> bool (optional, defaults False) config : dict, optional Free-form configuration for the concrete explainer (batch_size, background, etc.). """ self.m = model_adapter self.config = config or {} # Required methods
[docs] @abstractmethod def limitation_text(self) -> str: raise NotImplementedError
[docs] @abstractmethod def global_importance(self, x, rows_limit: int = 200,) -> Tuple[np.ndarray, List[str]]: """ Compute a global importance estimate (typically mean ``|contribution|``) in a memory-safe way across up to `rows_limit` rows of X. Returns ------- mean_abs : np.ndarray 1D array of length n_features with mean absolute importance per feature. feature_names : List[str] The feature names in the same order as 'mean_abs'. """ raise NotImplementedError
[docs] @abstractmethod def local_explanations(self, x_row) -> np.ndarray: """ Explain a single row. Should return a vector of signed contributions whose length matches the feature space (n_features). Notes ----- - Implementations may aggregate across classes if multi-class (e.g. sum over classes). - If there is a bias term, do NOT return it here; only per-feature values. """ raise NotImplementedError
# ---------- Optional methods ----------
[docs] def name(self) -> str: """Human-readable name of the explainer.""" return self.__class__.__name__