shapiq.tree.TreeModel¶

class shapiq.tree.TreeModel(children_left, children_right, children_missing, features, thresholds, values, node_sample_weight, empty_prediction=None, leaf_mask=None, n_features_in_tree=None, max_feature_id=None, feature_ids=None, root_node_id=None, n_nodes=None, nodes=None, decision_type=None, feature_map_original_internal=None, feature_map_internal_original=None, original_output_type='raw', intercepts=None, coeffs=None, cat_values=None, cat_start=None, cat_size=None, input_precision='float64')[source]¶

Bases: object

Internal representation of a single tree used by the shapiq tree explainers.

Each library-specific converter (scikit-learn, XGBoost, LightGBM, CatBoost) targets this common format so that the downstream algorithms (QuadratureTreeSHAP, TreeSHAP-IQ, LinearTreeSHAP, InterventionalTreeSHAPIQ) only need to understand one node-array layout.

Constructor arguments that fall back to a computed default when None is passed are documented on __init__(). The attributes below describe what is available on a fully initialized instance.

Variables:
  • children_left – The left children of each node in a tree. Leaf nodes are -1.

  • children_right – The right children of each node in a tree. Leaf nodes are -1.

  • children_missing – The child each node routes missing-value samples to. Used together with children_left to derive children_left_default during __init__.

  • children_left_default – Boolean mask. True at index i if missing-value samples at node i are routed to children_left[i]. Derived from children_missing.

  • features – The feature indices of the decision nodes in a tree. Leaf nodes are -2.

  • thresholds – The thresholds of the decision nodes in a tree. Leaf nodes are np.nan.

  • values – The leaf-node values, flattened to a 1-D array. Non-leaf nodes are set to 0.

  • node_sample_weight – The sample weights of the nodes in a tree.

  • cat_values – Concatenated (per-node sorted) category sets of all categorical decision nodes in CSR layout. A categorical node routes int(x[feature]) in set to the left child and everything else to the right child (NaN goes to the missing child). Empty for trees without categorical splits.

  • cat_start – Per-node offset of the node’s category set inside cat_values.

  • cat_size – Per-node length of the node’s category set. 0 marks a numeric or leaf node.

  • is_categorical – Boolean mask of categorical decision nodes (cat_size > 0).

  • has_categorical – Whether the tree contains any categorical decision node.

  • empty_prediction – The empty prediction of the tree model (weighted mean of leaf values).

  • leaf_mask – The boolean mask of the leaf nodes in a tree.

  • n_features_in_tree – The number of distinct features actually used by decision nodes.

  • max_feature_id – The maximum feature index used by any decision node (or 0 if none).

  • feature_ids – The set of feature indices used by decision nodes.

  • root_node_id – The root node id of the tree model. Defaults to 0.

  • n_nodes – The number of nodes in the tree model.

  • decision_type – The split comparison used by goes_left(). Either "<=" (default) or "<".

  • nodes – The node ids of the tree model as np.arange(n_nodes).

  • feature_map_original_internal – Mapping of feature indices from the original feature indices (as in the model) to the internal feature indices (as in the tree model).

  • feature_map_internal_original – Mapping of feature indices from the internal feature indices (as in the tree model) to the original feature indices (as in the model).

  • original_output_type – The original output type of the tree model. Defaults to "raw". Currently not used by downstream algorithms.

  • intercepts – Per-leaf intercept terms for linear-leaf tree models. Currently unused.

  • coeffs – Per-leaf coefficient vectors for linear-leaf tree models. Currently unused.

Parameters:

Initialize the TreeModel.

All numpy-array arguments must share a common node ordering. Arguments listed as None-able fall back to a value computed from the mandatory arrays.

