A depth-3 oblivious gradient-boosting machine that is exactly decomposable into ≤3rd-order functional-ANOVA (fANOVA) "rating tables" — without giving up accuracy or speed.
Every tree is a depth-1..=3 symmetric (oblivious) tree with one shared (feature, threshold)
test per level and at most three distinct raw features, so the trained ensemble truncates exactly
at the 3rd interaction order. That structure lets the fitted model be rewritten, losslessly, as a
small set of main-effect and interaction tables that reproduce the model's predictions bit-for-bit
— a glass-box GBM you can read, ship as lookup tables, or audit.
- Rust core (
tri-boost-core), thin PyO3 bindings, and scikit-learn estimators. The core is#![forbid(unsafe_code)], no-panic-gated, and deterministic (bit-identical across thread counts). - scikit-learn compatible:
TriBoostRegressor/TriBoostClassifierdrop intoPipeline,GridSearchCV,cross_val_score. - Objectives:
squared_error,logistic(binary), native-softmax multiclass, and the log-linkpoisson/gamma/tweediefamilies for insurance frequency & severity. - Exact decomposition:
model.tables(X)emits the ≤3rd-order fANOVA tables; the reconstruction is verified against the ensemble by five lossless invariant checks.
pip install tri-boost # numpy-only core (raw booster API)
pip install "tri-boost[sklearn]" # + the scikit-learn estimatorsWheels are built for Linux / macOS / Windows as a single abi3 wheel per platform (CPython 3.10–3.13).
Building from source needs a Rust toolchain (rustup) and maturin:
pip install maturin
maturin develop --release # builds the Rust extension into the active venvimport numpy as np
from tri_boost import TriBoostRegressor, TriBoostClassifier
# Constructor defaults embed the recommended recipe (early stopping against a large n_trees cap,
# leaf refinement, outer bagging), so a bare estimator performs well without tuning.
# Regression
reg = TriBoostRegressor().fit(X_train, y_train)
pred = reg.predict(X_test)
# Binary classification
clf = TriBoostClassifier().fit(X_train, y_binary)
proba = clf.predict_proba(X_test) # (n, 2)
# Multiclass (native softmax) — same API, K>=3 classes
mclf = TriBoostClassifier().fit(X_train, y_multiclass)
proba = mclf.predict_proba(X_test) # (n, K), rows sum to 1import json
tables = json.loads(clf.tables(X_sample)) # ≤3rd-order fANOVA rating tables (JSON)Each fitted model decomposes into main effects and ≤3-way interactions that reproduce the raw score exactly (for a multiclass model, one table bank per class logit).
| Objective | Task | Link |
|---|---|---|
squared_error |
regression | identity |
logistic |
binary classification | logit |
softmax (automatic for TriBoostClassifier with ≥3 classes) |
multiclass | softmax |
poisson |
counts / frequency | log |
gamma |
positive severities | log |
tweedie |
compound Poisson-gamma | log |
Pre-1.0; the wire schema_version is versioned independently of the package version.
Licensed under Apache-2.0.