Part 4 — Tree-based Models Lesson 16 / 56
Estimated Reading: 15–18 mins Level: Intermediate

Decision Trees: Learning from Data

Hierarchical Partitioning, Recursive Binary Splitting, Gini Impurity, Information Gain, and Cost-Complexity Pruning

Core Learning Objectives

Transition from linear decision boundaries to non-linear hierarchical decision rules; dissect the tree anatomy (Root, Decision Node, Branch, Leaf, Depth); master splitting metrics (Gini Impurity, Shannon Entropy, and Information Gain); differentiate Classification Trees from Regression Trees; explore piecewise constant step functions; tame overfitting using hyperparameters (max_depth, min_samples_leaf, and ccp_alpha); build Scikit-Learn pipelines; visualize tree rules; and rigorously evaluate Mean Decrease in Impurity (MDI) feature importance.

1. Introduction: Beyond Linear Boundaries

In the previous lesson, we learned Logistic Regression, which maps continuous scores to probabilities via the Sigmoid curve. However, Logistic Regression assumes a linear relationship between input features and the log-odds of the positive class. In original feature space, its decision boundary is strictly a flat hyperplane ($\mathbf{w}^T \mathbf{x} + b = 0$).

In reality, human decision-making and natural phenomena rarely follow flat diagonal hyperplanes. Consider how a loan officer evaluates an applicant:

  • "Is the applicant's credit score greater than 700?" $\rightarrow$ If Yes, check: "Is monthly income $\ge$ BDT 60,000?"
  • If No, check: "Do they have a co-signer with verified collateral?"

This sequence of hierarchical, conditional if-else questions mirrors the internal mechanics of a Decision Tree. Decision Trees are intuitive, non-parametric supervised algorithms that recursively partition feature space into orthogonal, axis-aligned boxes. They solve both Classification and Regression tasks without requiring feature scaling or linear assumptions.

🏦 Loan Approval Decision Tree Flow
Root Node Credit Score $\ge$ 700?
Decision Node (Depth 1) Monthly Income $\ge$ 50k?
Leaf Node (Outcome) Approve Loan (Class 1)

2. The Architectural Anatomy of a Decision Tree

To master Decision Trees, one must understand their structural building blocks:

Component Architectural Definition Role in Inference & Training
Root Node The very top node containing 100% of the training observations ($N$). Performs the very first feature split that maximizes impurity reduction.
Decision Node (Internal) Any intermediate node that evaluates a feature threshold (e.g. $x_j \le \theta$). Divides arriving data into two child branches (binary split).
Branch (Edge) The pathway connecting a parent node to a child node. Represents the outcome of a conditional test (True / False).
Leaf Node (Terminal) An end node with no children. Outputs the final prediction (majority class or regional mean).
Tree Depth The longest path from the root node to any leaf. Primary governor of model complexity and capacity.

3. Classification Trees vs. Regression Trees

While both tree variants share identical recursive hierarchical structures, their split criteria and prediction engines differ fundamentally:

Classification Tree (CART)
  • Target Output: Discrete category $y \in \{0, 1, \dots, K-1\}$.
  • Splitting Objective: Minimize node class impurity (Gini Impurity or Shannon Entropy).
  • Leaf Prediction: The mode (majority class) or empirical class probabilities $\hat{p}_k = \frac{n_k}{N_{\text{leaf}}}$.
  • Evaluation Metrics: Accuracy, Precision, Recall, F1-Score, ROC-AUC.
Regression Tree (CART)
  • Target Output: Continuous real numerical value $y \in \mathbb{R}$.
  • Splitting Objective: Minimize Mean Squared Error (MSE / Variance reduction) or MAE.
  • Leaf Prediction: The empirical sample mean $\bar{y}_{\text{leaf}} = \frac{1}{N_{\text{leaf}}} \sum_{i \in \text{leaf}} y_i$.
  • Evaluation Metrics: MAE, MSE, RMSE, $R^2$ Score.

4. Splitting Criteria: Gini Impurity, Shannon Entropy & Information Gain

How does a Decision Tree decide which feature and which numerical threshold to split on? It systematically tests every candidate threshold for every feature and picks the split that yields the highest reduction in impurity.

4.1 Gini Impurity ($I_G$)

Gini Impurity measures the probability that a randomly chosen sample from a node would be incorrectly classified if randomly labeled according to the class distribution within that node:

$$I_G(t) = 1 - \sum_{k=1}^K p_k^2$$

Where $K$ is the number of classes, and $p_k$ is the fraction of samples in node $t$ belonging to class $k$.