Parameters:
  • children_left (ndarray[tuple[Any, ...], dtype[int_]]) – Left-child node ids; -1 denotes a leaf.

  • children_right (ndarray[tuple[Any, ...], dtype[int_]]) – Right-child node ids; -1 denotes a leaf.

  • children_missing (ndarray[tuple[Any, ...], dtype[int_]]) – Node id to which missing-value samples are routed.

  • features (ndarray[tuple[Any, ...], dtype[int_]]) – Decision-node feature indices. Leaf positions are sanitized to -2.

  • thresholds (ndarray[tuple[Any, ...], dtype[floating]]) – Decision-node thresholds. Leaf positions are sanitized to np.nan.

  • values (ndarray[tuple[Any, ...], dtype[floating]]) – Leaf-node values. Higher-dim arrays are flattened to 1-D; non-leaf positions are forced to 0.

  • node_sample_weight (ndarray[tuple[Any, ...], dtype[floating]]) – Per-node sample weights. NaN at leaves is replaced with 1.

  • empty_prediction (float | None) – Pre-computed empty prediction. None triggers compute_empty_prediction().

  • leaf_mask (ndarray[tuple[Any, ...], dtype[bool]] | None) – Boolean mask of leaf nodes. None derives it from children_left == -1.

  • n_features_in_tree (int | None) – Number of distinct features used by decision nodes. None derives it from the unique values in features (excluding -2).

  • max_feature_id (int | None) – Largest feature index used. None derives it from features.

  • feature_ids (set[int] | None) – Set of feature indices used by decision nodes. None derives it from features.

  • root_node_id (int | None) – Root node id. None defaults to 0.

  • n_nodes (int | None) – Number of nodes. None derives it from len(children_left).

  • nodes (ndarray[tuple[Any, ...], dtype[int_]] | None) – Node-id array. None defaults to np.arange(n_nodes).

  • decision_type (Optional[Literal['<=', '<']]) – Split comparison used by goes_left() ("<=" or "<"). None defaults to "<=".

  • feature_map_original_internal (dict[int, int] | None) – Mapping from original to internal feature indices. None defaults to the identity mapping on feature_ids.

  • feature_map_internal_original (dict[int, int] | None) – Mapping from internal to original feature indices. None defaults to the identity mapping on feature_ids.

  • original_output_type (Literal['raw', 'probability']) – Currently unused; accepted for forward compatibility.

  • intercepts (ndarray[tuple[Any, ...], dtype[floating]] | None) – Currently unused; accepted for forward compatibility with linear-leaf trees.

  • coeffs (ndarray[tuple[Any, ...], dtype[floating]] | None) – Currently unused; accepted for forward compatibility with linear-leaf trees.

  • cat_values (ndarray[tuple[Any, ...], dtype[int_]] | None) – Concatenated category sets of categorical decision nodes (CSR layout, see the class docstring). Must be provided together with cat_start and cat_size. None (default) marks a tree without categorical splits.

  • cat_start (ndarray[tuple[Any, ...], dtype[int_]] | None) – Per-node offsets into cat_values.

  • cat_size (ndarray[tuple[Any, ...], dtype[int_]] | None) – Per-node category-set lengths (0 = numeric node).

  • input_precision (Literal['float64', 'float32']) – Precision in which the source library compares inputs against thresholds at prediction time: "float32" for XGBoost and CatBoost (inputs are cast before routing, see cast_input()), "float64" otherwise. Defaults to "float64".

cast_input(x)[source]¶

Round x the way the source library rounds prediction inputs.

XGBoost and CatBoost cast inputs to float32 before comparing them against their (float32) split thresholds; routing the original float64 values can reach a different leaf than the model’s own prediction. The float32 embedding into float64 is exact and order-preserving, so the round trip below makes every downstream float64 comparison bit-identical to the source library’s float32 comparison. LightGBM compares in float64 (no cast), and sklearn’s thresholds are exact midpoints of adjacent float32 values, which makes its internal float32 input cast unobservable — both keep "float64".

Parameters:

x (ndarray[tuple[Any, ...], dtype[floating]]) – Instance(s) in the original feature space.

Return type:

