sgtlearn is a Python package for learning Shape Generalized Trees (SGTs).
- 🌳 Shape Generalized Trees (SGTs): A class of decision trees where each node applies a learnable, axis-aligned shape function to a feature for non-linear and interpretable splits.
- 👁 Interpretability: Each node's shape function can be visualized directly.
- ⚡ ShapeCART Algorithm: An efficient induction method for learning SGTs from data.
- 🔀 Extensions:
- Shape²GT (S²GT): Bivariate shape functions for richer splits.
- SGTK: Multi-way branching generalization.
- Shape²CART & ShapeCARTK: Algorithms for learning S²GTs and SGTKs.
Note
This codebase is an efficient, but working implementation of the algorithms in the paper "Empowering Decision Trees via Shape Function Branching". Please refer to the ROADMAP for a detailed list of features that are currently implemented and those that are planned for future releases. For the canonical code base for the paper, please refer to https://github.com/optimal-uoft/Empowering-DTs-via-Shape-Functions. Features in the paper that are not yet implemented in this codebase include:
- Bivariate shape functions (Shape$^2$CART) + Higher branching factors for bivariate splits (Shape$^2$SGT$_K$)
- Visualization for bivariate splits (ex. contour plots)
pip install sgtlearnWheels are published for CPython 3.11–3.14 on Linux, macOS, and Windows (x86_64 + arm64); no compiler is needed for a binary install. To build from source instead, see Developer Setup.
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sgtlearn import SGTClassifier, plot_tree, make_plus
X, y = make_plus(n_samples=1500, grid=3, margin=0.07, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = SGTClassifier(max_depth=4, random_state=42)
model.fit(X_train, y_train)
plot_tree(model, X=X_train)
plt.show()Read the full docs here: https://sgtlearn.readthedocs.io/en/latest/index.html
Use a project-local virtual environment (.venv) so Python, pytest, and
scikit-learn stay isolated and reproducible. Pick one of the paths below
(uv is recommended). All require Python ≥ 3.11.
uv provisions a hermetic CPython and resolves the dev extras in one step:
uv sync --all-extras
source .venv/bin/activate # Windows: .venv\Scripts\activatepython3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -U pip
pip install -e ".[dev]"The editable install builds the C++ extensions via scikit-build-core and
installs the sgtlearn package plus native modules into .venv.
pip install .
pip install ".[dev]" # dev extras (pytest, scikit-learn) only if neededAnaconda users: Do not bootstrap the venv from an Anaconda Python. Anaconda ships a
libstdc++.so.6that lags the symbol versions produced by recent system compilers (gcc ≥ 13), so the install succeeds butimport sgtlearnfails withImportError: GLIBCXX_3.4.NN not found. Use a non-Anaconda Python — e.g.uv venv --python 3.12 .venv(downloads a hermetic CPython),pyenv, or your distro'spython3.
pip install . drives this build path:
pyproject.tomlselectsscikit_build_core.buildas the backend.- CMake is configured from
cpp/CMakeLists.txt. - Each file in
cpp/bindings/*.cppbecomes one pybind11 module target. - After each module is built,
pybind11-stubgengenerates a matching.pyi. - The
.pyiis generated and installed in the same location as the module.so.
cpp/include/sgtlearn/: public headers for the core C++ API.cpp/src/: internal C++ implementation for the core library.cpp/bindings/: pybind11 binding entrypoints; one.cppfile maps to one Python extension module.cpp/tests/: C++ unit tests consumed by thecpp_testsexecutable target.
sgtlearn_core(static library): shared C++ logic used by Python modules and tests.<module_name>(pybind11 module, one per file incpp/bindings/): compiled extension modules installed into the package.cpp_tests(Catch2 executable): optional C++ test target, controlled by:-DSGTLEARN_BUILD_TESTS=ON(build C++ tests)-DSGTLEARN_BUILD_TESTS=OFF(default forpip install; the CMake option itself defaults toON, butpyproject.tomloverrides this so wheels don't ship test binaries)
Example (build C++ tests for one install):
pip install . --config-settings=cmake.args="-DSGTLEARN_BUILD_TESTS=ON"MIT License - see LICENSE for details.
Contributions are welcome. Please feel free to submit a pull request.
If you use this package in your research, please cite:
@article{upadhya2026empowering,
title={Empowering Decision Trees via Shape Function Branching},
author={Upadhya, Nakul and Cohen, Eldan},
journal={Advances in Neural Information Processing Systems},
volume={38},
pages={122263--122308},
year={2026}
}
Additionally, check out our other works on our lab website.