Pure Node ($I_G = 0$) All samples belong to a single class ($p_1 = 1.0 \implies 1 - 1^2 = 0$). Zero uncertainty!
Maximum Impurity ($I_G = 0.50$) For binary classes, a 50/50 split yields $1 - (0.5^2 + 0.5^2) = 0.50$. Maximum uncertainty.

4.2 Shannon Entropy ($H$)

Borrowed from Claude Shannon's Information Theory, Entropy measures the average level of "information", surprise, or uncertainty in a random variable:

$$H(t) = -\sum_{k=1}^K p_k \log_2(p_k)$$

By convention, if $p_k = 0$, then $0 \log_2(0) \equiv 0$. For a pure binary node, $H(t) = 0$ bits. For a 50/50 binary split, $H(t) = -[0.5 \log_2(0.5) + 0.5 \log_2(0.5)] = 1.0$ bit.

4.3 Information Gain (Impurity Reduction)

When a parent node $t$ is split into left child $t_L$ and right child $t_R$, the Information Gain (IG) is the difference between parent impurity and weighted child impurities:

$$\text{IG}(t, \text{split}) = I(t) - \left( \frac{N_L}{N_t} I(t_L) + \frac{N_R}{N_t} I(t_R) \right)$$
📐 Step-by-Step Numerical Calculation
Parent Node: $N = 100$ samples (80 Positive, 20 Negative).
$$I_G(\text{parent}) = 1 - (0.80^2 + 0.20^2) = 1 - (0.64 + 0.04) = 0.320$$
Candidate Split ($x_1 \le 3.5$):
  • Left Child ($t_L$): $N_L = 40$ (40 Positive, 0 Negative) $\implies I_G(t_L) = 1 - (1.0^2 + 0^2) = 0.000$ (Pure!)
  • Right Child ($t_R$): $N_R = 60$ (40 Positive, 20 Negative) $\implies I_G(t_R) = 1 - \left[\left(\frac{40}{60}\right)^2 + \left(\frac{20}{60}\right)^2\right] = 1 - \left(\frac{4}{9} + \frac{1}{9}\right) = \frac{4}{9} \approx 0.444$
Weighted Child Impurity: $\frac{40}{100}(0.000) + \frac{60}{100}(0.444) = 0.267$
$$\text{Information Gain} = 0.320 - 0.267 = 0.053$$

The CART algorithm repeats this calculation across all possible thresholds on all features and chooses the split that yields the maximum Information Gain.

5. The Recursive Binary Splitting Algorithm

Decision Trees grow using a Greedy Top-Down Recursive Partitioning strategy:

  1. Greedy Choice: At each node, the algorithm identifies the single best feature and split point that maximizes immediate impurity reduction. It does not look ahead to see if a sub-optimal current split might lead to a superior overall tree later.
  2. Continuous Thresholds: For a continuous feature with $N$ unique values, the algorithm sorts the values and tests the $N-1$ midpoints between adjacent samples: $\theta_i = \frac{x_{(i)} + x_{(i+1)}}{2}$.
  3. Recursion: The data is partitioned into two disjoint subsets. The algorithm repeats the exact same procedure recursively on both subsets.
  4. Stopping Conditions: Recursion stops when a node is 100% pure ($I = 0$), reaches max_depth, has fewer samples than min_samples_split, or the impurity reduction drops below min_impurity_decrease.

6. Regression Trees & Piecewise Constant Prediction

In Regression Trees, the splitting objective is to minimize the total Mean Squared Error:

$$\text{MSE}(t) = \frac{1}{N_t} \sum_{i \in t} (y_i - \bar{y}_t)^2$$

Where $\bar{y}_t$ is the arithmetic average of target values in node $t$.

Crucial Insight: Piecewise Constant Staircases

Unlike Linear or Polynomial Regression which output smooth continuous slopes, a Regression Tree partitions feature space into distinct flat regions $R_1, R_2, \dots, R_M$. For any query $\mathbf{x} \in R_m$, the prediction is strictly constant ($\hat{y} = \bar{y}_m$). Consequently, a 1D Regression Tree curve resembles a staircase (step function).

7. Hyperparameter Tuning & Overfitting Control

If allowed to grow without constraints, a Decision Tree will continue splitting until every single training point occupies its own leaf node ($I_G = 0$). This achieves 100% training accuracy but results in catastrophic overfitting—memorizing noise and failing on new test data.

