Skip to content

Api regional

Summary

All regional effect methods have a similar interface and workflow:

  1. create an instance of the regional effect method you want to use
  2. (optional) .fit() to customize the method
  3. .summary() to print the partition tree found for each feature
  4. .plot() to plot the regional effect of a feature at a specific node
  5. .eval() to evaluate the regional effect of a feature at a specific node at a specific grid of points

Usage

# set up the input
X = ... # input data
predict = ... # model to be explained
jacobian = ... # jacobian of the model
  1. Create an instance of the regional effect method you want to use:

    effector.RegionalPDP(data=X, model=predict)
    
    effector.RegionalRHALE(data=X, model=predict, model_jac=jacobian)
    
    effector.RegionalShapDP(data=X, model=predict)
    
    effector.RegionalALE(data=X, model=predict)
    
    effector.DerPDP(data=X, model=predict, model_jac=jacobian)
    
  2. Customize the regional effect method (optional):

    .fit(features, **method_specific_args)

    This is the place for customization

    The .fit() step can be omitted if you are ok with the default settings; you can directly call the .summary(), .plot(), or .eval() methods. However, if you want more control over the fitting process, you can pass additional arguments to the .fit() method. Check the Usage section below and the method-specific documentation for more information.

    Usage
    # customize the space partitioning algorithm
    space_partitioner = effector.space_partitioning.Best(
        min_heterogeneity_decrease_pcg=0.3, # percentage drop threshold (default: 0.1),
        max_split_levels=1 # maximum number of split levels (default: 2)
    )
    r_method.fit(
        features=[0, 1], # list of features to be analyzed
        space_partitioner=space_partitioner # space partitioning algorithm (default: effector.space_partitioning.Best)
    )
    
  3. Print the partition tree found for each feature in features:

    .summary(features)

    Usage
    features = [...] # list of features to be analyzed
    r_method.summary(features)
    
    Example Output
    Feature 3 - Full partition tree:
    🌳 Full Tree Structure:
    ───────────────────────
    
    hr 🔹 [id: 0 | heter: 0.43 | inst: 3476 | w: 1.00]
        workingday = 0.00 🔹 [id: 1 | heter: 0.36 | inst: 1129 | w: 0.32]
            temp ≤ 6.50 🔹 [id: 3 | heter: 0.17 | inst: 568 | w: 0.16]
            temp > 6.50 🔹 [id: 4 | heter: 0.21 | inst: 561 | w: 0.16]
        workingday ≠ 0.00 🔹 [id: 2 | heter: 0.28 | inst: 2347 | w: 0.68]
            temp ≤ 6.50 🔹 [id: 5 | heter: 0.19 | inst: 953 | w: 0.27]
            temp > 6.50 🔹 [id: 6 | heter: 0.20 | inst: 1394 | w: 0.40]
    --------------------------------------------------
    Feature 3 - Statistics per tree level:
    🌳 Tree Summary:
    ─────────────────
    Level 0🔹heter: 0.43
        Level 1🔹heter: 0.31 | 🔻0.12 (28.15%)
            Level 2🔹heter: 0.19 | 🔻0.11 (37.10%)
    
  4. Plot the regional effect of a feature at a specific node:

    .plot(feature, node_idx)

    Usage
    feature = ...
    node_idx = ...
    r_method.plot(feature, node_idx, **plot_specific_args)
    
    Output
    node_idx=1: \(x_1\) when \(x_2 \leq 0\) node_idx=2: \(x_1\) when \(x_2 > 0\)
    r_method.plot(0, 1) r_method.plot(0, 2)
    Alt text Alt text
    node_idx=1: \(x_1\) when \(x_2 \leq 0\) node_idx=2: \(x_1\) when \(x_2 > 0\)
    r_method.plot(0, 1) r_method.plot(0, 2)
    Alt text Alt text
    node_idx=1: \(x_1\) when \(x_2 \leq 0\) node_idx=2: \(x_1\) when \(x_2 > 0\)
    r_method.plot(0, 1) r_method.plot(0, 2)
    Alt text Alt text
    node_idx=1: \(x_1\) when \(x_2 \leq 0\) node_idx=2: \(x_1\) when \(x_2 > 0\)
    r_method.plot(0, 1) r_method.plot(0, 2)
    Alt text Alt text
    node_idx=1: \(x_1\) when \(x_2 \leq 0\) node_idx=2: \(x_1\) when \(x_2 > 0\)
    r_method.plot(0, 1) r_method.plot(0, 2)
    Alt text Alt text
  5. Evaluate the regional effect of a feature at a specific node at a specific grid of points:

    .eval(feature, node_idx, xs)

    Usage
    # Example input
    feature = ... # feature to be analyzed
    node_idx = ... # node index
    xs = ... # grid of points to evaluate the regional effect, e.g., np.linspace(0, 1, 100)
    
    y, het = r_method.eval(feature, node_idx, xs, heterogeneity=True)
    

API

Constructor for the RegionalEffect class.

Methods:

Name Description
eval

👉 Evaluate the regional effect for a given feature and node.

summary

👉 Summarize the partition tree for the selected features.

Source code in effector/regional_effect.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def __init__(
    self,
    method_name: str,
    data,
    model: Callable,
    model_jac: Optional[Callable] = None,
    *,
    data_effect: Optional[np.ndarray] = None,
    nof_instances: Union[int, str] = 10_000,
    axis_limits: Optional[np.ndarray] = None,
    schema: Optional[Union[ingestion.Schema, dict]] = None,
    random_state: Optional[int] = 21,
) -> None:
    """
    Constructor for the RegionalEffect class.
    """
    self.method_name = method_name.lower()
    self.random_state = random_state

    # the border crossing (R10): validate numpy `data`, resolve/auto-infer
    # metadata; `model`/`model_jac` pass through as given (numpy-only). Type
    # inference runs on the full data, before subsampling.
    ing = ingestion.ingest(data, model, model_jac, schema=schema)
    data = ing.data
    self.model = ing.model
    self.model_jac = ing.model_jac
    self.feature_metadata: ingestion.FeatureMetadata = ing.meta

    self.dim = data.shape[1]

    # shared preprocessing: filter to axis_limits (or infer them), then
    # subsample nof_instances (helpers.prep_data)
    data, data_effect, axis_limits, self.nof_instances, self.indices = (
        helpers.prep_data(
            data, axis_limits, nof_instances, data_effect, random_state
        )
    )
    self.axis_limits: np.ndarray = axis_limits

    # store the data
    self.data: np.ndarray = data
    self.data_effect: Optional[np.ndarray] = data_effect

    # flat mirrors of the resolved metadata
    self.feature_names: list = list(ing.meta.feature_names)
    self.feature_types: list = list(ing.meta.feature_types)
    self.cat_limit: int = ing.meta.cat_limit
    self.target_name: str = ing.meta.target_name
    self.scale_x_list: Optional[list] = ing.meta.scale_x_list
    self.scale_y: Optional[dict] = ing.meta.scale_y

    # state variables
    self.is_fitted: np.ndarray = np.ones([self.dim]) < 0

    # parameters used when fitting the regional effect: what detected the
    # subregions, and what eval/plot must refit the node objects with —
    # written out explicitly by each subclass's fit (no locals(); B1)
    self.kwargs_subregion_detection: typing.Dict = {}
    self.kwargs_fitting: typing.Dict = {}

    # dictionary with all the information required for plotting or evaluating the regional effects
    self.partitioners: typing.Dict[str, Best] = {}
    self.tree: typing.Dict[str, Tree] = {}

    # the ONE global effect object (regional ≡ masked global): constructed
    # once, fitted per feature; the split search AND the node eval/plot are
    # its own masked summaries — pure numpy over its cached local effects
    self._global_fe = None

eval(feature, node_idx, xs, heterogeneity=False, centering=None)

👉 Evaluate the regional effect for a given feature and node.

The heterogeneity argument changes the return value of the function.

  • If heterogeneity=False, the function returns y
  • If heterogeneity=True, the function returns a tuple (y, h) where h is the heterogeneity curve (eval_heter)

Parameters:

Name Type Description Default
feature int

index of the feature

required
node_idx int

index of the node

required
xs ndarray

horizontal grid of points to evaluate on

required
heterogeneity bool

