e2tree turns the ensemble's internal structure into a pairwise dissimilarity matrix, then uses that matrix to grow a single decision tree — and measures how faithfully that tree reconstructs the ensemble. This page covers the math behind each step.
A tree-based ensemble of B trees assigns every observation to a terminal node in each tree. Two observations that frequently share a terminal node are, in the ensemble's view, similar. This intuition is formalised as the co-occurrence matrix O.
Each entry is a weighted co-occurrence measure. The numerator accumulates the node goodness-of-fit Wtij|b each time observations i and j share a leaf; the denominator normalises by the larger of the two marginal sums:
The corresponding dissimilarity matrix is:
For classification, Wtij|b = Rt is the correct classification rate of the node where i and j meet in tree b (proportion of correctly classified training observations in that node). D is symmetric, non-negative, with zero diagonal, and values in [0, 1]. Computed by createDisMatrix(), with optional parallelisation.
e2tree() constructs the tree recursively. At each node the algorithm searches for the binary split — over all predictors and candidate thresholds — that maximises the reduction in within-group weighted dissimilarity:
Impurity at a node is the average intra-group dissimilarity. Splitting continues until any stopping rule is triggered:
impTotal — minimum node impurity to attempt a splitmaxDec — minimum impurity decrease requiredn — minimum observations in a nodelevel — maximum tree depthIn the classification setting, the response variable is a factor. e2tree computes the dissimilarity matrix from the ensemble's proximity (co-occurrence in terminal nodes), then fits a tree whose leaf predictions are the majority class within each node.
Terminal node purity — the proportion of observations belonging to the predicted class — provides a local measure of classification confidence. The tree produces decision rules domain experts can read directly.
Leaf node prediction for a new observation follows the standard CART convention: route the observation through the split rules to a terminal node; the prediction is the majority class of the training observations in that node, weighted by the ensemble's dissimilarity structure.
Three-class problem on 150 observations. e2tree recovers perfect setosa separation and near-perfect discrimination between versicolor and virginica in 6 terminal nodes — with 2 split variables.
Included in the package as data(credit). Demonstrates e2tree on an imbalanced binary classification task typical in real-world finance and risk modelling.
vimp(). Petal variables dominate, consistent with the underlying ensemble.
as.party() and rendered by partykit. Terminal nodes carry class-distribution bar plots; decision rules stay human-readable.
Extending e2tree to regression required redefining the goodness-of-fit weight W. The co-occurrence formula has the same structure as the classification case, but the weight now uses the normalised mean squared error (NMSE) at the node: nodes where the ensemble predicts poorly contribute less to the co-occurrence of their observations.
Formally, the regression weight is defined as:
where , p(t) = n(t)/N is the proportion of observations in node t, and MSEmax is the theoretical maximum MSE under the Jacobson bound. Two observations sharing a leaf only count toward co-occurrence to the extent that the ensemble predicts accurately in that node.
The extension is fully described in the 2026 paper in Applied Stochastic Models in Business and Industry. The R implementation follows the same workflow as the classification case: only the response type changes.
Leaf predictions become the group mean of the training observations in the node, and predict() additionally returns a node-level standard deviation. Splitting, validation, and importance all work exactly as in the classification case.
Aria, M., Gnasso, A., Iorio, C., & Fokkema, M. (2026). Extending Explainable Ensemble Trees to Regression Contexts. ASMBI, 42(1), e70064.
Read the paper ↗e2tree only ever asks an ensemble two questions: which terminal node does each observation fall into, in each tree? and what does the ensemble predict? Everything else — the co-occurrence matrix, the tree, the fidelity measures — follows from those answers.
That contract is isolated behind a three-method adapter layer, so the algorithm itself never changes. Supporting a new ensemble class means implementing get_ensemble_type(), extract_terminal_nodes() and get_ensemble_predictions() for it.
Interpretation note. The dissimilarity scale differs systematically between bagging and boosting backends. Boosted trees are shallow and highly correlated, so co-occurrence is denser; compare nLoI values within a backend, not across.
| Package | Class | Family | Tasks |
|---|---|---|---|
| randomForest | randomForest | Bagging | class. & reg. |
| ranger | ranger | Bagging | class. & reg. |
| xgboost | xgb.Booster | Boosting | class. & reg. |
| lightgbm | lgb.Booster | Boosting | class. & reg. |
| gbm | gbm | Boosting | class. & reg. |
| catboost | catboost.Model | Boosting | class. & reg. |
e2tree is interpretive, not predictive. Its quality is fidelity to the ensemble it explains, never accuracy against the outcome. Measuring that fidelity properly needs a scale-sensitive measure of agreement.
The ensemble matrix O holds continuous values in (0, 1); the e2tree matrix Ô is crisp and block-diagonal, zero for every pair the tree separates. Two matrices can correlate perfectly and still disagree systematically — the classic correlation vs. concordance distinction of Bland & Altman. A correlation-based statistic such as the Mantel test is scale-invariant, so it is blind to exactly the discrepancy that matters here.
The Loss of Interpretability answers the right question. It is a direct, scale-sensitive divergence between the two co-occurrence matrices:
Each squared discrepancy is normalised by , which makes every contribution dimensionless and concentrates the measure's sensitivity on high-proximity pairs: failures to reconstruct a strong association incur a substantial penalty, while near-zero co-occurrences contribute little.
Dividing by the number of unique pairs yields the normalized LoI, an average per-pair discrepancy that is comparable across datasets of any size:
The nLoI is bounded, non-negative, symmetric, permutation-invariant, and vanishes if and only if the reconstruction is exact. It is a robustified Neyman-type statistic, and sits inside the Cressie–Read power divergence family at .
Aria, M., Gnasso, A., & Iorio, C. A Family of Divergence Measures for Evaluating the Reconstruction Quality of Explainable Ensemble Trees.
Submitted to Computational Statistics & Data Analysis.
eValidation() complements the nLoI with four measures, each capturing a distinct structural facet of approximation quality, all under one permutation-testing framework:
The Mantel test remains available via test = "mantel" for association, not agreement.
The nLoI's distinctive property is that it splits cleanly in two. Let be the pairs the e2tree groups together and the pairs it separates. Because separated pairs have by construction, their contribution collapses to , and the statistic decomposes exactly:
The two sets have vastly different cardinalities, so the raw totals are not comparable. The per-pair averages are:
This is a diagnostic no correlation-based measure — the Mantel test included — can provide. A scalar association statistic tells you the reconstruction is "good" or "poor"; it cannot tell you which of the two failure modes you are looking at.
The tree is separating pairs the ensemble considers similar. Grow more terminal nodes or relax the pruning constraints.
Split boundaries are well placed, but within-node proximity values deviate from the ensemble's. Usually the inherent fuzzy-to-crisp transition.
The partition is well placed and the calibration is accurate. The explanations you read off the tree are the ensemble's, not the surrogate's.
plot() on an eValidation object. Top: ensemble proximity O (left) against e2tree proximity Ô (right) — note the fuzzy background against the crisp blocks. Bottom: the observed nLoI against its permutation null distribution, and the within- versus between-node decomposition.
A single global number cannot tell you which explanations to trust. localLoI() disaggregates the nLoI down to each node and each observation. For observation i:
A high flags an observation whose local explanation — its path, its neighbours, its attribution — is less trustworthy. Crucially, the per-observation values average back exactly to the published statistic, . Local LoI is an exact spatial decomposition, not a separate metric.
The leaf partition is recovered directly from the block structure of Ô — two observations share a leaf if and only if — so the decomposition needs nothing but the two matrices.
Install from CRAN and run the five-step workflow in a few minutes.