max_depth Default: None (Infinite)
Caps the maximum distance from root to leaf. Restricting depth (e.g. 3–5) is the single most effective way to prevent deep, overfit branches.
min_samples_split Default: 2
The minimum number of samples a node must contain to consider splitting. Higher values (e.g. 10–20) prevent splitting on isolated noise points.
min_samples_leaf Default: 1
The minimum number of samples required to form a leaf node. Setting this to 5–10 guarantees that predictions represent statistical consensus rather than 1 outlier.
ccp_alpha (Cost-Complexity Pruning) Default: 0.0
Post-pruning penalty parameter: $R_\alpha(T) = R(T) + \alpha |T|$, where $|T|$ is the number of terminal leaves. Prunes branches whose impurity reduction does not justify their complexity.

8. Complete Scikit-Learn Python Pipeline

Below is a complete, production-grade workflow demonstrating synthetic classification data creation, 70/15/15 stratified partitioning, validation depth tuning, tree visualization, and out-of-sample evaluation:

decision_tree_pipeline.py Python 3.10+ · Scikit-Learn 1.3+
# Step 1: Scientific & Machine Learning Imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score,
    f1_score, classification_report, confusion_matrix
)

# Step 2: Generate Synthetic Customer Churn Dataset (1,000 samples, 5 features)
X, y = make_classification(
    n_samples=1000,
    n_features=5,
    n_informative=3,
    n_redundant=1,
    n_classes=2,
    weights=[0.70, 0.30],
    random_state=42
)
feature_names = ["income", "age", "credit_score", "visits", "prev_default"]

# Step 3: Stratified 70/15/15 Partitioning (Train, Validation, Test)
X_train, X_temp, y_train, y_temp = train_test_split(
    X, y, test_size=0.30, random_state=42, stratify=y
)
X_val, X_test, y_val, y_test = train_test_split(
    X_temp, y_temp, test_size=0.50, random_state=42, stratify=y_temp
)
print(f"Partition Sizes: Train={len(X_train)}, Val={len(X_val)}, Test={len(X_test)}")

# Step 4: Hyperparameter Tuning: Select Optimal Depth on Validation Set
candidate_depths = [1, 2, 3, 4, 5, 7, 10, None]
best_depth = 3
best_val_f1 = 0.0

for d in candidate_depths:
    tree = DecisionTreeClassifier(
        criterion="gini",
        max_depth=d,
        min_samples_leaf=5,
        random_state=42
    )
    tree.fit(X_train, y_train)
    val_pred = tree.predict(X_val)
    f1 = f1_score(y_val, val_pred, zero_division=0)
    if f1 > best_val_f1:
        best_val_f1 = f1
        best_depth = d

print(f"Selected Optimal Depth: {best_depth} (Validation F1 = {best_val_f1:.3f})")

# Step 5: Refit Selected Model on Combined Development Set (Train + Val)
X_dev = np.vstack([X_train, X_val])
y_dev = np.concatenate([y_train, y_val])

final_model = DecisionTreeClassifier(
    criterion="gini",
    max_depth=best_depth,
    min_samples_leaf=5,
    random_state=42
)
final_model.fit(X_dev, y_dev)

# Step 6: Final Unseen Test Evaluation
y_test_pred = final_model.predict(X_test)
print(f"\n=== FINAL TEST EVALUATION (Depth = {best_depth}) ===")
print(f"Accuracy  : {accuracy_score(y_test, y_test_pred):.4f}")
print(f"Precision : {precision_score(y_test, y_test_pred, zero_division=0):.4f}")
print(f"Recall    : {recall_score(y_test, y_test_pred, zero_division=0):.4f}")
print(f"F1-Score  : {f1_score(y_test, y_test_pred, zero_division=0):.4f}")
print(f"\nConfusion Matrix:\n{confusion_matrix(y_test, y_test_pred)}")

# Step 7: Inspect Feature Importances (Mean Decrease in Impurity)
importances = pd.DataFrame({
    "Feature": feature_names,
    "Importance": final_model.feature_importances_
}).sort_values(by="Importance", ascending=False)
print(f"\nFeature Importance Breakdown:\n{importances}")

9. Feature Importance: Mechanics & Pitfalls

Scikit-Learn computes feature importance using Mean Decrease in Impurity (MDI):

$$\text{Importance}(x_j) = \frac{\sum_{t \in \text{splits on } x_j} N_t \cdot \Delta I(t)}{\sum_{t \in \text{all splits}} N_t \cdot \Delta I(t)}$$

The score represents the total weighted impurity reduction brought about by feature $x_j$ normalized to sum to $1.0$.

