Introduction to Pilz¶
What is Pilz?¶
Pilz (German for "mushroom" / "fungus") is a machine learning library for classification tasks. The name reflects its nature: like mushrooms are neither plants nor animals, Pilz is neither a traditional decision tree nor a neural network — it's something in between that captures the best of both worlds.
Unlike traditional ML tools that create "black box" models, Pilz generates readable SQL rules that you can directly deploy to your database.
The core innovation of Pilz is its ability to handle feature correlations naturally through multi-dimensional cuts.
How It Works¶
Pilz evaluates feature combinations by their ability to separate target from non-target, with the training data processing running natively in Polars. The algorithm is composed of several key concepts:
- Feature Categorization — Every feature is binned into
n_catcategories. Numerical features use quantile binning; categorical features are grouped by target rate similarity. - Multi-Dimensional Splits — Pilz splits on feature combinations directly, not one at a time. This captures correlations between features in a single split.
- SQL-Native Architecture — Training runs natively in Polars; DuckDB SQL is used for legacy model scoring and the multi-class label combination. Filters are a custom boolean-expression AST (
pilz.model.expr) that renders to SQLWHEREclauses, and decision thresholds are derived on the fly from the stored leaf counts. - Splitting Nodes into Branches — Each node's winning bin combinations fan out into recursive subtrees (merged by
spore_diff), plus a residual.nbranch for the unobserved combinations. - Downsampling — At every node, Pilz independently samples target and non-target rows from a training frame that was shuffled once at load time, taking the first matching rows (
.head(max_eval_fit)). - Imbalanced Data — Because target and non-target are sampled independently with equal total weight, Pilz handles skewed distributions without SMOTE or class weights.
Traditional vs Pilz¶
A traditional decision tree needs multiple sequential splits to capture a pairwise correlation. Pilz captures it in a single multi-dimensional cut:
Comparison with Other Approaches¶
| Aspect | Neural Networks | Traditional Trees | Pilz |
|---|---|---|---|
| Feature correlations | Learned implicitly | Multiple splits | Single cut |
| Interpretability | Low | Medium | High (SQL) |
| Output format | Opaque weights | Tree structure | SQL rules |
| Data preprocessing | Often required | Minimal | Minimal |
| Imbalanced data | Needs tuning | Needs tuning | Native support |
Core Parameters¶
| Parameter | What it controls |
|---|---|
n_dims |
How many features to combine in a single split |
n_cat |
Number of bins per feature |
max_depth |
Maximum tree depth |
spore_diff |
Branch-merge distance for the winning split's bin combinations (0 = fan-out, >= 1 = binary split) |
max_eval_fit |
Rows sampled per node |
calcs_per_dim |
Max combinations evaluated per dimension |
When to Use Pilz¶
✓ Ideal For¶
- Tabular data — Customer data, transactions, any structured data
- Interpretability matters — You need to understand and deploy model logic
- Feature correlations exist — Pilz captures them naturally
- SQL-native deployment — Model output is runnable SQL
✗ Not Ideal For¶
- Image/audio/video — Use neural networks
- Very large datasets — May need tuning
- No correlations — Simpler models may suffice
Next Steps¶
- Installation — Get Pilz running in 5 minutes
- Feature Categorization — Start with how features are binned
- Multi-Dimensional Splits — The core innovation explained
Pilz: Capturing feature correlations naturally through multi-dimensional cuts.