The tree model: nodes, splits and leaves
What it is
A decision tree is a binary tree in which every internal node holds a test of the form feature <= threshold, and every leaf holds a prediction: a class distribution for classification, a mean for regression. Predicting means walking from the root to a leaf, answering one test per level.
Why it matters
It is the only mainstream model whose full decision procedure can be read aloud, which makes it the natural baseline whenever someone has to explain a prediction. It is also the base learner for random forests and gradient boosting, so this structure is the atom of the next two modules.
In the real world: A loan decision as a flowchart: income over ₹50,000? Existing loans? Missed payments? Each path ends in approve or decline.
Visual example
DecisionTreeClassifier(max_depth=2)One tree, written as the table of its nodes. Prediction is a walk down the go left if true column until a leaf.
Where node 3's probability comes from
18 training rows reached node 3: 5 benign, 13 malignant
predict_proba = 13/18 = 0.72 — literally the leaf's class proportion
n = 18 out of 455, so this probability rests on 4% of the data
Why this matters
A leaf's prediction is just a count of the training rows that fell into it. That is why a deep tree's confident probabilities are untrustworthy: its leaves hold two or three rows each.
Common misconception
Wrong idea: predict_proba from a tree is a calibrated probability.
Correct idea: it is the class fraction of one leaf's training rows. A pure leaf reports 1.00 whether it held 300 rows or 3.
- 1Start at the rootNode 0 tests one feature against one threshold.
- 2Answer and descendTrue goes left, false goes right; one test per level.
- 3Stop at a leafThe leaf's stored training distribution is the prediction.
from sklearn.tree import DecisionTreeClassifier, export_text
tree = DecisionTreeClassifier(max_depth=3, random_state=0).fit(X_train, y_train)
print(export_text(tree, feature_names=list(feature_names)))
# |--- worst radius <= 16.80
# | |--- worst concave points <= 0.14
# | | |--- class: 1
# | |--- class: 0
tree.tree_.node_count # how many nodes it actually grew
tree.get_depth(), tree.get_n_leaves()Reading a tree's printed rules as an explanation of the *problem* rather than of the *fit*. Two trees grown on 95% overlapping data can pick entirely different root features and produce near-identical accuracy — the rules are one of many equally good descriptions, not the discovered truth.