1. High Cardinality Bias Features with many unique values (e.g. user ID, timestamp) offer numerous candidate split points, giving the greedy algorithm more chances to reduce impurity purely by chance. MDI unfairly inflates their importance!
2. Correlated Feature Masking If two features carry identical information, the tree may arbitrarily pick the first one at the root. The second feature's importance drops to near zero despite being equally predictive.
3. Association vs. Causality High feature importance proves that a feature was useful for partitioning the sample data; it does not prove that altering that feature will causally change the target outcome in the real world.

10. Decision Tree Regression with Scikit-Learn

Predicting continuous outcomes (e.g. apartment price based on square footage) using DecisionTreeRegressor:

from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# Fit Regression Tree with bounded depth to prevent extreme step overfitting
reg_tree = DecisionTreeRegressor(
    max_depth=3,
    min_samples_leaf=5,
    criterion="squared_error",
    random_state=42
)
reg_tree.fit(X_train[:, :1], y_train)

# In-Sample & Out-of-Sample Predictions
y_pred = reg_tree.predict(X_test[:, :1])
print(f"MAE : {mean_absolute_error(y_test, y_pred):.2f}")
print(f"RMSE: {np.sqrt(mean_squared_error(y_test, y_pred)):.2f}")
print(f"R²  : {r2_score(y_test, y_pred):.3f}")

11. Advantages & Architectural Limitations

✅ Core Advantages
  • White-Box Explainability: Shallow trees can be transcribed into intuitive if-else rule sheets for non-technical stakeholders.
  • Non-Linear Boundary Modeling: Naturally captures complex interactions without manual polynomial expansions.
  • Invariant to Monotonic Transforms: Scaling (StandardScaler) is completely unnecessary because splits depend strictly on ordering, not magnitudes.
  • Handles Mixed Types: Gracefully processes numerical and encoded categorical variables.
❌ Architectural Limitations
  • High Variance & Instability: Changing a single data point can tilt the root split and completely mutate the entire downstream tree.
  • Greedy Sub-Optimality: Locally optimal splits at depth 1 do not guarantee globally optimal trees (NP-complete problem).
  • Step Discontinuity: Regression trees cannot generate smooth slopes or extrapolate trends outside $[x_{\min}, x_{\max}]$.
  • Diagonal Boundary Inefficiency: Modeling a smooth diagonal boundary ($x_1 = x_2$) requires hundreds of stair-stepped orthogonal splits.

12. Head-to-Head: Logistic Regression vs. Decision Trees

Dimension Logistic Regression Decision Tree
Primary Tasks Classification & Probability Estimation Both Classification & Regression
Decision Boundary Strictly Linear Hyperplane ($\mathbf{w}^T \mathbf{x} + b = 0$) Piecewise Orthogonal (Axis-Aligned Boxes)
Feature Scaling Required? Yes (Critical for regularized gradient descent) No (Order-invariant threshold tests)
Interpretability Multiplicative Odds Ratios ($e^{w_j}$) Human-readable if-then visual tree rules
Overfitting Control $L_1$ / $L_2$ Regularization ($\lambda$) Max Depth, Min Leaf Samples, Cost-Complexity Pruning
Interactive Simulator

Decision Tree Laboratory

Experiment with Gini impurity splitting, observe depth-induced boundary overfitting, and explore regression step predictions live

2.5 hrs
Left: Study Hours $\le \theta$ | Right: Study Hours $\gt \theta$
Impurity Metric Criterion:
Exam Pass / Fail Dataset ($N = 100$ Students)
Passed (Class 1) Failed (Class 0) Split Cutoff
Parent Impurity 0.480
Left Child Impurity 0.095
Right Child Impurity 0.142
Information Gain +0.358

13. Summary & Key Takeaways

Hierarchical Tree Structure Begins at the Root Node, branches through Decision Nodes via threshold tests, and terminates at Leaf Nodes with predictions.
Impurity Reduction Objectives Classification trees maximize Information Gain via Gini Impurity or Shannon Entropy; regression trees minimize residual variance (MSE).
Overfitting Vulnerability Unconstrained trees overfit completely. Restrict depth (max_depth) and require minimum leaf occupancy (min_samples_leaf).
No Feature Scaling Required Because splits are monotonic threshold evaluations ($x \le \theta$), standardization or normalization has zero mathematical impact on tree structure.
Next Lesson · Ensemble Learning

Lesson 15.17: Random Forests & Ensemble Learning

A single Decision Tree suffers from high variance and instability. What if we combined hundreds of decorrelated trees through Bootstrap Aggregation (Bagging) and feature randomness? Next, we unlock the tremendous predictive power of Random Forests.

Proceed to Next Lesson