Changed
- pandas is no longer a dependency. The categorical machinery (factorize, predict-time code mapping, gdiff group means) is now numpy/numba only, bit-identical to the pandas implementation (the gdiff group sums replicate pandas' Kahan-compensated groupby exactly). DataFrames still work as input — they are consumed through their own
to_numpy/columnsattributes. Installs pull four packages instead of five. - Bagged predict no longer redoes the categorical transform per member. Members factorize each categorical (and combo) column once per call through a shared cache and remap only the unique values through their own fit-time maps; the input conversion and validation also run once instead of once per member. Predictions are bit-identical. 50k rows,
n_ensembles=8, 4 string categoricals: binary predict 1.21 s → 0.40 s, multiclass 1.78 s → 0.74 s, regression 1.35 s → 0.49 s; single-model predict is unchanged at big batches and ~9× faster at 1-row calls (0.19 ms vs 1.7 ms).
Fixed
- Bagged members no longer keep their fit-time thread cap at predict. A parallel
n_ensemblesfit divides the thread budget across workers, but members retained that sliver permanently — an 8-member bag walked each forest on 1–2 threads. Members now get the parent'sthread_countback after fitting. Bit-identical; bagged predict ~3–5× faster on an 8-core box (numeric 0.80 s → 0.24 s at 50k rows).
Full details in CHANGELOG.md.