Decision Trees

A decision tree predicts by asking a sequence of yes/no questions about the features — "is income ≤ 52k?", "is age ≤ 25?" — until it reaches a leaf that holds a prediction. Trees handle numeric and categorical inputs, need no feature scaling, capture interactions and non-linearities automatically, and can be read by a human. On their own they overfit easily; as building blocks they power the strongest tabular models in use today, Random Forest and Gradient Boosting.

This page focuses on classification trees (CART) under Classification; regression trees use the same algorithm with a variance criterion.



1. Structure of a Tree

A Fitted Decision Tree (Depth 2) income ≤ 52k ?gini 0.48 · n = 1000 debt_ratio ≤ 0.4 ?gini 0.41 · n = 560 age ≤ 25 ?gini 0.22 · n = 440 Approvep(default)=0.12 Rejectp(default)=0.71 Reviewp(default)=0.38 Approvep(default)=0.05 yes no yes no yes no Internal nodes test one feature against one threshold; leaves store a class distribution.

A tree is a binary graph. Each internal node holds a test xj ≤ t on a single feature; samples that pass go left, the rest go right. Each leaf stores the class counts of the training samples that landed there, so the tree can output both a hard label (the majority class) and a probability (the class fraction). Prediction is a walk from root to leaf: O(depth) comparisons, which makes trees very cheap at inference time.

The example shows why trees are popular in regulated settings: the path to "Reject" is literally income ≤ 52k and debt_ratio > 0.4. That explanation is exact, not an approximation — as long as the tree stays small.

2. How Splits Are Chosen

CART builds the tree greedily, top-down. At each node it tries every feature and every candidate threshold (midpoints between sorted unique values) and picks the split that most reduces impurity. For a node with class proportions pk:

The split score is the weighted child impurity: (nL/n)·I(L) + (nR/n)·I(R); the best split minimizes it. Gini and entropy almost always pick similar splits; Gini is slightly cheaper to compute. Recursion stops when a node is pure, hits max_depth, has fewer than min_samples_split samples, or no split improves impurity by at least min_impurity_decrease.

Finding the optimal tree is NP-hard, so the greedy algorithm is a heuristic: it can miss splits that only pay off two levels down (the classic XOR problem). Ensembles compensate for this by averaging or sequentially correcting many greedy trees.

3. Geometry: Axis-Aligned Partitions

Recursive Splits Carve Axis-Aligned Rectangles split 1: x₁ ≤ t₁ split 2a split 2b Each split: one feature, one threshold Result: boxes, never diagonal lines Leaf prediction: majority class in the box A diagonal true boundary needs many small steps (a staircase), which is one reason single trees overfit.

Every split is perpendicular to one feature axis, so a tree partitions the feature space into axis-aligned hyper-rectangles and predicts a constant in each. This gives trees two useful properties: they are invariant to monotone transforms of each feature (log, rank, scaling change nothing), and they handle interactions naturally (split 2a and 2b above can use different features).

The downside is that a diagonal or curved boundary must be approximated by a staircase of many small boxes. A linear model such as Logistic Regression represents the same boundary with a handful of parameters, which is why trees and linear models often have complementary strengths.

4. Overfitting, Depth and Pruning

Tree Depth vs Error: Where Overfitting Starts max_depth error best depth underfit overfit Blue: training error → 0 Yellow: validation error Fix: max_depth, min_samples_leaf, ccp_alpha pruning, or ensembles

Grown to full depth, a tree keeps splitting until each leaf is pure, which memorizes noise: training error goes to zero while validation error climbs. Trees are also high-variance — a small change in the data can change the root split and therefore the whole tree. Controls:

5. Python Example (scikit-learn)


import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.tree import DecisionTreeClassifier, export_text

X, y = load_breast_cancer(return_X_y=True, as_frame=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.25, stratify=y, random_state=0)

# 1) Full-depth tree: perfect on train, worse on test
full = DecisionTreeClassifier(random_state=0).fit(X_tr, y_tr)
print("full  depth", full.get_depth(), "train", full.score(X_tr, y_tr), "test", round(full.score(X_te, y_te), 3))

# 2) Cost-complexity pruning, alpha chosen by CV
path = full.cost_complexity_pruning_path(X_tr, y_tr)
grid = GridSearchCV(
    DecisionTreeClassifier(random_state=0),
    {"ccp_alpha": np.unique(path.ccp_alphas), "min_samples_leaf": [1, 5, 10]},
    cv=5,
).fit(X_tr, y_tr)
best = grid.best_estimator_
print("pruned depth", best.get_depth(), "leaves", best.get_n_leaves(),
      "test", round(best.score(X_te, y_te), 3))

# 3) Human-readable rules and impurity-based importances
print(export_text(best, feature_names=list(X.columns), max_depth=3))
imp = sorted(zip(best.feature_importances_, X.columns), reverse=True)[:5]
for v, name in imp:
    print(f"{name:<25} {v:.3f}")

export_text prints the tree as nested if/else rules. For plots use sklearn.tree.plot_tree. Impurity-based importances are fast but biased toward high-cardinality features; prefer sklearn.inspection.permutation_importance on held-out data when importance matters.

6. When to Use It — Trade-offs

StrengthLimitation
No scaling; mixed feature types; robust to monotone transforms and outliers in X.High variance — unstable to small data changes.
Captures interactions and non-linear thresholds automatically.Staircase approximation of smooth or diagonal boundaries.
Transparent rules when shallow.Cannot extrapolate beyond the training range (constant leaves).
Fast inference; the base learner for RF, XGBoost, LightGBM.Single trees are rarely the most accurate model.

Use a single, shallow tree when the rules themselves are the deliverable (eligibility logic, triage, a model a domain expert must audit) or to explore which features and thresholds matter. When accuracy is the goal, use a tree ensemble.

7. Common Pitfalls