whether to also return the heterogeneity curve

  • if heterogeneity=False, the function returns y, a numpy array of the mean effect at grid points xs
  • If heterogeneity=True, the function returns (y, h) where h is the heterogeneity curve at grid points xs
False
centering Union[None, bool, str]

whether to center the regional effect. The following options are available:

  • If centering is None, the underlying method's class default is used (R3)
  • If centering is False, the regional effect is not centered
  • If centering is True or zero_integral, the regional effect is centered around the y axis.
  • If centering is zero_start, the regional effect starts from y=0.
None

Returns:

Type Description
Union[ndarray, Tuple[ndarray, ndarray]]

the mean effect y, if heterogeneity=False (default) or a tuple (y, h) otherwise

Source code in effector/regional_effect.py
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
def eval(
    self,
    feature: int,
    node_idx: int,
    xs: np.ndarray,
    heterogeneity: bool = False,
    centering: Union[None, bool, str] = None,
) -> Union[np.ndarray, Tuple[np.ndarray, np.ndarray]]:
    """
    :point_right: Evaluate the regional effect for a given feature and node.

    !!! note "The `heterogeneity` argument changes the return value of the function."

        - If `heterogeneity=False`, the function returns `y`
        - If `heterogeneity=True`, the function returns a tuple `(y, h)`
          where `h` is the heterogeneity curve (`eval_heter`)

    Args:
        feature: index of the feature
        node_idx: index of the node
        xs: horizontal grid of points to evaluate on
        heterogeneity: whether to also return the heterogeneity curve

              - if `heterogeneity=False`, the function returns `y`, a numpy array of the mean effect at grid points `xs`
              - If `heterogeneity=True`, the function returns `(y, h)` where `h` is the heterogeneity curve at grid points `xs`

        centering: whether to center the regional effect. The following options are available:

            - If `centering` is `None`, the underlying method's class default is used (R3)
            - If `centering` is `False`, the regional effect is not centered
            - If `centering` is `True` or `zero_integral`, the regional effect is centered around the `y` axis.
            - If `centering` is `zero_start`, the regional effect starts from `y=0`.

    Returns:
        the mean effect `y`, if `heterogeneity=False` (default) or a tuple `(y, h)` otherwise

    """
    self.refit(feature)
    centering = self._resolve_centering(centering)

    _, mask = self._node_mask(feature, node_idx)
    fe = self._global_fe
    y = fe.eval(feature, xs, centering=centering, mask=mask)
    if heterogeneity:
        return y, fe.eval_heter(feature, xs, mask=mask)
    return y

summary(features, scale_x_list=None)

👉 Summarize the partition tree for the selected features.

Example output
Feature 3 - Full partition tree:
🌳 Full Tree Structure:
───────────────────────
hr 🔹 [id: 0 | heter: 0.43 | inst: 3476 | w: 1.00]
    workingday = 0.00 🔹 [id: 1 | heter: 0.36 | inst: 1129 | w: 0.32]
        temp ≤ 6.50 🔹 [id: 3 | heter: 0.17 | inst: 568 | w: 0.16]
        temp > 6.50 🔹 [id: 4 | heter: 0.21 | inst: 561 | w: 0.16]
    workingday ≠ 0.00 🔹 [id: 2 | heter: 0.28 | inst: 2347 | w: 0.68]
        temp ≤ 6.50 🔹 [id: 5 | heter: 0.19 | inst: 953 | w: 0.27]
        temp > 6.50 🔹 [id: 6 | heter: 0.20 | inst: 1394 | w: 0.40]
--------------------------------------------------
Feature 3 - Statistics per tree level:
🌳 Tree Summary:
─────────────────
Level 0🔹heter: 0.43
    Level 1🔹heter: 0.31 | 🔻0.12 (28.15%)
        Level 2🔹heter: 0.19 | 🔻0.11 (37.10%)

Parameters:

Name Type Description Default
features List[int]

indices of the features to summarize

required
scale_x_list Union[None, bool, List]

list of scaling factors for each feature

  • None, for no scaling
  • [{"mean": 0, "std": 1}, {"mean": 3, "std": 0.1}], to manually scale the features
None
Source code in effector/regional_effect.py
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
def summary(
    self,
    features: List[int],
    scale_x_list: typing.Union[None, bool, List] = None,
):
    """:point_right: Summarize the partition tree for the selected features.

    ???+ Example "Example output"

        ```python
        Feature 3 - Full partition tree:
        🌳 Full Tree Structure:
        ───────────────────────
        hr 🔹 [id: 0 | heter: 0.43 | inst: 3476 | w: 1.00]
            workingday = 0.00 🔹 [id: 1 | heter: 0.36 | inst: 1129 | w: 0.32]
                temp ≤ 6.50 🔹 [id: 3 | heter: 0.17 | inst: 568 | w: 0.16]
                temp > 6.50 🔹 [id: 4 | heter: 0.21 | inst: 561 | w: 0.16]
            workingday ≠ 0.00 🔹 [id: 2 | heter: 0.28 | inst: 2347 | w: 0.68]
                temp ≤ 6.50 🔹 [id: 5 | heter: 0.19 | inst: 953 | w: 0.27]
                temp > 6.50 🔹 [id: 6 | heter: 0.20 | inst: 1394 | w: 0.40]
        --------------------------------------------------
        Feature 3 - Statistics per tree level:
        🌳 Tree Summary:
        ─────────────────
        Level 0🔹heter: 0.43
            Level 1🔹heter: 0.31 | 🔻0.12 (28.15%)
                Level 2🔹heter: 0.19 | 🔻0.11 (37.10%)
        ```

    Args:
        features: indices of the features to summarize
        scale_x_list: list of scaling factors for each feature

            - `None`, for no scaling
            - `[{"mean": 0, "std": 1}, {"mean": 3, "std": 0.1}]`, to manually scale the features

    """
    scale_x_list = helpers.resolve_scale(scale_x_list, self.scale_x_list)
    features = helpers.prep_features(features, self.dim)

    for feat in features:
        self.refit(feat)

        feat_str = "feature_{}".format(feat)
        tree_dict = self.tree[feat_str]

        print("\n")
        print("Feature {} - Full partition tree:".format(feat))

        if tree_dict is None:
            print("No splits found for feature {}".format(feat))
        else:
            tree_dict.show_full_tree(scale_x_list=scale_x_list)

        print("-" * 50)
        print("Feature {} - Statistics per tree level:".format(feat))

        if tree_dict is None:
            print("No splits found for feature {}".format(feat))
        else:
            tree_dict.show_level_stats()
        print("\n")

effector.regional_effect_ale.RegionalALE(data, model, *, nof_instances=10000, axis_limits=None, schema=None, random_state=21)

Bases: RegionalEffectBase

Initialize the Regional Effect method.

Parameters:

Name Type Description Default
data ndarray

the design matrix, ndarray of shape (N,D)

required
model callable

the black-box model, Callable with signature x -> y where:

  • x: ndarray of shape (N, D)
  • y: ndarray of shape (N)
required
axis_limits Union[None, ndarray]

Feature effect limits along each axis

  • None, infers them from data (min and max of each feature)
  • array of shape (D, 2), manually specify the limits for each feature.

When possible, specify the axis limits manually

  • they help to discard outliers and improve the quality of the fit
  • axis_limits define the .plot method's x-axis limits; manual specification leads to better visualizations

Their shape is (2, D), not (D, 2)

axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
None
nof_instances Union[int, str]

Max instances to use

  • "all", uses all data
  • int, randomly selects int instances from data

100_000 (default) is a good choice; RegionalALE can handle large datasets. 😎

10000
schema Optional[Union[Schema, dict]]

input metadata (R10) — an effector.Schema or a plain dict with any of the keys feature_names, feature_types, cat_limit, target_name, scale_x_list, scale_y

  • omitted fields are auto-inferred from data (numpy heuristics) or synthesized (["x_0", ...], "y"); to start from a DataFrame use effector.from_dataframe
  • explicit fields always win over inference
None
random_state Optional[int]

seed for every internal random step (e.g. nof_instances subsampling)

  • int (default: 21), for reproducible output; two identical constructions give identical results
  • None, for non-deterministic behavior
21

Methods:

Name Description
fit

Find subregions by minimizing the ALE-based heterogeneity.

plot

Plot the regional ALE effect of feature at node node_idx.

