Repository navigation
Conversation
Classification trees store the weighted class distribution of each leaf. `DecisionTreeClassifier::predict_proba` returns these frequencies. Before, it returned 1 for the predicted class and 0 for the other classes. - Replace the `usize` leaf output with `ClassificationOutput` (`class_index`, `slot`). `slot` is the leaf's row in `BaseTree::leaf_probabilities` (f32, `n_leaves` x `n_classes`). A node is still 24 bytes. - A split gives the true child the parent's slot and appends a new slot for the false child. Thus the slots are 0..n_leaves. - Random forest and extra trees store the distributions too. A follow-up PR adds `predict_proba` to these forests. - `BaseTree` equality compares the leaf distributions. - Add tests for slot allocation, distribution values, sample weights, all split criteria and serde round trips. Breaking change: trees and forests serialized with an earlier version cannot be deserialized. Fit these models again.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #533 +/- ##
===========================================
+ Coverage 43.97% 87.15% +43.17%
===========================================
Files 85 100 +15
Lines 7281 9962 +2681
===========================================
+ Hits 3202 8682 +5480
+ Misses 4079 1280 -2799 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thanks for this PR, and for the clear description. The design is sound and fits the project's constraints: no Verified in the diff
Requested changes / questions
Minor / nits
Once item 1 is clarified and 2 is addressed, this looks good to merge from my side. |
In criterion, compute the argmax from the written probabilities, not from the classcounts. This way, predict and predict_proba will always agree on the class (argmax)
|
(1) lint failure does not happen at my side and is in parts of the source code unrelated to this PR. |
Fixes #526
Checklist
Current behaviour
A classification tree stores only the predicted class in each leaf.
DecisionTreeClassifier::predict_probareturns 1 for the predicted class and 0 for the other classes, so it gives no information about how certain a prediction is.New expected behaviour
Classification trees store the weighted class distribution of each leaf.
predict_probareturns the weighted class frequencies of the training samples in the leaf (the same as scikit-learn).Implementation:
ClassificationOutput { class_index, slot }(wasusize).slotis the row of the leaf inBaseTree::leaf_probabilities, a flatVec<f32>withn_leavesrows ofn_classesvalues. Regression trees keep an empty vector.0..n_leaves, and the vector has no gaps.Node<ClassificationOutput>is still 24 bytes (a test checks this). The three classification criteria share oneClassStats::leaf_valuehelper.BaseTreeequality also compares the leaf distributions.Random forest and extra trees store the distributions too, but they do not use them yet. A follow-up PR adds
predict_probato these forests.Tests
n_leavesequals the number of leaf nodes, and the slots are exactly0..n_leavesfor both splitters and for different depths.predict_probafor the Gini, Entropy and ClassificationError criteria, and for a root-only tree.Change logs
Changed
tree,ensemble: the fitted trees store the number of leaves and, for classification, the class distribution of each leaf. Models serialized with an earlier version cannot be deserialized.tree:DecisionTreeClassifier::predict_probareturns the weighted class frequencies of the training samples in the leaf.Note: the follow up issue #532 which implements
predict_probafor random forest and extra trees classifier is ready to be merged after this one has landed.