explainiverse 0.1.1a1__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- explainiverse/__init__.py +45 -1
- explainiverse/adapters/__init__.py +9 -0
- explainiverse/adapters/base_adapter.py +25 -25
- explainiverse/adapters/sklearn_adapter.py +32 -32
- explainiverse/core/__init__.py +22 -0
- explainiverse/core/explainer.py +31 -31
- explainiverse/core/explanation.py +24 -24
- explainiverse/core/registry.py +563 -0
- explainiverse/engine/__init__.py +8 -0
- explainiverse/engine/suite.py +142 -142
- explainiverse/evaluation/__init__.py +8 -0
- explainiverse/evaluation/metrics.py +232 -232
- explainiverse/explainers/__init__.py +41 -0
- explainiverse/explainers/attribution/__init__.py +10 -0
- explainiverse/explainers/attribution/lime_wrapper.py +90 -63
- explainiverse/explainers/attribution/shap_wrapper.py +89 -66
- explainiverse/explainers/attribution/treeshap_wrapper.py +434 -0
- explainiverse/explainers/counterfactual/__init__.py +8 -0
- explainiverse/explainers/counterfactual/dice_wrapper.py +302 -0
- explainiverse/explainers/global_explainers/__init__.py +23 -0
- explainiverse/explainers/global_explainers/ale.py +191 -0
- explainiverse/explainers/global_explainers/partial_dependence.py +192 -0
- explainiverse/explainers/global_explainers/permutation_importance.py +123 -0
- explainiverse/explainers/global_explainers/sage.py +164 -0
- explainiverse/explainers/rule_based/__init__.py +8 -0
- explainiverse/explainers/rule_based/anchors_wrapper.py +350 -0
- explainiverse-0.2.1.dist-info/METADATA +264 -0
- explainiverse-0.2.1.dist-info/RECORD +30 -0
- explainiverse-0.1.1a1.dist-info/METADATA +0 -128
- explainiverse-0.1.1a1.dist-info/RECORD +0 -19
- {explainiverse-0.1.1a1.dist-info → explainiverse-0.2.1.dist-info}/LICENSE +0 -0
- {explainiverse-0.1.1a1.dist-info → explainiverse-0.2.1.dist-info}/WHEEL +0 -0
explainiverse/__init__.py
CHANGED
|
@@ -1 +1,45 @@
|
|
|
1
|
-
#
|
|
1
|
+
# src/explainiverse/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Explainiverse - A unified, extensible explainability framework.
|
|
4
|
+
|
|
5
|
+
Supports multiple XAI methods including LIME, SHAP, Anchors, Counterfactuals,
|
|
6
|
+
Permutation Importance, PDP, ALE, and SAGE through a consistent interface.
|
|
7
|
+
|
|
8
|
+
Quick Start:
|
|
9
|
+
from explainiverse import default_registry
|
|
10
|
+
|
|
11
|
+
# List available explainers
|
|
12
|
+
print(default_registry.list_explainers())
|
|
13
|
+
|
|
14
|
+
# Create an explainer
|
|
15
|
+
explainer = default_registry.create("lime", model=adapter, training_data=X, ...)
|
|
16
|
+
explanation = explainer.explain(instance)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from explainiverse.core.explainer import BaseExplainer
|
|
20
|
+
from explainiverse.core.explanation import Explanation
|
|
21
|
+
from explainiverse.core.registry import (
|
|
22
|
+
ExplainerRegistry,
|
|
23
|
+
ExplainerMeta,
|
|
24
|
+
default_registry,
|
|
25
|
+
get_default_registry,
|
|
26
|
+
)
|
|
27
|
+
from explainiverse.adapters.sklearn_adapter import SklearnAdapter
|
|
28
|
+
from explainiverse.engine.suite import ExplanationSuite
|
|
29
|
+
|
|
30
|
+
__version__ = "0.2.1"
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
# Core
|
|
34
|
+
"BaseExplainer",
|
|
35
|
+
"Explanation",
|
|
36
|
+
# Registry
|
|
37
|
+
"ExplainerRegistry",
|
|
38
|
+
"ExplainerMeta",
|
|
39
|
+
"default_registry",
|
|
40
|
+
"get_default_registry",
|
|
41
|
+
# Adapters
|
|
42
|
+
"SklearnAdapter",
|
|
43
|
+
# Engine
|
|
44
|
+
"ExplanationSuite",
|
|
45
|
+
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# src/explainiverse/adapters/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Model adapters - wrappers that provide a consistent interface for different ML frameworks.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from explainiverse.adapters.base_adapter import BaseModelAdapter
|
|
7
|
+
from explainiverse.adapters.sklearn_adapter import SklearnAdapter
|
|
8
|
+
|
|
9
|
+
__all__ = ["BaseModelAdapter", "SklearnAdapter"]
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# src/explainiverse/adapters/base_adapter.py
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
|
|
5
|
-
class BaseModelAdapter(ABC):
|
|
6
|
-
"""
|
|
7
|
-
Abstract base class for all model adapters.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
def __init__(self, model, feature_names=None):
|
|
11
|
-
self.model = model
|
|
12
|
-
self.feature_names = feature_names
|
|
13
|
-
|
|
14
|
-
@abstractmethod
|
|
15
|
-
def predict(self, data):
|
|
16
|
-
"""
|
|
17
|
-
Returns prediction probabilities or outputs in a standard format.
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
data: Input data (single instance or batch).
|
|
21
|
-
|
|
22
|
-
Returns:
|
|
23
|
-
List or NumPy array of prediction scores.
|
|
24
|
-
"""
|
|
25
|
-
pass
|
|
1
|
+
# src/explainiverse/adapters/base_adapter.py
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
class BaseModelAdapter(ABC):
|
|
6
|
+
"""
|
|
7
|
+
Abstract base class for all model adapters.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, model, feature_names=None):
|
|
11
|
+
self.model = model
|
|
12
|
+
self.feature_names = feature_names
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def predict(self, data):
|
|
16
|
+
"""
|
|
17
|
+
Returns prediction probabilities or outputs in a standard format.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
data: Input data (single instance or batch).
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
List or NumPy array of prediction scores.
|
|
24
|
+
"""
|
|
25
|
+
pass
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
# src/explainiverse/adapters/sklearn_adapter.py
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from .base_adapter import BaseModelAdapter
|
|
5
|
-
|
|
6
|
-
class SklearnAdapter(BaseModelAdapter):
|
|
7
|
-
"""
|
|
8
|
-
Adapter for Scikit-learn classifiers.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, model, feature_names=None, class_names=None):
|
|
12
|
-
super().__init__(model, feature_names)
|
|
13
|
-
self.class_names = class_names
|
|
14
|
-
|
|
15
|
-
def predict(self, data: np.ndarray) -> np.ndarray:
|
|
16
|
-
"""
|
|
17
|
-
Returns prediction probabilities.
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
data: A 2D numpy array of inputs.
|
|
21
|
-
|
|
22
|
-
Returns:
|
|
23
|
-
Array of shape (n_samples, n_classes).
|
|
24
|
-
"""
|
|
25
|
-
if hasattr(self.model, "predict_proba"):
|
|
26
|
-
return self.model.predict_proba(data)
|
|
27
|
-
else:
|
|
28
|
-
preds = self.model.predict(data)
|
|
29
|
-
if self.class_names:
|
|
30
|
-
return np.eye(len(self.class_names))[preds]
|
|
31
|
-
else:
|
|
32
|
-
return preds.reshape(-1, 1) # regression: raw outputs
|
|
1
|
+
# src/explainiverse/adapters/sklearn_adapter.py
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from .base_adapter import BaseModelAdapter
|
|
5
|
+
|
|
6
|
+
class SklearnAdapter(BaseModelAdapter):
|
|
7
|
+
"""
|
|
8
|
+
Adapter for Scikit-learn classifiers.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, model, feature_names=None, class_names=None):
|
|
12
|
+
super().__init__(model, feature_names)
|
|
13
|
+
self.class_names = class_names
|
|
14
|
+
|
|
15
|
+
def predict(self, data: np.ndarray) -> np.ndarray:
|
|
16
|
+
"""
|
|
17
|
+
Returns prediction probabilities.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
data: A 2D numpy array of inputs.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Array of shape (n_samples, n_classes).
|
|
24
|
+
"""
|
|
25
|
+
if hasattr(self.model, "predict_proba"):
|
|
26
|
+
return self.model.predict_proba(data)
|
|
27
|
+
else:
|
|
28
|
+
preds = self.model.predict(data)
|
|
29
|
+
if self.class_names:
|
|
30
|
+
return np.eye(len(self.class_names))[preds]
|
|
31
|
+
else:
|
|
32
|
+
return preds.reshape(-1, 1) # regression: raw outputs
|
explainiverse/core/__init__.py
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# src/explainiverse/core/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Explainiverse core components.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from explainiverse.core.explainer import BaseExplainer
|
|
7
|
+
from explainiverse.core.explanation import Explanation
|
|
8
|
+
from explainiverse.core.registry import (
|
|
9
|
+
ExplainerRegistry,
|
|
10
|
+
ExplainerMeta,
|
|
11
|
+
default_registry,
|
|
12
|
+
get_default_registry,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"BaseExplainer",
|
|
17
|
+
"Explanation",
|
|
18
|
+
"ExplainerRegistry",
|
|
19
|
+
"ExplainerMeta",
|
|
20
|
+
"default_registry",
|
|
21
|
+
"get_default_registry",
|
|
22
|
+
]
|
explainiverse/core/explainer.py
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# src/explainiverse/core/explainer.py
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
|
|
5
|
-
class BaseExplainer(ABC):
|
|
6
|
-
"""
|
|
7
|
-
Abstract base class for all explainers in Explainiverse.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
def __init__(self, model):
|
|
11
|
-
"""
|
|
12
|
-
Initialize with a model adapter or raw model.
|
|
13
|
-
|
|
14
|
-
Args:
|
|
15
|
-
model: A wrapped ML model with a standardized `predict` method.
|
|
16
|
-
"""
|
|
17
|
-
self.model = model
|
|
18
|
-
|
|
19
|
-
@abstractmethod
|
|
20
|
-
def explain(self, instance, **kwargs):
|
|
21
|
-
"""
|
|
22
|
-
Generate an explanation for a single input instance.
|
|
23
|
-
|
|
24
|
-
Args:
|
|
25
|
-
instance: The input to explain (e.g., feature vector, image, text).
|
|
26
|
-
**kwargs: Optional method-specific parameters.
|
|
27
|
-
|
|
28
|
-
Returns:
|
|
29
|
-
An Explanation object or dict.
|
|
30
|
-
"""
|
|
31
|
-
pass
|
|
1
|
+
# src/explainiverse/core/explainer.py
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
class BaseExplainer(ABC):
|
|
6
|
+
"""
|
|
7
|
+
Abstract base class for all explainers in Explainiverse.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, model):
|
|
11
|
+
"""
|
|
12
|
+
Initialize with a model adapter or raw model.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
model: A wrapped ML model with a standardized `predict` method.
|
|
16
|
+
"""
|
|
17
|
+
self.model = model
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def explain(self, instance, **kwargs):
|
|
21
|
+
"""
|
|
22
|
+
Generate an explanation for a single input instance.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
instance: The input to explain (e.g., feature vector, image, text).
|
|
26
|
+
**kwargs: Optional method-specific parameters.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
An Explanation object or dict.
|
|
30
|
+
"""
|
|
31
|
+
pass
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
# src/explainiverse/core/explanation.py
|
|
2
|
-
|
|
3
|
-
class Explanation:
|
|
4
|
-
"""
|
|
5
|
-
Unified container for explanation results.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
def __init__(self, explainer_name: str, target_class: str, explanation_data: dict):
|
|
9
|
-
self.explainer_name = explainer_name
|
|
10
|
-
self.target_class = target_class
|
|
11
|
-
self.explanation_data = explanation_data # e.g., {'feature_attributions': {...}}
|
|
12
|
-
|
|
13
|
-
def __repr__(self):
|
|
14
|
-
return (f"Explanation(explainer='{self.explainer_name}', "
|
|
15
|
-
f"target='{self.target_class}', "
|
|
16
|
-
f"keys={list(self.explanation_data.keys())})")
|
|
17
|
-
|
|
18
|
-
def plot(self, type='bar'):
|
|
19
|
-
"""
|
|
20
|
-
Visualizes the explanation.
|
|
21
|
-
This will later integrate with a proper visualization backend.
|
|
22
|
-
"""
|
|
23
|
-
print(f"[plot: {type}] Plotting explanation for {self.target_class} "
|
|
24
|
-
f"from {self.explainer_name}.")
|
|
1
|
+
# src/explainiverse/core/explanation.py
|
|
2
|
+
|
|
3
|
+
class Explanation:
|
|
4
|
+
"""
|
|
5
|
+
Unified container for explanation results.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
def __init__(self, explainer_name: str, target_class: str, explanation_data: dict):
|
|
9
|
+
self.explainer_name = explainer_name
|
|
10
|
+
self.target_class = target_class
|
|
11
|
+
self.explanation_data = explanation_data # e.g., {'feature_attributions': {...}}
|
|
12
|
+
|
|
13
|
+
def __repr__(self):
|
|
14
|
+
return (f"Explanation(explainer='{self.explainer_name}', "
|
|
15
|
+
f"target='{self.target_class}', "
|
|
16
|
+
f"keys={list(self.explanation_data.keys())})")
|
|
17
|
+
|
|
18
|
+
def plot(self, type='bar'):
|
|
19
|
+
"""
|
|
20
|
+
Visualizes the explanation.
|
|
21
|
+
This will later integrate with a proper visualization backend.
|
|
22
|
+
"""
|
|
23
|
+
print(f"[plot: {type}] Plotting explanation for {self.target_class} "
|
|
24
|
+
f"from {self.explainer_name}.")
|