Source code in effector/regional_effect_ale.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
def __init__(
    self,
    data: np.ndarray,
    model: callable,
    *,
    nof_instances: typing.Union[int, str] = 10_000,
    axis_limits: typing.Union[None, np.ndarray] = None,
    schema: Optional[Union[ingestion.Schema, dict]] = None,
    random_state: typing.Optional[int] = 21,
):
    """
    Initialize the Regional Effect method.

    Args:
        data: the design matrix, `ndarray` of shape `(N,D)`
        model: the black-box model, `Callable` with signature `x -> y` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `y`: `ndarray` of shape `(N)`

        axis_limits: Feature effect limits along each axis

            - `None`, infers them from `data` (`min` and `max` of each feature)
            - `array` of shape `(D, 2)`, manually specify the limits for each feature.

            !!! tip "When possible, specify the axis limits manually"

                - they help to discard outliers and improve the quality of the fit
                - `axis_limits` define the `.plot` method's x-axis limits; manual specification leads to better visualizations

            !!! tip "Their shape is `(2, D)`, not `(D, 2)`"

                ```python
                axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
                ```

        nof_instances: Max instances to use

            - `"all"`, uses all `data`
            - `int`, randomly selects `int` instances from `data`

            !!! tip "`100_000` (default) is a good choice; RegionalALE can handle large datasets. :sunglasses:"

        schema: input metadata (R10) — an `effector.Schema` or a plain `dict`
            with any of the keys `feature_names`, `feature_types`,
            `cat_limit`, `target_name`, `scale_x_list`, `scale_y`

            - omitted fields are auto-inferred from `data` (numpy
              heuristics) or synthesized (`["x_0", ...]`, `"y"`); to start
              from a DataFrame use `effector.from_dataframe`
            - explicit fields always win over inference

        random_state: seed for every internal random step (e.g. `nof_instances` subsampling)

            - `int` (default: `21`), for reproducible output; two identical constructions give identical results
            - `None`, for non-deterministic behavior
    """

    super(RegionalALE, self).__init__(
        "ale",
        data,
        model,
        nof_instances=nof_instances,
        axis_limits=axis_limits,
        schema=schema,
        random_state=random_state,
    )

fit(features='all', *, candidate_conditioning_features='all', space_partitioner='best', binning_method='fixed')

Find subregions by minimizing the ALE-based heterogeneity.

Parameters:

Name Type Description Default
features Union[int, str, list]

for which features to search for subregions

  • use "all", for all features, e.g. features="all"
  • use an int, for a single feature, e.g. features=0
  • use a list, for multiple features, e.g. features=[0, 1, 2]
'all'
candidate_conditioning_features Union[str, list]

list of features to consider as conditioning features

'all'
space_partitioner Union[str, Best]

the space partitioner to use

'best'
binning_method Union[str, Fixed]

must be the Fixed binning method

  • If set to "fixed", the ALE plot will be computed with the default values, which are 20 bins with at least 0 points per bin
  • If you want to change the parameters of the method, you pass an instance of the class effector.axis_partitioning.Fixed with the desired parameters. For example: Fixed(nof_bins=20, min_points_per_bin=0)
'fixed'
Source code in effector/regional_effect_ale.py
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
def fit(
    self,
    features: typing.Union[int, str, list] = "all",
    *,
    candidate_conditioning_features: typing.Union["str", list] = "all",
    space_partitioner: typing.Union[str, effector.space_partitioning.Best] = "best",
    binning_method: typing.Union[str, ap.Fixed] = "fixed",
):
    """
    Find subregions by minimizing the ALE-based heterogeneity.

    Args:
        features: for which features to search for subregions

            - use `"all"`, for all features, e.g. `features="all"`
            - use an `int`, for a single feature, e.g. `features=0`
            - use a `list`, for multiple features, e.g. `features=[0, 1, 2]`

        candidate_conditioning_features: list of features to consider as conditioning features
        space_partitioner: the space partitioner to use

        binning_method: must be the Fixed binning method

            - If set to `"fixed"`, the ALE plot will be computed with the  default values, which are
            `20` bins with at least `0` points per bin
            - If you want to change the parameters of the method, you pass an instance of the
            class `effector.axis_partitioning.Fixed` with the desired parameters.
            For example: `Fixed(nof_bins=20, min_points_per_bin=0)`
    """
    self.kwargs_subregion_detection = {
        "features": features,
        "candidate_conditioning_features": candidate_conditioning_features,
        "space_partitioner": space_partitioner,
    }
    self.kwargs_fitting = {"binning_method": binning_method}

    self._fit_loop(features, candidate_conditioning_features, space_partitioner)

plot(feature, node_idx, heterogeneity=True, centering=None, scale_x_list=None, scale_y=None, y_limits=None, dy_limits=None, show_plot=True)

Plot the regional ALE effect of feature at node node_idx.

Parameters:

Name Type Description Default
feature int

the feature to plot

required
node_idx int

the index of the node to plot

required
heterogeneity Union[bool, str]

whether to plot the heterogeneity (std of the bin effects)

True
centering Union[None, bool, str]

whether to center the plot (None uses the class default)

None
scale_x_list Optional[list]

list with a {"mean": ..., "std": ...} dict per feature, for de-normalizing the x-axes

None
scale_y Optional[dict]

{"mean": ..., "std": ...} dict for de-normalizing the y-axis

None
y_limits Optional[list]

manual limits of the y-axis

None
dy_limits Optional[list]

manual limits of the dy/dx-axis

None
show_plot bool

if True, show the figure; if False, return (fig, ax)

True
Source code in effector/regional_effect_ale.py
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
def plot(
    self,
    feature: int,
    node_idx: int,
    heterogeneity: Union[bool, str] = True,
    centering: Union[None, bool, str] = None,
    scale_x_list: Optional[list] = None,
    scale_y: Optional[dict] = None,
    y_limits: Optional[list] = None,
    dy_limits: Optional[list] = None,
    show_plot: bool = True,
):
    """Plot the regional ALE effect of `feature` at node `node_idx`.

    Args:
        feature: the feature to plot
        node_idx: the index of the node to plot
        heterogeneity: whether to plot the heterogeneity (std of the bin effects)
        centering: whether to center the plot (`None` uses the class default)
        scale_x_list: list with a `{"mean": ..., "std": ...}` dict per feature, for de-normalizing the x-axes
        scale_y: `{"mean": ..., "std": ...}` dict for de-normalizing the y-axis
        y_limits: manual limits of the y-axis
        dy_limits: manual limits of the dy/dx-axis
        show_plot: if `True`, show the figure; if `False`, return `(fig, ax)`
    """
    return self._plot(
        feature,
        node_idx,
        scale_x_list,
        dict(
            heterogeneity=heterogeneity,
            centering=centering,
            scale_y=scale_y,
            y_limits=y_limits,
            dy_limits=dy_limits,
            show_plot=show_plot,
        ),
    )

effector.regional_effect_ale.RegionalRHALE(data, model, model_jac=None, *, data_effect=None, nof_instances=10000, axis_limits=None, schema=None, random_state=21)

Bases: RegionalEffectBase

Initialize the Regional Effect method.

Parameters:

Name Type Description Default
data ndarray

the design matrix, ndarray of shape (N,D)

required
model Callable

the black-box model, Callable with signature x -> y where:

  • x: ndarray of shape (N, D)
  • y: ndarray of shape (N)
required
model_jac Optional[Callable]

the black-box model's Jacobian, Callable with signature x -> dy_dx where:

  • x: ndarray of shape (N, D)
  • dy_dx: ndarray of shape (N, D)
None
data_effect Optional[ndarray]

The jacobian of the model on the data

  • None, infers the Jacobian internally using model_jac(data) or numerically
  • np.ndarray, to provide the Jacobian directly

When possible, provide the Jacobian directly

Computing the jacobian on the whole dataset can be memory demanding. If you have the jacobian already computed, provide it directly to the constructor.

None
axis_limits Optional[ndarray]

Feature effect limits along each axis

  • None, infers them from data (min and max of each feature)
  • array of shape (D, 2), manually specify the limits for each feature.

When possible, specify the axis limits manually

  • they help to discard outliers and improve the quality of the fit
  • axis_limits define the .plot method's x-axis limits; manual specification leads to better visualizations

Their shape is (2, D), not (D, 2)

axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
None
nof_instances Union[int, str]

Max instances to use

  • "all", uses all data
  • int, randomly selects int instances from data

100_000 (default), is a good choice. RHALE can handle large datasets 😎 😎

10000
schema Optional[Union[Schema, dict]]

input metadata (R10) — an effector.Schema or a plain dict with any of the keys feature_names, feature_types, cat_limit, target_name, scale_x_list, scale_y

  • omitted fields are auto-inferred from data (numpy heuristics) or synthesized (["x_0", ...], "y"); to start from a DataFrame use effector.from_dataframe
  • explicit fields always win over inference
None
random_state Optional[int]

seed for every internal random step (e.g. nof_instances subsampling)

  • int (default: 21), for reproducible output; two identical constructions give identical results
  • None, for non-deterministic behavior
21

Methods:

Name Description
fit

Find subregions by minimizing the RHALE-based heterogeneity.

plot

Plot the regional RHALE effect of feature at node node_idx.

Source code in effector/regional_effect_ale.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def __init__(
    self,
    data: np.ndarray,
    model: Callable,
    model_jac: Optional[Callable] = None,
    *,
    data_effect: Optional[np.ndarray] = None,
    nof_instances: Union[int, str] = 10_000,
    axis_limits: Optional[np.ndarray] = None,
    schema: Optional[Union[ingestion.Schema, dict]] = None,
    random_state: Optional[int] = 21,
):
    """
    Initialize the Regional Effect method.

    Args:
        data: the design matrix, `ndarray` of shape `(N,D)`
        model: the black-box model, `Callable` with signature `x -> y` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `y`: `ndarray` of shape `(N)`

        model_jac: the black-box model's Jacobian, `Callable` with signature `x -> dy_dx` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `dy_dx`: `ndarray` of shape `(N, D)`

        data_effect: The jacobian of the `model` on the `data`

            - `None`, infers the Jacobian internally using `model_jac(data)` or numerically
            - `np.ndarray`, to provide the Jacobian directly

            !!! tip "When possible, provide the Jacobian directly"

                Computing the jacobian on the whole dataset can be memory demanding.
                If you have the jacobian already computed, provide it directly to the constructor.

        axis_limits: Feature effect limits along each axis

            - `None`, infers them from `data` (`min` and `max` of each feature)
            - `array` of shape `(D, 2)`, manually specify the limits for each feature.

            !!! tip "When possible, specify the axis limits manually"

                - they help to discard outliers and improve the quality of the fit
                - `axis_limits` define the `.plot` method's x-axis limits; manual specification leads to better visualizations

            !!! tip "Their shape is `(2, D)`, not `(D, 2)`"

                ```python
                axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
                ```

        nof_instances: Max instances to use

            - `"all"`, uses all `data`
            - `int`, randomly selects `int` instances from `data`

            !!! tip "`100_000` (default), is a good choice. RHALE can handle large datasets :sunglasses: :sunglasses: "

        schema: input metadata (R10) — an `effector.Schema` or a plain `dict`
            with any of the keys `feature_names`, `feature_types`,
            `cat_limit`, `target_name`, `scale_x_list`, `scale_y`

            - omitted fields are auto-inferred from `data` (numpy
              heuristics) or synthesized (`["x_0", ...]`, `"y"`); to start
              from a DataFrame use `effector.from_dataframe`
            - explicit fields always win over inference

        random_state: seed for every internal random step (e.g. `nof_instances` subsampling)

            - `int` (default: `21`), for reproducible output; two identical constructions give identical results
            - `None`, for non-deterministic behavior
    """

    super(RegionalRHALE, self).__init__(
        "rhale",
        data,
        model,
        model_jac,
        data_effect=data_effect,
        nof_instances=nof_instances,
        axis_limits=axis_limits,
        schema=schema,
        random_state=random_state,
    )

fit(features='all', *, candidate_conditioning_features='all', space_partitioner='best', binning_method='dp', binning_scope='global')

Find subregions by minimizing the RHALE-based heterogeneity.

Parameters:

Name Type Description Default
features Union[int, str, list]

for which features to search for subregions

  • use "all", for all features, e.g. features="all"
  • use an int, for a single feature, e.g. features=0
  • use a list, for multiple features, e.g. features=[0, 1, 2]
'all'
candidate_conditioning_features Union[str, list]

list of features to consider as conditioning features

'all'
space_partitioner Union[str, Best]

the space partitioner to use

'best'
binning_method str

the binning method to use.

  • Use "greedy" for using the Greedy binning solution with the default parameters. For custom parameters initialize a axis_partitioning.Greedy object
  • Use "dp" for using a Dynamic Programming binning solution with the default parameters. For custom parameters initialize a axis_partitioning.DynamicProgramming object
  • Use "fixed" for using a Fixed binning solution with the default parameters. For custom parameters initialize a axis_partitioning.Fixed object
'dp'
binning_scope str

the x-range the binner covers when a subregion is re-binned (the split search and the node eval/plot alike)

  • "global" (default): the frozen global axis_limits — one frame for every subregion, directly comparable
  • "effective": each subregion's own [min, max] — bins packed into the subregion, finer resolution
'global'
Source code in effector/regional_effect_ale.py
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def fit(
    self,
    features: typing.Union[int, str, list] = "all",
    *,
    candidate_conditioning_features: typing.Union[str, list] = "all",
    space_partitioner: typing.Union[str, effector.space_partitioning.Best] = "best",
    binning_method: typing.Union[
        str,
        ap.Fixed,
        ap.DynamicProgramming,
        ap.Agglomerative,
        ap.Quantile,
    ] = "dp",
    binning_scope: str = "global",
):
    """
    Find subregions by minimizing the RHALE-based heterogeneity.

    Args:
        features: for which features to search for subregions

            - use `"all"`, for all features, e.g. `features="all"`
            - use an `int`, for a single feature, e.g. `features=0`
            - use a `list`, for multiple features, e.g. `features=[0, 1, 2]`

        candidate_conditioning_features: list of features to consider as conditioning features
        space_partitioner: the space partitioner to use
        binning_method (str): the binning method to use.

            - Use `"greedy"` for using the Greedy binning solution with the default parameters.
              For custom parameters initialize a `axis_partitioning.Greedy` object
            - Use `"dp"` for using a Dynamic Programming binning solution with the default parameters.
              For custom parameters initialize a `axis_partitioning.DynamicProgramming` object
            - Use `"fixed"` for using a Fixed binning solution with the default parameters.
              For custom parameters initialize a `axis_partitioning.Fixed` object

        binning_scope: the x-range the binner covers when a subregion is
            re-binned (the split search and the node eval/plot alike)

            - `"global"` (default): the frozen global `axis_limits` — one
              frame for every subregion, directly comparable
            - `"effective"`: each subregion's own `[min, max]` — bins
              packed into the subregion, finer resolution
    """
    if self.data_effect is None:
        self.compile()

    self.kwargs_subregion_detection = {
        "features": features,
        "candidate_conditioning_features": candidate_conditioning_features,
        "space_partitioner": space_partitioner,
    }
    self.kwargs_fitting = {
        "binning_method": binning_method,
        "binning_scope": binning_scope,
    }

    self._fit_loop(features, candidate_conditioning_features, space_partitioner)

plot(feature, node_idx, heterogeneity=True, centering=None, scale_x_list=None, scale_y=None, y_limits=None, dy_limits=None, show_plot=True)

Plot the regional RHALE effect of feature at node node_idx.

Parameters:

Name Type Description Default
feature int

the feature to plot

required
node_idx int

the index of the node to plot

required
heterogeneity Union[bool, str]

whether to plot the heterogeneity (std of the bin effects)

True
centering Union[None, bool, str]

whether to center the plot (None uses the class default)

None
scale_x_list Optional[list]

list with a {"mean": ..., "std": ...} dict per feature, for de-normalizing the x-axes

None
scale_y Optional[dict]

{"mean": ..., "std": ...} dict for de-normalizing the y-axis

None
y_limits Optional[list]

manual limits of the y-axis

None
dy_limits Optional[list]

manual limits of the dy/dx-axis

None
show_plot bool

if True, show the figure; if False, return (fig, ax)

