effector is an eXplainable AI package for tabular data. It:
- explains any black-box model with global and regional effects: what each feature does, and where the average hides something
- produces a report in one line:
effector.explain(X, model)fits, ranks the features, hunts for subregions, and writes a single self-contained HTML page - offers an interactive API when you want the controls: five engines (PDP, d-PDP, ALE, RHALE, SHAP-DP), one verb set
- is model agnostic: any callable
numpy β numpyworks, and adapters wrap scikit-learn, PyTorch, classifiers and DataFrame pipelines - is fast, for both global and regional methods: everything after the fit is free
π Documentation | π Quickstart | π§ API | π Examples
Installation
Effector requires Python 3.10+:
pip install effector
This installs a lightweight core (numpy, scipy, matplotlib, tqdm) that covers PDP, ALE, RHALE and their regional effects.
ShapDP needs the heavier shap/shapiq backends (which pull in numba, scikit-learn, pandas, ...). Install them only if you use that method:
pip install effector[shap]
Quickstart
(a) The inputs
A dataset as a numpy array, a model as a numpy β numpy callable, and, optionally, a schema so the explanation speaks your vocabulary:
import effector
from sklearn.ensemble import HistGradientBoostingRegressor
data = effector.datasets.BikeSharing() # standardized numpy arrays
model = HistGradientBoostingRegressor(random_state=21).fit(data.x_train, data.y_train)
predict = effector.adapters.from_sklearn(model) # a plain numpy -> numpy callable
schema = effector.Schema(
feature_names=data.feature_names,
feature_types=[
"nominal", "nominal", "ordinal", "ordinal", "nominal", "nominal",
"nominal", "ordinal", "continuous", "continuous", "continuous",
],
category_names=[
["winter", "spring", "summer", "fall"],
["2011", "2012"],
["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
None,
["no", "yes"],
["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
["no", "yes"],
["clear", "mist", "light rain/snow", "heavy rain"],
None, None, None,
],
scale_x_list=[
{"mean": data.x_train_mu[i], "std": data.x_train_std[i]}
for i in range(data.x_train.shape[1])
],
scale_y={"mean": data.y_train_mu, "std": data.y_train_std},
target_name="bike-rentals",
)
π In depth: the input layer; pandas, sklearn, torch, classifiers, feature types, units.
(b) The one-liner
report = effector.explain(
data.x_train, predict, y=data.y_train, schema=schema, nof_instances=5000
)
It fits once, ranks the features, hunts for subregions where the average is hiding something, keeps only the splits that pay for themselves, and opens with the one number worth having:
[effector] global effects (GAM) -> 72.3% of the model's variance
regional effects (CALM) -> 92.0%
The result is a Report, a value you can export or print:
report.to_html("report.html") # a single self-contained page; mail it, commit it
report.show() # the same story, as terminal tables
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
PDP report Β· target: bike-rentals
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
DATA & MODEL
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
instances 5,000
features 11 Β· 5 nominal Β· 3 ordinal Β· 3 continuous
model output mean 188 Β· std 176 Β· range [-19.5, 948]
model RΒ² 0.960 (on this subsample)
EXPLAINED VARIANCE
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
step split on solo ΞRΒ² RΒ² heter
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
GAM (all features global) β β 72.3% β
+ hr temp, workingday, yr +18.3% +18.3% 90.6% 0.47 β 0.26
+ temp hr, hum +2.4% +1.4% 92.0% 0.22 β 0.19
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FINAL 92.0%
REJECTED SPLITS min gain 1.0%
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
feature split on solo ΞRΒ² reason
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β yr hr, workingday +2.7% -0.8% redundant
β hum hr, temp +2.2% +0.2% below threshold
β weekday hr, temp, yr +0.4% +0.2% below threshold
β workingday hr, yr +6.2% -4.8% redundant
β redundant: it would explain variance on its own (see solo),
but the accepted splits already account for it.
FEATURES ranked, in the selected snapshot
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
feature importance heter #regions
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
hr 0.7273 ββββββββββββββββββ 0.2608 4
yr 0.2271 ββββββ 0.2088 1
temp 0.2098 βββββ 0.1874 4
hum 0.0932 ββ 0.1221 1
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
the features above carry 82% of the total importance mass
(the accepted partition trees follow)
π In depth: the report; the explained variance ledger, the triage plane, the regional analysis, every knob of explain(...).
(c) The interactive API
The same engine, as a live handle you query as you go:
pdp = effector.PDP(data.x_train, predict, schema=schema, nof_instances=5000)
pdp.plot("hr") # the global effect, ICE curves behind it
pdp.heter_score("hr") # 0.47: the average hides a lot
partition = pdp.find_regions("hr") # where is it hiding it?
partition.show()
Feature 3 - Full partition tree:
π³ Full Tree Structure:
βββββββββββββββββββββββ
hr πΉ [id: 0 | heter: 0.47 | inst: 5000 | w: 1.00]
workingday = no πΉ [id: 1 | heter: 0.33 | inst: 1545 | w: 0.31]
temp < 6.86 πΉ [id: 2 | heter: 0.22 | inst: 778 | w: 0.16]
temp β₯ 6.86 πΉ [id: 3 | heter: 0.26 | inst: 767 | w: 0.15]
workingday = yes πΉ [id: 4 | heter: 0.34 | inst: 3455 | w: 0.69]
yr = 2011 πΉ [id: 5 | heter: 0.23 | inst: 1720 | w: 0.34]
yr = 2012 πΉ [id: 6 | heter: 0.31 | inst: 1735 | w: 0.35]
--------------------------------------------------
Feature 3 - Statistics per tree level:
π³ Tree Summary:
βββββββββββββββββ
Level 0πΉheter: 0.47
Level 1πΉheter: 0.34 | π»0.13 (28.12%)
Level 2πΉheter: 0.26 | π»0.08 (22.91%)
The effect of hr depends on workingday (commute peaks vs a midday plateau), and within each branch on temp and yr. Plot the effect inside a region:
partition.plot(2) # hr, on non-working days, in the cold
![]() |
![]() |
Every verb answers one question:
| verb | question it answers |
|---|---|
.plot(f) |
what does feature f do? |
.eval(f, xs) |
β¦as numbers, on my grid |
.importance(f) |
how much does f move the output? |
.heter_score(f) |
is the average hiding something? |
.find_regions(f) |
where is it hiding it? |
.select_regions() |
which splits actually earn their keep? |
.fit(features, **cfg) |
(optional) tune the method first |
π In depth: the interactive API; construct and fit, customizing .fit(), plot, eval, scores, regions.
Documentation map
Start here:
- What are global and regional effects: the concepts
effector's API: the whole API in 3 minutes- (a) The input layer: numpy, models, adapters, the schema
- (b)
effector's report: the one-liner,.show(), and the HTML page - (c) The interactive API: the five engines, global and regional effects
Going deeper:
- The mental model: the thinking behind the API; one engine, values not state, two entrances
- Methods: the math reference: how each method defines the effect, its heterogeneity, and the two scalars
- The design contract: the rules the API is built on, one breath each
- Efficiency of global and regional methods: count the model calls
Supported Methods
Every method computes global effects, and regional effects via .find_regions(feature):
| Method | Class | Reference | ML model | Speed |
|---|---|---|---|---|
| PDP | PDP |
Friedman, 2001 | any | fast for a small dataset |
| d-PDP | DerPDP |
Goldstein et al., 2013 | differentiable | fast for a small dataset |
| ALE | ALE |
Apley & Zhu, 2020 | any | fast |
| RHALE | RHALE |
Gkolemis et al., 2023 | differentiable | very fast |
| SHAP-DP | ShapDP |
Lundberg & Lee, 2017 | any | fast for a small dataset and a light model |
Choosing a method
Three questions decide: is the dataset small (N < 10K) or large? Is the model light (< 0.1s per call) or heavy? Is it differentiable or not?
| your case | use |
|---|---|
| small + light | any: PDP, ALE, ShapDP; plus RHALE, DerPDP if differentiable |
| small + heavy | PDP, ALE; plus RHALE, DerPDP if differentiable |
| large + differentiable | RHALE |
| large + non-differentiable | ALE |
Citation
If you use effector, please cite it:
@misc{gkolemis2024effector,
title={effector: A Python package for regional explanations},
author={Vasilis Gkolemis et al.},
year={2024},
eprint={2404.02629},
archivePrefix={arXiv},
primaryClass={cs.LG}
}
Spotlight on effector
π Featured Publications
- Gkolemis, Vasilis, et al.
"Fast and Accurate Regional Effect Plots for Automated Tabular Data Analysis."
Proceedings of the VLDB Endowment | ISSN 2150-8097
π€ Talks & Presentations
- LMU-IML Group Talk
Slides & Materials | LMU-IML Research - AIDAPT Plenary Meeting
Deep dive into effector - XAI World Conference 2024
Poster | Paper
π Adoption & Collaborations
- AIDAPT Project
Leveragingeffectorfor explainable AI solutions.
π Additional Resources
-
Medium Post
Effector: An eXplainability Library for Global and Regional Effects -
Courses & Lists:
IML Course @ LMU
Awesome ML Interpretability
Awesome XAI
Best of ML Python
π Related Publications
Papers that have inspired effector:
-
REPID: Regional Effects in Predictive Models
Herbinger et al., 2022 - Link -
Decomposing Global Feature Effects Based on Feature Interactions
Herbinger et al., 2023 - Link -
RHALE: Robust Heterogeneity-Aware Effects
Gkolemis Vasilis et al., 2023 - Link -
DALE: Decomposing Global Feature Effects
Gkolemis Vasilis et al., 2023 - Link -
Greedy Function Approximation: A Gradient Boosting Machine
Friedman, 2001 - Link -
Visualizing Predictor Effects in Black-Box Models
Apley, 2016 - Link -
SHAP: A Unified Approach to Model Interpretation
Lundberg & Lee, 2017 - Link -
Regionally Additive Models: Explainable-by-design models minimizing feature interactions
Gkolemis Vasilis et al., 2023 - Link
License
effector is released under the MIT License.