ndarray[tuple[Any, ...], dtype[floating]]

Returns:

x unchanged for input_precision == "float64", otherwise x rounded through float32 (returned as float64).

compute_empty_prediction()[source]¶

Compute the empty prediction of the tree model.

The method computes the empty prediction of the tree model by taking the weighted average of the leaf node values. The method modifies the tree model in place.

Return type:

None

goes_left(node_id, value)[source]¶

Route a feature value through the split at node_id.

Handles both node kinds: numeric nodes compare against thresholds[node_id] using decision_type; categorical nodes route int(value) in the node’s category set to the left child and everything else (including unknown categories) to the right child. NaN values route to the missing child for both node kinds.

Parameters:
  • node_id (int) – The decision node to route through.

  • value (float) – The feature value of the instance at this node’s split feature.

Return type:

bool

Returns:

True to go to children_left[node_id], False for the right child.

predict(X)[source]¶

Predicts the output of multiple instances.

Parameters:

X (ndarray[tuple[Any, ...], dtype[floating]]) – The instances to predict as a 2-dimensional array of shape (n_instances, n_features).

Return type:

ndarray[tuple[Any, ...], dtype[floating]]

Returns:

The predictions of the instances with the tree model as a 1-dimensional array of shape (n_instances,).

predict_one(x)[source]¶

Predicts the output of a single instance.

Parameters:

x (ndarray[tuple[Any, ...], dtype[floating]]) – The instance to predict as a 1-dimensional array.

Return type:

float

Returns:

The prediction of the instance with the tree model.

reduce_feature_complexity()[source]¶

Reduces the feature complexity of the tree model.

The method reduces the feature complexity of the tree model by removing unused features and reindexing the feature indices of the decision nodes in the tree. The method modifies the tree model in place. To see the original feature mappings after the reduction, use the feature_map_original_internal and feature_map_internal_original attributes.

For example, consider a tree model with the following feature indices:

[0, 1, 8]

The method will remove the unused feature indices and reindex the feature indices of the decision nodes in the tree to the following:

[0, 1, 2]

Feature '8' is ‘renamed’ to '2' such that in the internal representation a one-hot vector (and matrices) of length 3 suffices to represent the feature indices.

Return type:

None

cat_size: ndarray[tuple[Any, ...], dtype[int64]]¶
cat_start: ndarray[tuple[Any, ...], dtype[int64]]¶
cat_values: ndarray[tuple[Any, ...], dtype[int64]]¶
children_left: ndarray[tuple[Any, ...], dtype[int64]]¶
children_left_default: ndarray[tuple[Any, ...], dtype[bool]]¶
children_missing: ndarray[tuple[Any, ...], dtype[int64]]¶
children_right: ndarray[tuple[Any, ...], dtype[int64]]¶
coeffs: ndarray[tuple[Any, ...], dtype[floating]]¶
decision_type: Literal['<=', '<']¶
empty_prediction: float¶
feature_ids: set[int]¶
feature_map_internal_original: dict[int, int]¶
feature_map_original_internal: dict[int, int]¶
features: ndarray[tuple[Any, ...], dtype[int64]]¶
has_categorical: bool¶
input_precision: Literal['float64', 'float32'] = 'float64'¶
intercepts: ndarray[tuple[Any, ...], dtype[floating]]¶
is_categorical: ndarray[tuple[Any, ...], dtype[bool]]¶
leaf_mask: ndarray[tuple[Any, ...], dtype[bool]]¶
max_feature_id: int¶
n_features_in_tree: int¶
n_nodes: int¶
node_sample_weight: ndarray[tuple[Any, ...], dtype[floating]]¶
nodes: ndarray[tuple[Any, ...], dtype[int64]]¶
original_output_type: Literal['raw', 'probability'] = 'raw'¶
root_node_id: int¶
thresholds: ndarray[tuple[Any, ...], dtype[floating]]¶
values: ndarray[tuple[Any, ...], dtype[floating]]¶