True
Source code in effector/regional_effect_ale.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
def plot(
    self,
    feature: int,
    node_idx: int,
    heterogeneity: Union[bool, str] = True,
    centering: Union[None, bool, str] = None,
    scale_x_list: Optional[list] = None,
    scale_y: Optional[dict] = None,
    y_limits: Optional[list] = None,
    dy_limits: Optional[list] = None,
    show_plot: bool = True,
):
    """Plot the regional RHALE effect of `feature` at node `node_idx`.

    Args:
        feature: the feature to plot
        node_idx: the index of the node to plot
        heterogeneity: whether to plot the heterogeneity (std of the bin effects)
        centering: whether to center the plot (`None` uses the class default)
        scale_x_list: list with a `{"mean": ..., "std": ...}` dict per feature, for de-normalizing the x-axes
        scale_y: `{"mean": ..., "std": ...}` dict for de-normalizing the y-axis
        y_limits: manual limits of the y-axis
        dy_limits: manual limits of the dy/dx-axis
        show_plot: if `True`, show the figure; if `False`, return `(fig, ax)`
    """
    return self._plot(
        feature,
        node_idx,
        scale_x_list,
        dict(
            heterogeneity=heterogeneity,
            centering=centering,
            scale_y=scale_y,
            y_limits=y_limits,
            dy_limits=dy_limits,
            show_plot=show_plot,
        ),
    )

effector.regional_effect_pdp.RegionalPDP(data, model, *, nof_instances=10000, axis_limits=None, schema=None, random_state=21)

Bases: RegionalPDPBase

Initialize the Regional Effect method.

Parameters:

Name Type Description Default
data ndarray

the design matrix, ndarray of shape (N,D)

required
model callable

the black-box model, Callable with signature f(x) -> y where:

  • x: ndarray of shape (N, D)
  • y: ndarray of shape (N)
required
axis_limits Union[None, ndarray]

Feature effect limits along each axis

  • None, infers them from data (min and max of each feature)
  • array of shape (D, 2), manually specify the limits for each feature.

When possible, specify the axis limits manually

  • they help to discard outliers and improve the quality of the fit
  • axis_limits define the .plot method's x-axis limits; manual specification leads to better visualizations

Their shape is (2, D), not (D, 2)

axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
None
nof_instances Union[int, str]

Max instances to use

  • "all", uses all data
  • int, randomly selects int instances from data

10_000 (default), is a good balance between speed and accuracy

10000
schema Optional[Union[Schema, dict]]

input metadata (R10) — an effector.Schema or a plain dict with any of the keys feature_names, feature_types, cat_limit, target_name, scale_x_list, scale_y

  • omitted fields are auto-inferred from data (numpy heuristics) or synthesized (["x_0", ...], "y"); to start from a DataFrame use effector.from_dataframe
  • explicit fields always win over inference
None
random_state Optional[int]

seed for every internal random step (e.g. nof_instances subsampling)

  • int (default: 21), for reproducible output; two identical constructions give identical results
  • None, for non-deterministic behavior
21

Methods:

Name Description
fit

Find subregions by minimizing the PDP-based heterogeneity.

plot

Plot the regional PDP effect of feature at node node_idx.

Source code in effector/regional_effect_pdp.py
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def __init__(
    self,
    data: np.ndarray,
    model: callable,
    *,
    nof_instances: typing.Union[int, str] = 10_000,
    axis_limits: typing.Union[None, np.ndarray] = None,
    schema: typing.Optional[typing.Union[ingestion.Schema, dict]] = None,
    random_state: typing.Optional[int] = 21,
):
    """
    Initialize the Regional Effect method.

    Args:
        data: the design matrix, `ndarray` of shape `(N,D)`
        model: the black-box model, `Callable` with signature `f(x) -> y` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `y`: `ndarray` of shape `(N)`

        axis_limits: Feature effect limits along each axis

            - `None`, infers them from `data` (`min` and `max` of each feature)
            - `array` of shape `(D, 2)`, manually specify the limits for each feature.

            !!! tip "When possible, specify the axis limits manually"

                - they help to discard outliers and improve the quality of the fit
                - `axis_limits` define the `.plot` method's x-axis limits; manual specification leads to better visualizations

            !!! tip "Their shape is `(2, D)`, not `(D, 2)`"

                ```python
                axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
                ```

        nof_instances: Max instances to use

            - `"all"`, uses all `data`
            - `int`, randomly selects `int` instances from `data`

            !!! tip "`10_000` (default), is a good balance between speed and accuracy"

        schema: input metadata (R10) — an `effector.Schema` or a plain `dict`
            with any of the keys `feature_names`, `feature_types`,
            `cat_limit`, `target_name`, `scale_x_list`, `scale_y`

            - omitted fields are auto-inferred from `data` (numpy
              heuristics) or synthesized (`["x_0", ...]`, `"y"`); to start
              from a DataFrame use `effector.from_dataframe`
            - explicit fields always win over inference

        random_state: seed for every internal random step (e.g. `nof_instances` subsampling)

            - `int` (default: `21`), for reproducible output; two identical constructions give identical results
            - `None`, for non-deterministic behavior
    """

    super(RegionalPDP, self).__init__(
        "pdp",
        data,
        model,
        None,
        nof_instances=nof_instances,
        axis_limits=axis_limits,
        schema=schema,
        random_state=random_state,
    )

fit(features='all', *, candidate_conditioning_features='all', space_partitioner='best', points_for_centering=30, use_vectorized=True)

Find subregions by minimizing the PDP-based heterogeneity.

Parameters:

Name Type Description Default
features Union[int, str, list]

for which features to search for subregions

  • use "all", for all features, e.g. features="all"
  • use an int, for a single feature, e.g. features=0
  • use a list, for multiple features, e.g. features=[0, 1, 2]
'all'
candidate_conditioning_features Union[str, list]

list of features to consider as conditioning features

  • use "all", for all features, e.g. candidate_conditioning_features="all"
  • use a list, for multiple features, e.g. candidate_conditioning_features=[0, 1, 2]
  • it means that for each feature in the feature list, the algorithm will consider applying a split conditioned on each feature in the candidate_conditioning_features list
'all'
space_partitioner Union[str, Best]

the method to use for partitioning the space

'best'
points_for_centering int

number of equidistant points along the feature axis used for centering ICE plots

30
use_vectorized bool

whether to use vectorized operations for the PDP and ICE curves

True
Source code in effector/regional_effect_pdp.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def fit(
    self,
    features: typing.Union[int, str, list] = "all",
    *,
    candidate_conditioning_features: typing.Union[str, list] = "all",
    space_partitioner: typing.Union[str, Best] = "best",
    points_for_centering: int = 30,
    use_vectorized: bool = True,
):
    """
    Find subregions by minimizing the PDP-based heterogeneity.

    Args:
        features: for which features to search for subregions

            - use `"all"`, for all features, e.g. `features="all"`
            - use an `int`, for a single feature, e.g. `features=0`
            - use a `list`, for multiple features, e.g. `features=[0, 1, 2]`

        candidate_conditioning_features: list of features to consider as conditioning features

            - use `"all"`, for all features, e.g. `candidate_conditioning_features="all"`
            - use a `list`, for multiple features, e.g. `candidate_conditioning_features=[0, 1, 2]`
            - it means that for each feature in the `feature` list, the algorithm will consider applying a split
            conditioned on each feature in the `candidate_conditioning_features` list

        space_partitioner: the method to use for partitioning the space
        points_for_centering: number of equidistant points along the feature axis used for centering ICE plots
        use_vectorized: whether to use vectorized operations for the PDP and ICE curves


    """
    self.kwargs_subregion_detection = {
        "features": features,
        "candidate_conditioning_features": candidate_conditioning_features,
        "space_partitioner": space_partitioner,
    }
    self.kwargs_fitting = {
        "points_for_centering": points_for_centering,
        "use_vectorized": use_vectorized,
    }

    self._fit_loop(features, candidate_conditioning_features, space_partitioner)

plot(feature, node_idx, heterogeneity='ice', centering=None, nof_points=100, scale_x_list=None, scale_y=None, nof_ice=100, show_avg_output=False, y_limits=None, use_vectorized=True, show_plot=True)

Plot the regional PDP effect of feature at node node_idx.

Parameters:

Name Type Description Default
feature int

the feature to plot

required
node_idx int

the index of the node to plot

required
heterogeneity Union[bool, str]

whether to plot the heterogeneity ("ice", "std", or False)

'ice'
centering Union[None, bool, str]

whether to center the plot (None uses the class default)

None
nof_points int

the grid size for the PDP curve

100
scale_x_list Union[None, list]

list with a {"mean": ..., "std": ...} dict per feature, for de-normalizing the x-axes

None
scale_y Union[None, dict]

{"mean": ..., "std": ...} dict for de-normalizing the y-axis

None
nof_ice Union[int, str]

number of ICE curves to show

100
show_avg_output bool

whether to show the average output of the model

False
y_limits Union[None, list]

manual limits of the y-axis

None
use_vectorized bool

whether to use the vectorized ICE computation

True
show_plot bool

if True, show the figure; if False, return (fig, ax)

True
Source code in effector/regional_effect_pdp.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
def plot(
    self,
    feature: int,
    node_idx: int,
    heterogeneity: typing.Union[bool, str] = "ice",
    centering: typing.Union[None, bool, str] = None,
    nof_points: int = 100,
    scale_x_list: typing.Union[None, list] = None,
    scale_y: typing.Union[None, dict] = None,
    nof_ice: typing.Union[int, str] = 100,
    show_avg_output: bool = False,
    y_limits: typing.Union[None, list] = None,
    use_vectorized: bool = True,
    show_plot: bool = True,
):
    """Plot the regional PDP effect of `feature` at node `node_idx`.

    Args:
        feature: the feature to plot
        node_idx: the index of the node to plot
        heterogeneity: whether to plot the heterogeneity (`"ice"`, `"std"`, or `False`)
        centering: whether to center the plot (`None` uses the class default)
        nof_points: the grid size for the PDP curve
        scale_x_list: list with a `{"mean": ..., "std": ...}` dict per feature, for de-normalizing the x-axes
        scale_y: `{"mean": ..., "std": ...}` dict for de-normalizing the y-axis
        nof_ice: number of ICE curves to show
        show_avg_output: whether to show the average output of the model
        y_limits: manual limits of the y-axis
        use_vectorized: whether to use the vectorized ICE computation
        show_plot: if `True`, show the figure; if `False`, return `(fig, ax)`
    """
    return self._plot(
        feature,
        node_idx,
        scale_x_list,
        dict(
            heterogeneity=heterogeneity,
            centering=centering,
            nof_points=nof_points,
            scale_y=scale_y,
            nof_ice=nof_ice,
            show_avg_output=show_avg_output,
            y_limits=y_limits,
            use_vectorized=use_vectorized,
            show_plot=show_plot,
        ),
    )

effector.regional_effect_pdp.RegionalDerPDP(data, model, model_jac=None, *, nof_instances=10000, axis_limits=None, schema=None, random_state=21)

Bases: RegionalPDPBase

Initialize the Regional Effect method.

Parameters:

Name Type Description Default
data ndarray

the design matrix, ndarray of shape (N,D)

required
model callable

the black-box model, Callable with signature x -> y where:

  • x: ndarray of shape (N, D)
  • y: ndarray of shape (N)
required
model_jac Optional[callable]

the black-box model's Jacobian, Callable with signature x -> dy_dx where:

  • x: ndarray of shape (N, D)
  • dy_dx: ndarray of shape (N, D)
None
axis_limits Union[None, ndarray]

Feature effect limits along each axis

  • None, infers them from data (min and max of each feature)
  • array of shape (D, 2), manually specify the limits for each feature.

When possible, specify the axis limits manually

  • they help to discard outliers and improve the quality of the fit
  • axis_limits define the .plot method's x-axis limits; manual specification leads to better visualizations

Their shape is (2, D), not (D, 2)

axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
None
nof_instances Union[int, str]

Max instances to use

  • "all", uses all data
  • int, randomly selects int instances from data

10_000 (default), is a good balance between speed and accuracy

10000
schema Optional[Union[Schema, dict]]

input metadata (R10) — an effector.Schema or a plain dict with any of the keys feature_names, feature_types, cat_limit, target_name, scale_x_list, scale_y

  • omitted fields are auto-inferred from data (numpy heuristics) or synthesized (["x_0", ...], "y"); to start from a DataFrame use effector.from_dataframe
  • explicit fields always win over inference
None
random_state Optional[int]

seed for every internal random step (e.g. nof_instances subsampling)

  • int (default: 21), for reproducible output; two identical constructions give identical results
  • None, for non-deterministic behavior
21

Methods:

Name Description
fit

Find subregions by minimizing the PDP-based heterogeneity.

plot

Plot the regional d-PDP effect of feature at node node_idx.

Source code in effector/regional_effect_pdp.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
def __init__(
    self,
    data: np.ndarray,
    model: callable,
    model_jac: typing.Optional[callable] = None,
    *,
    nof_instances: typing.Union[int, str] = 10_000,
    axis_limits: typing.Union[None, np.ndarray] = None,
    schema: typing.Optional[typing.Union[ingestion.Schema, dict]] = None,
    random_state: typing.Optional[int] = 21,
):
    """
    Initialize the Regional Effect method.

    Args:
        data: the design matrix, `ndarray` of shape `(N,D)`
        model: the black-box model, `Callable` with signature `x -> y` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `y`: `ndarray` of shape `(N)`

        model_jac: the black-box model's Jacobian, `Callable` with signature `x -> dy_dx` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `dy_dx`: `ndarray` of shape `(N, D)`

        axis_limits: Feature effect limits along each axis

            - `None`, infers them from `data` (`min` and `max` of each feature)
            - `array` of shape `(D, 2)`, manually specify the limits for each feature.

            !!! tip "When possible, specify the axis limits manually"

                - they help to discard outliers and improve the quality of the fit
                - `axis_limits` define the `.plot` method's x-axis limits; manual specification leads to better visualizations

            !!! tip "Their shape is `(2, D)`, not `(D, 2)`"

                ```python
                axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
                ```

        nof_instances: Max instances to use

            - `"all"`, uses all `data`
            - `int`, randomly selects `int` instances from `data`

            !!! tip "`10_000` (default), is a good balance between speed and accuracy"

        schema: input metadata (R10) — an `effector.Schema` or a plain `dict`
            with any of the keys `feature_names`, `feature_types`,
            `cat_limit`, `target_name`, `scale_x_list`, `scale_y`

            - omitted fields are auto-inferred from `data` (numpy
              heuristics) or synthesized (`["x_0", ...]`, `"y"`); to start
              from a DataFrame use `effector.from_dataframe`
            - explicit fields always win over inference

        random_state: seed for every internal random step (e.g. `nof_instances` subsampling)

            - `int` (default: `21`), for reproducible output; two identical constructions give identical results
            - `None`, for non-deterministic behavior
    """

    super(RegionalDerPDP, self).__init__(
        "d-pdp",
        data,
        model,
        model_jac,
        nof_instances=nof_instances,
        axis_limits=axis_limits,
        schema=schema,
        random_state=random_state,
    )

fit(features='all', *, candidate_conditioning_features='all', space_partitioner='best', use_vectorized=True)

Find subregions by minimizing the PDP-based heterogeneity.

Parameters:

Name Type Description Default
features Union[int, str, list]

for which features to search for subregions

  • use "all", for all features, e.g. features="all"
  • use an int, for a single feature, e.g. features=0
  • use a list, for multiple features, e.g. features=[0, 1, 2]
'all'
candidate_conditioning_features Union[str, list]

list of features to consider as conditioning features

  • use "all", for all features, e.g. candidate_conditioning_features="all"
  • use a list, for multiple features, e.g. candidate_conditioning_features=[0, 1, 2]
  • it means that for each feature in the feature list, the algorithm will consider applying a split conditioned on each feature in the candidate_conditioning_features list
'all'
space_partitioner Union[str, Best]

the method to use for partitioning the space

'best'
use_vectorized bool

whether to use vectorized operations for the PDP and ICE curves

True
Source code in effector/regional_effect_pdp.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
def fit(
    self,
    features: typing.Union[int, str, list] = "all",
    *,
    candidate_conditioning_features: typing.Union[str, list] = "all",
    space_partitioner: typing.Union[str, Best] = "best",
    use_vectorized: bool = True,
):
    """
    Find subregions by minimizing the PDP-based heterogeneity.

    Args:
        features: for which features to search for subregions

            - use `"all"`, for all features, e.g. `features="all"`
            - use an `int`, for a single feature, e.g. `features=0`
            - use a `list`, for multiple features, e.g. `features=[0, 1, 2]`

        candidate_conditioning_features: list of features to consider as conditioning features

            - use `"all"`, for all features, e.g. `candidate_conditioning_features="all"`
            - use a `list`, for multiple features, e.g. `candidate_conditioning_features=[0, 1, 2]`
            - it means that for each feature in the `feature` list, the algorithm will consider applying a split
            conditioned on each feature in the `candidate_conditioning_features` list

        space_partitioner: the method to use for partitioning the space
        use_vectorized: whether to use vectorized operations for the PDP and ICE curves


    """
    self.kwargs_subregion_detection = {
        "features": features,
        "candidate_conditioning_features": candidate_conditioning_features,
        "space_partitioner": space_partitioner,
    }
    self.kwargs_fitting = {"use_vectorized": use_vectorized}

    self._fit_loop(features, candidate_conditioning_features, space_partitioner)

plot(feature, node_idx, heterogeneity='ice', centering=None, nof_points=100, scale_x_list=None, scale_y=None, nof_ice=100, show_avg_output=False, y_limits=None, use_vectorized=True, show_plot=True)

Plot the regional d-PDP effect of feature at node node_idx.

Parameters:

Name Type Description Default
feature int

the feature to plot

required
node_idx int

the index of the node to plot

required
heterogeneity Union[bool, str]

whether to plot the heterogeneity ("ice", "std", or False)

'ice'
centering Union[None, bool, str]

whether to center the plot (None uses the class default)

None
nof_points int

the grid size for the d-PDP curve

100
scale_x_list Union[None, list]

list with a {"mean": ..., "std": ...} dict per feature, for de-normalizing the x-axes

None
scale_y Union[None, dict]

{"mean": ..., "std": ...} dict for de-normalizing the y-axis

None
nof_ice Union[int, str]

number of d-ICE curves to show

100
show_avg_output bool

whether to show the average output of the model

False
y_limits Union[None, list]

manual limits of the y-axis (derivative units)

None
use_vectorized bool

whether to use the vectorized ICE computation

True
show_plot bool

if True, show the figure; if False, return (fig, ax)

True
Source code in effector/regional_effect_pdp.py
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
def plot(
    self,
    feature: int,
    node_idx: int,
    heterogeneity: typing.Union[bool, str] = "ice",
    centering: typing.Union[None, bool, str] = None,
    nof_points: int = 100,
    scale_x_list: typing.Union[None, list] = None,
    scale_y: typing.Union[None, dict] = None,
    nof_ice: typing.Union[int, str] = 100,
    show_avg_output: bool = False,
    y_limits: typing.Union[None, list] = None,
    use_vectorized: bool = True,
    show_plot: bool = True,
):
    """Plot the regional d-PDP effect of `feature` at node `node_idx`.

    Args:
        feature: the feature to plot
        node_idx: the index of the node to plot
        heterogeneity: whether to plot the heterogeneity (`"ice"`, `"std"`, or `False`)
        centering: whether to center the plot (`None` uses the class default)
        nof_points: the grid size for the d-PDP curve
        scale_x_list: list with a `{"mean": ..., "std": ...}` dict per feature, for de-normalizing the x-axes
        scale_y: `{"mean": ..., "std": ...}` dict for de-normalizing the y-axis
        nof_ice: number of d-ICE curves to show
        show_avg_output: whether to show the average output of the model
        y_limits: manual limits of the y-axis (derivative units)
        use_vectorized: whether to use the vectorized ICE computation
        show_plot: if `True`, show the figure; if `False`, return `(fig, ax)`
    """
    return self._plot(
        feature,
        node_idx,
        scale_x_list,
        dict(
            heterogeneity=heterogeneity,
            centering=centering,
            nof_points=nof_points,
            scale_y=scale_y,
            nof_ice=nof_ice,
            show_avg_output=show_avg_output,
            y_limits=y_limits,
            use_vectorized=use_vectorized,
            show_plot=show_plot,
        ),
    )

effector.regional_effect_shap.RegionalShapDP(data, model, *, nof_instances=1000, axis_limits=None, schema=None, random_state=21, shap_values=None, backend='shap', budget=512, shap_explainer_kwargs=None, shap_explanation_kwargs=None)

Bases: RegionalEffectBase

Initialize the Regional Effect method.

Parameters:

Name Type Description Default
data ndarray

the design matrix, ndarray of shape (N,D)

required
model Callable

the black-box model, Callable with signature f(x) -> y where:

  • x: ndarray of shape (N, D)
  • y: ndarray of shape (N)
required
axis_limits Optional[ndarray]

Feature effect limits along each axis

  • None, infers them from data (min and max of each feature)
  • array of shape (D, 2), manually specify the limits for each feature.

When possible, specify the axis limits manually

  • they help to discard outliers and improve the quality of the fit
  • axis_limits define the .plot method's x-axis limits; manual specification leads to better visualizations

Their shape is (2, D), not (D, 2)

axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
None
nof_instances Union[int, str]

Max instances to use

  • "all", uses all data
  • int, randomly selects int instances from data

1_000 (default), is a good balance between speed and accuracy

1000
schema Optional[Union[Schema, dict]]

input metadata (R10) — an effector.Schema or a plain dict with any of the keys feature_names, feature_types, cat_limit, target_name, scale_x_list, scale_y

  • omitted fields are auto-inferred from data (numpy heuristics) or synthesized (["x_0", ...], "y"); to start from a DataFrame use effector.from_dataframe
  • explicit fields always win over inference
None
random_state Optional[int]

seed for every internal random step (nof_instances subsampling and the shap/shapiq explainer, unless overridden via shap_explainer_kwargs)

  • int (default: 21), for reproducible output; two identical constructions give identical results
  • None, for non-deterministic behavior
21
backend str

Package to compute SHAP values

  • use "shap" for the shap package (default)
  • use "shapiq" for the shapiq package
'shap'

Methods:

Name Description
fit

Fit the regional SHAP.

plot

Plot the regional SHAP.

Source code in effector/regional_effect_shap.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def __init__(
    self,
    data: np.ndarray,
    model: Callable,
    *,
    nof_instances: Union[int, str] = 1_000,
    axis_limits: Optional[np.ndarray] = None,
    schema: Optional[Union[ingestion.Schema, dict]] = None,
    random_state: Optional[int] = 21,
    shap_values: Optional[np.ndarray] = None,
    backend: str = "shap",
    budget: int = 512,
    shap_explainer_kwargs: Optional[dict] = None,
    shap_explanation_kwargs: Optional[dict] = None,
):
    """
    Initialize the Regional Effect method.

    Args:
        data: the design matrix, `ndarray` of shape `(N,D)`
        model: the black-box model, `Callable` with signature `f(x) -> y` where:

            - `x`: `ndarray` of shape `(N, D)`
            - `y`: `ndarray` of shape `(N)`

        axis_limits: Feature effect limits along each axis

            - `None`, infers them from `data` (`min` and `max` of each feature)
            - `array` of shape `(D, 2)`, manually specify the limits for each feature.

            !!! tip "When possible, specify the axis limits manually"

                - they help to discard outliers and improve the quality of the fit
                - `axis_limits` define the `.plot` method's x-axis limits; manual specification leads to better visualizations

            !!! tip "Their shape is `(2, D)`, not `(D, 2)`"

                ```python
                axis_limits = np.array([[0, 1, -1], [1, 2, 3]])
                ```

        nof_instances: Max instances to use

            - `"all"`, uses all `data`
            - `int`, randomly selects `int` instances from `data`

            !!! tip "`1_000` (default), is a good balance between speed and accuracy"

        schema: input metadata (R10) — an `effector.Schema` or a plain `dict`
            with any of the keys `feature_names`, `feature_types`,
            `cat_limit`, `target_name`, `scale_x_list`, `scale_y`

            - omitted fields are auto-inferred from `data` (numpy
              heuristics) or synthesized (`["x_0", ...]`, `"y"`); to start
              from a DataFrame use `effector.from_dataframe`
            - explicit fields always win over inference

        random_state: seed for every internal random step (`nof_instances` subsampling and the shap/shapiq explainer, unless overridden via `shap_explainer_kwargs`)

            - `int` (default: `21`), for reproducible output; two identical constructions give identical results
            - `None`, for non-deterministic behavior

        backend: Package to compute SHAP values

            - use `"shap"` for the `shap` package (default)
            - use `"shapiq"` for the `shapiq` package
    """
    self.global_shap_values = shap_values
    self.backend = backend
    self.budget = budget
    self.shap_explainer_kwargs = shap_explainer_kwargs
    self.shap_explanation_kwargs = shap_explanation_kwargs
    super(RegionalShapDP, self).__init__(
        "shap",
        data,
        model,
        nof_instances=nof_instances,
        axis_limits=axis_limits,
        schema=schema,
        random_state=random_state,
    )

fit(features='all', *, candidate_conditioning_features='all', space_partitioner='best', binning_method='dp', binning_scope='global')

Fit the regional SHAP.

Parameters:

Name Type Description Default
features Union[int, str, list]

the features to fit. - If set to "all", all the features will be fitted.

'all'
candidate_conditioning_features Union[str, list]

list of features to consider as conditioning features for the candidate splits - If set to "all", all the features will be considered as conditioning features.

'all'
space_partitioner Union[str, Best]

the space partitioner to use - If set to "greedy", the greedy space partitioner will be used.

'best'
binning_method Union[str, DynamicProgramming, Agglomerative, Quantile, Fixed]

the binning method to use

'dp'
binning_scope str

the x-range the binner covers when a subregion is re-binned (the split search and the node eval/plot alike)

  • "global" (default): the frozen global axis_limits — one frame for every subregion, directly comparable
  • "effective": each subregion's own [min, max] — bins packed into the subregion, finer resolution
'global'
budget

Budget to use for the approximation. Defaults to 512. - Increasing the budget improves the approximation at the cost of slower computation. - Decrease the budget for faster computation at the cost of approximation error.

required
shap_explainer_kwargs

the keyword arguments to be passed to the shap.Explainer or shapiq.Explainer class, depending on the backend. The constructor's random_state is used as the backend seed (seed= for shap, random_state= for shapiq) unless you pass your own here.

Code behind the scene

See effector.global_effect_shap._compute_shap_values — the single place the explainer is constructed and invoked.

Be careful with custom arguments

For customizing shap_explainer_kwargs and shap_explanation_kwargs args, check the official documentation of shap and shapiq packages.

required
shap_explanation_kwargs

the keyword arguments to be passed to the shap or shapiq Explainer to compute the SHAP values.

Code behind the scene

See effector.global_effect_shap._compute_shap_values — the single place the explainer is constructed and invoked.

Be careful with custom arguments

For customizing shap_explainer_kwargs and shap_explanation_kwargs args, check the official documentation of shap and shapiq packages.

required
Source code in effector/regional_effect_shap.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
def fit(
    self,
    features: typing.Union[int, str, list] = "all",
    *,
    candidate_conditioning_features: typing.Union[str, list] = "all",
    space_partitioner: typing.Union[str, effector.space_partitioning.Best] = "best",
    binning_method: Union[
        str, ap.DynamicProgramming, ap.Agglomerative, ap.Quantile, ap.Fixed
    ] = "dp",
    binning_scope: str = "global",
):
    """
    Fit the regional SHAP.

    Args:
        features: the features to fit.
            - If set to "all", all the features will be fitted.

        candidate_conditioning_features: list of features to consider as conditioning features for the candidate splits
            - If set to "all", all the features will be considered as conditioning features.

        space_partitioner: the space partitioner to use
            - If set to "greedy", the greedy space partitioner will be used.

        binning_method: the binning method to use

        binning_scope: the x-range the binner covers when a subregion is
            re-binned (the split search and the node eval/plot alike)

            - `"global"` (default): the frozen global `axis_limits` — one
              frame for every subregion, directly comparable
            - `"effective"`: each subregion's own `[min, max]` — bins
              packed into the subregion, finer resolution

        budget: Budget to use for the approximation. Defaults to 512.
            - Increasing the budget improves the approximation at the cost of slower computation.
            - Decrease the budget for faster computation at the cost of approximation error.

        shap_explainer_kwargs: the keyword arguments to be passed to the `shap.Explainer` or `shapiq.Explainer` class, depending on the backend.
            The constructor's `random_state` is used as the backend seed (`seed=` for `shap`, `random_state=` for `shapiq`) unless you pass your own here.

            ??? note "Code behind the scene"

                See `effector.global_effect_shap._compute_shap_values` — the single place the explainer is constructed and invoked.

            ??? warning "Be careful with custom arguments"

                For customizing `shap_explainer_kwargs` and `shap_explanation_kwargs` args,
                check the official documentation of [`shap`](https://shap.readthedocs.io/en/latest/) and [`shapiq`](https://shapiq.readthedocs.io/en/latest/) packages.

        shap_explanation_kwargs: the keyword arguments to be passed to the `shap` or `shapiq` Explainer to compute the SHAP values.

            ??? note "Code behind the scene"

                See `effector.global_effect_shap._compute_shap_values` — the single place the explainer is constructed and invoked.

            ??? warning "Be careful with custom arguments"

                For customizing `shap_explainer_kwargs` and `shap_explanation_kwargs` args,
                check the official documentation of [`shap`](https://shap.readthedocs.io/en/latest/) and [`shapiq`](https://shapiq.readthedocs.io/en/latest/) packages.

    """
    self.kwargs_subregion_detection = {
        "features": features,
        "candidate_conditioning_features": candidate_conditioning_features,
        "space_partitioner": space_partitioner,
    }
    self.kwargs_fitting = {
        "binning_method": binning_method,
        "binning_scope": binning_scope,
    }

    self._fit_loop(features, candidate_conditioning_features, space_partitioner)

plot(feature, node_idx, heterogeneity='shap_values', centering=None, nof_points=100, scale_x_list=None, scale_y=None, nof_shap_values=100, show_avg_output=False, y_limits=None, only_shap_values=False, show_plot=True)

Plot the regional SHAP.

Parameters:

Name Type Description Default
feature int

the feature to plot

required
node_idx int

the index of the node to plot

required
heterogeneity Union[bool, str]

whether to plot the heterogeneity

'shap_values'
centering Union[None, bool, str]

whether to center the SHAP values (None uses the class default)

None
nof_points int

number of points to plot

100
scale_x_list Optional[list]

the list of scaling factors for the feature names

None
scale_y Optional[dict]

the scaling factor for the SHAP values

None
nof_shap_values Union[int, str]

number of SHAP values to plot

100
show_avg_output bool

whether to show the average output

False
y_limits Optional[list]

the limits of the y-axis

None
only_shap_values bool

whether to plot only the SHAP values

False
show_plot bool

if True, show the figure; if False, return (fig, ax)

True
Source code in effector/regional_effect_shap.py
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
def plot(
    self,
    feature: int,
    node_idx: int,
    heterogeneity: Union[bool, str] = "shap_values",
    centering: Union[None, bool, str] = None,
    nof_points: int = 100,
    scale_x_list: Optional[list] = None,
    scale_y: Optional[dict] = None,
    nof_shap_values: Union[int, str] = 100,
    show_avg_output: bool = False,
    y_limits: Optional[list] = None,
    only_shap_values: bool = False,
    show_plot: bool = True,
):
    """
    Plot the regional SHAP.

    Args:
        feature: the feature to plot
        node_idx: the index of the node to plot
        heterogeneity: whether to plot the heterogeneity
        centering: whether to center the SHAP values (`None` uses the class default)
        nof_points: number of points to plot
        scale_x_list: the list of scaling factors for the feature names
        scale_y: the scaling factor for the SHAP values
        nof_shap_values: number of SHAP values to plot
        show_avg_output: whether to show the average output
        y_limits: the limits of the y-axis
        only_shap_values: whether to plot only the SHAP values
        show_plot: if `True`, show the figure; if `False`, return `(fig, ax)`
    """
    return self._plot(
        feature,
        node_idx,
        scale_x_list,
        dict(
            heterogeneity=heterogeneity,
            centering=centering,
            nof_points=nof_points,
            scale_y=scale_y,
            nof_shap_values=nof_shap_values,
            show_avg_output=show_avg_output,
            y_limits=y_limits,
            only_shap_values=only_shap_values,
            show_plot=show_plot,
        ),
    )