Part II · Chapter 6

Decision trees

After this page you can take a table of labelled examples, build the decision tree by hand the way the algorithm would, compute its training error, and say exactly why the error-rate splitting criterion has to be thrown away.

Essentials

How to build a decision tree from labelled examples by hand, and why the error-rate splitting criterion has to be thrown away.

Everything below is the explanation and the practice. If you are short on time, read this box, then go to the problems.

The apartment problem

Four hundred apartments are listed and you cannot tour four hundred. You need a cheap rule that says go see this one or skip it, explainable to your roommate. So you write one down — not as a formula, but as a sequence of questions:

Figure 1 · The hand-written apartment tree
YesNo YesNo YesNo YesNo YesNo Rent low? Deposit low? Within 1miof campus? Within 2miof campus? Near bus stop? ✓ ✓ ✗ ✓ ✓ ✗ ✓ = go see it    ✗ = skip it    boxes = internal nodes (questions)    circles = leaves (answers)
What to notice: nothing here is symmetric. The No side of "Rent low?" is willing to accept an expensive place only if it is really close to campus (1 mile); the Yes side, having already saved money on rent, is far more forgiving — it will walk 2 miles, or take a bus. The tree encodes that trade-off without ever writing a utility function.

Read it out loud and it is a policy: if the rent is low and the deposit is low, go; if the rent is low, the deposit high, but you are within 2 miles, go; if the rent is high, you only bother within a mile. That is a decision tree.

Anatomy, and what interpretability actually buys you

Definition

A decision tree is a hypothesis function $\hat y = h(x)$ built from two kinds of node:

Key idea

Major benefit: human interpretable. You can print a decision tree on one page, hand it to someone with no mathematical training, and they can both execute it and argue with it.

Concretely, you can audit it ("rejected because the deposit was high and it's 2.3 miles out"), debug it, deploy it legally where decisions must be justified, and edit it by hand. The cost is accuracy on hard problems: trees carve feature space into axis-aligned boxes (see below), so a diagonal rule costs a staircase of splits.

Rule-based vs. learned: the actual ML question

Where did Figure 1 come from? You made it up: you already knew rent matters more than bus access, and you guessed the thresholds. That is a rule-based approach, legitimate when you have the rules. The notes' objection is two-part:

Key idea

The ML question for this chapter: given a set of labelled examples, how do you construct a decision tree?

Everything that follows — stumps, majority vote, the recursion, BestAttribute, entropy in Chapter 7 — is an answer to that one question.

What the examples comprise

First say precisely what one "example" is. In the apartment problem:

Written formally, exactly as the notes have it:

$$N = \#\text{ prospective apartments},\qquad \X = \{\text{Yes},\text{No}\}^5 = \{0,1\}^5, \qquad \Y = \{Y, N\} = \{0,1\}$$
Common mistake

$N$ counts examples (rows), not attributes. $\X$ is the input space: all possible $x$, not the ones you have — $\{0,1\}^5$ has $2^5 = 32$ elements while your dataset might hold 12 apartments, some repeated. And the superscript in $x^{(i)}$ is an index, not a power: $x^{(3)}_2$ is the third apartment's answer to question 2, subscript for attributes, parenthesised superscript for examples.

Now generalise. For the rest of the chapter:

$$\X = \{0,1\}^d \ \ (d \text{ binary attributes}), \qquad \Y = \{0,1\}$$

Inference: running a new point down the tree

Prediction is trivial, and that is the point. Given a new apartment $x^{(\mathrm{new})} \in \X$: start at the root, answer the question, follow the matching branch, repeat, and output the label of the leaf you land in.

Example

Take $x^{(\mathrm{new})} = (\text{rent low}=\text{Yes},\ \text{deposit low}=\text{No},\ \text{1mi}=\text{No},\ \text{2mi}=\text{No},\ \text{bus}=\text{Yes})$.

Root "Rent low?" → Yes → "Deposit low?" → No → "Within 2mi of campus?" → No → "Near bus stop?" → Yes → leaf $\checkmark$.

Go see it. Cost: four comparisons. Note that attribute "Within 1mi" was never even read — a tree only looks at the features it needs, which is another quiet advantage over models that must evaluate every coordinate.

A tree over $d = 5$ binary attributes has depth 3 along the path a particular $x$ takes. How many of the 5 attribute values of that $x$ did the tree actually need to look at?
Why: Inference reads one attribute per internal node it passes through, so a depth-3 path reads at most 3 attributes (fewer if the tree reuses an attribute). The model is defined for all of $\{0,1\}^5$, but it consumes only what its path needs. This is why trees are cheap at test time and why they cope gracefully with features that are expensive to measure — an unused feature never has to be collected.

The key building block: the decision stump

Trees are recursive, so start with the smallest tree that still does something — the notes' key building block:

Definition

A decision stump is a decision tree with exactly one split: a single internal node "Is a certain attribute $= 1$?" branching straight into two leaves, each carrying a chosen output label.

Figure 2 · The decision stump, the atom of every tree
Yes No Is a certain attribute = 1? some chosen output label some chosen output label Two free choices: WHICH attribute, and WHICH label goes in each leaf.
What to notice: a stump has exactly two degrees of freedom — the attribute at the node and the two leaf labels. With $d$ binary attributes and binary labels there are only $d \times 2 \times 2 = 4d$ possible stumps, so you can brute-force the best one.

Constructing a stump, in three steps

The pre-reading gives the recipe:

  1. Select the attribute and split criterion. Which feature does the node test, and what test? For binary features the test is just "$x_b = 1$?"; for real-valued features you also pick a threshold.
  2. Split the training dataset into subsets by passing each training point through the decision node. Each leaf then holds a subset of the training data.
  3. Each leaf predicts by majority vote among the output values $y^{(i)}$ of the points that landed there. A tie-breaking scheme must be specified.
Definition

Majority vote. Given a leaf's subset of training points, each with a discrete label $y^{(i)} \in \Y$:

$$\hat y \;=\; \argmax_{k \in \Y} \; \sum_i \1\!\left(y^{(i)} = k\right)$$

Symbol by symbol: $\1(\cdot)$ is the indicator function, $1$ when the statement inside is true and $0$ otherwise, so $\sum_i \1(y^{(i)} = k)$ counts the points in this leaf with label $k$ and $\argmax_k$ returns the label with the biggest count — the class that appears most often in the leaf's training subset.

Common mistake

$\argmax$ returns the argument (which label), not the value (how many). If a leaf holds labels $\{0,0,1\}$, then $\sum_i \1(y^{(i)}=0) = 2$ and $\sum_i \1(y^{(i)}=1)=1$, so the $\max$ is $2$ but the $\argmax$ — and therefore $\hat y$ — is $\mathbf{0}$.

And notice why a tie-break rule is genuinely needed: with labels $\{0,0,1,1\}$ the $\argmax$ is not unique, so the formula alone does not define $\hat y$. Convention used throughout this guide: on a tie, predict $1$. Any fixed rule works; what is unacceptable is leaving it unstated, because then two people compute different training errors for the same tree.

Why majority vote is the right leaf label

Proof

Claim: among all constant predictors on a leaf, majority vote minimises the number of training mistakes on that leaf.

Let the leaf hold $n_k$ points of label $k$, with $n = \sum_k n_k$ total. A constant predictor $\hat y = c$ is wrong on every point whose label is not $c$, so it makes

$$\text{mistakes}(c) \;=\; n - n_c$$

mistakes. Since $n$ is fixed, minimising $n - n_c$ over $c$ is the same as maximising $n_c$ over $c$, and $\argmax_c n_c$ is exactly the majority vote. $\blacksquare$

This is why leaves are never a design decision: given the tree's structure, the optimal leaf labels are forced. All the intelligence in tree learning lives in choosing the splits.

The recursive construction algorithm

From a stump to a tree is one idea: do it again on each leaf. Each leaf holds a subset; run the stump procedure on that subset; repeat until a stopping criterion fires. The algorithm exactly as the notes state it:

Algorithm 1  Decision Tree Construction

1: function DT(dataset S, set of attributes A ⊆ {1, 2, ..., d})
2:     if A = ∅  or  all examples in S have the same label then
3:         return a leaf with value = majority vote of labels in S
4:     end if
5:     let b = BestAttribute(S, A) ∈ A
6:     let LeftNode  = DT( {(x,y) ∈ S | x_b = 1},  A \ {b} )
7:     let RightNode = DT( {(x,y) ∈ S | x_b = 0},  A \ {b} )
8:     return the tree           "Is the b-th attribute equal to 1?"
                                    /  Yes            No  \
                                LeftNode            RightNode
9: end function

It is called initially with the whole training set and the whole attribute list:

$$S = \{(x^{(i)}, y^{(i)})\}_{i=1}^{N}, \qquad A = \{1, 2, \dots, d\}$$

The recursion in words, line by line

Figure 3 · The call tree of DT on the 8-row dataset (the recursion, not the model)
x₂=0 (No)x₂=1 (Yes) x₁=0x₁=1 DT( S = all 8 rows, A = {1,2,3} ) DT( rows 1,2,3,4, A = {1,3} ) DT( rows 5,6,7,8, A = {1,3} ) DT( row 4, A={3} ) pure → leaf 1 DT( rows 1,2,3, A={3} ) pure → leaf 0 all labels = 1 → base case → leaf 1 Orange = a call that recursed (it chose an attribute). Teal = a call that hit a base case and returned a leaf. Note $A$ shrinks by one attribute at every level — that is the termination argument.
What to notice: the call tree and the model tree have the same shape. Every recursive call becomes an internal node; every base case becomes a leaf. Drawing the recursion is drawing the tree.

A wrinkle worth naming: "Is $x_b = 1$?" vs "Is $x_b = 0$?"

The pseudocode always asks "Is $x_b = 1$?", while the notes' worked example asks "Is $x_2 = 0$?". Not different algorithms: "is it 0?" is the same split with the branches swapped. The phrasing is cosmetic — keep the partition straight and the labels take care of themselves.

BestAttribute, version 1: minimise training error

We need to fill in BestAttribute. The notes' first proposal is the most obvious one:

Key idea

Pretend you are allowed only one split — i.e. you must produce a decision stump. Then ask: which choice of attribute to split on (and which labels for the two resulting leaves) gives the lowest training error? Pick that attribute.

A finite search you can do by hand: for each $b \in A$, split $S$ into the $x_b = 1$ and $x_b = 0$ groups, majority-vote each, add the mistakes; smallest total wins. Leaf labels need no separate search — majority vote is already optimal given the split — so "choose attribute and labels" collapses to "choose attribute".

The poll example, solved completely

The notes pose this question and answer only "In poll." Here is the full answer, every split, every count.

Example

Training data. $N = 8$, $d = 3$, all attributes and labels binary. I have added a row index $i$; the notes give only the four columns.

$i$$y$$x_1$$x_2$$x_3$
10100
20101
30100
41001
51110
61111
71110
81111

Question. Which attribute does BestAttribute pick at the root under the training-error criterion? And what is the final tree?

Step 0 — the root before any split

Rows 1, 2, 3 have $y=0$ and rows 4–8 have $y=1$: 3 zeros, 5 ones. Majority-voting the whole dataset without splitting predicts $\hat y = 1$ and is wrong on the 3 zeros — a baseline training error of $3/8$, which any split has to beat.

Step 1 — try every attribute as a stump

Split onBranchRows that land thereLabelsCounts (0 / 1)Majority vote $\hat y$Mistakes
$x_1$$x_1 = 1$1, 2, 3, 5, 6, 7, 80,0,0,1,1,1,13 / 413
$x_1 = 0$410 / 110
$x_2$$x_2 = 1$5, 6, 7, 81,1,1,10 / 410
$x_2 = 0$1, 2, 3, 40,0,0,13 / 101
$x_3$$x_3 = 1$2, 4, 6, 80,1,1,11 / 311
$x_3 = 0$1, 3, 5, 70,0,1,12 / 21 (tie → 1)2

Adding the two branches of each split gives the totals:

AttributeMistakes on $x_b=1$ sideMistakes on $x_b=0$ sideTotal training errorBeats the $3/8$ baseline?
$x_1$30$3/8 = 0.375$no — ties it
$x_2$01$\mathbf{1/8 = 0.125}$yes
$x_3$12$3/8 = 0.375$no — ties it
Key idea

$x_2$ is the best first split, $1/8$ against $3/8$ for the other two, because the $x_2 = 1$ side is perfectly pure — all four rows there have $y=1$ — so that branch is finished in one step.

Step 2 — recurse on the impure branch

The calls are DT({rows 5,6,7,8}, A = {1,3}) and DT({rows 1,2,3,4}, A = {1,3}).

The $x_2 = 1$ branch holds rows 5–8, all with $y = 1$: line 2 fires, return a leaf with value $1$. The $x_2 = 0$ branch holds rows 1–4 with labels $0,0,0,1$ — not pure, and $A = \{1,3\}$ is not empty, so recurse on:

$i$$y$$x_1$$x_3$
1010
2011
3010
4101
Split onBranchRowsLabelsMajority $\hat y$MistakesTotal
$x_1$$x_1=1$1, 2, 30,0,0000 / 4
$x_1=0$4110
$x_3$$x_3=1$2, 40,11 (tie)11 / 4
$x_3=0$1, 30,000

$x_1$ resolves this node completely. Both of its children are pure, so both are immediately leaves, and the recursion stops.

Step 3 — the finished tree

Assembling the pieces gives exactly the tree in the notes (written in the notes' "Is $x_2 = 0$?" phrasing):

Figure 4 · The learned tree for the poll dataset
YesNo YesNo Is x₂ = 0? Is x₁ = 0? Label 1 Label 1 Label 0 rows 5,6,7,8 (4 ones) row 4 (1 one) rows 1,2,3 (3 zeros) Every leaf is pure → training error 0.
What to notice: attribute $x_3$ never appears. The algorithm used two of three attributes and stopped, because both base cases (purity) fired. Unused attributes are not a bug — they are the tree telling you $x_3$ carried no information it needed.

Step 4 — verify zero training error by running all 8 rows through it

$i$$x_1$$x_2$$x_3$Path through the tree$\hat y$$y$$\1(y \ne \hat y)$
1100$x_2{=}0$ Yes → $x_1{=}0$ No000
2101$x_2{=}0$ Yes → $x_1{=}0$ No000
3100$x_2{=}0$ Yes → $x_1{=}0$ No000
4001$x_2{=}0$ Yes → $x_1{=}0$ Yes110
5110$x_2{=}0$ No110
6111$x_2{=}0$ No110
7110$x_2{=}0$ No110
8111$x_2{=}0$ No110

The last column sums to $0$, so the error rate is $\tfrac{1}{8}\cdot 0 = 0$: a perfect fit to this training set. (Whether that is good is another question — see stopping criteria.)

Guided problemWhat if we had been forced to split on $x_3$ first?

Suppose a stubborn colleague insists the root must test $x_3$. Build the rest of the tree greedily from there (splitting the children on the best remaining attribute), and report the final training error. Is a perfect fit still reachable?

Step 1 — Perform the root split on $x_3$

$x_3 = 1$: rows 2, 4, 6, 8 with labels $0,1,1,1$ (attributes $x_1,x_2$ left).
$x_3 = 0$: rows 1, 3, 5, 7 with labels $0,0,1,1$.

Neither child is pure, so both recurse with $A = \{1,2\}$.

Step 2 — Recurse on the $x_3 = 1$ child (rows 2, 4, 6, 8)

Their $(y, x_1, x_2)$: row 2 = $(0,1,0)$, row 4 = $(1,0,0)$, row 6 = $(1,1,1)$, row 8 = $(1,1,1)$.

Split on $x_1$: $x_1{=}1$ → rows 2,6,8 with labels $0,1,1$ → vote 1, 1 mistake. $x_1{=}0$ → row 4, label 1 → 0 mistakes. Total 1.

Split on $x_2$: $x_2{=}1$ → rows 6,8, labels $1,1$ → 0 mistakes. $x_2{=}0$ → rows 2,4, labels $0,1$ → tie → vote 1, 1 mistake. Total 1.

A tie. Take $x_2$ (lowest index among the winners is a fine deterministic rule; the notes do not specify one, so state yours). Then the $x_2{=}1$ leaf is pure, and the $x_2{=}0$ node still holds rows 2 and 4 with labels $0,1$ and $A = \{1\}$ remaining. Split on $x_1$: row 2 has $x_1{=}1$ (label 0), row 4 has $x_1{=}0$ (label 1). Both children pure! So this whole branch reaches 0 mistakes at depth 3.

Step 3 — Recurse on the $x_3 = 0$ child (rows 1, 3, 5, 7)

Their $(y, x_1, x_2)$: row 1 = $(0,1,0)$, row 3 = $(0,1,0)$, row 5 = $(1,1,1)$, row 7 = $(1,1,1)$.

Split on $x_1$: every row has $x_1 = 1$. The $x_1{=}0$ child is empty and the $x_1{=}1$ child is the whole set — a useless split, 2 mistakes.

Split on $x_2$: $x_2{=}1$ → rows 5,7 (labels $1,1$, pure); $x_2{=}0$ → rows 1,3 (labels $0,0$, pure). 0 mistakes.

So $x_2$ wins here and finishes the branch at depth 2.

Answer & the takeaway

Final training error: 0. The forced-$x_3$ tree still fits perfectly — but it needs 4 internal nodes and depth 3, where the greedy tree needed 2 internal nodes and depth 2.

Takeaway. A bad first split usually does not destroy your ability to fit the training data; with enough attributes you can almost always drive training error to zero eventually. What it destroys is compactness. And compactness is not cosmetic: a bigger tree means fewer examples per leaf, which means the leaf labels are estimated from less data, which means worse generalisation. BestAttribute is fighting for a small tree, not merely a correct one.

Build the tree yourself

Reading a split table is not the same as feeling it. The 8 rows below are live: click any leaf to select it, split it on an attribute, and watch the counts flow into the children and the training error drop.

Figure 5 · Interactive tree builder — the poll dataset
$i$$y$$x_1$$x_2$$x_3$lands in leaf
What to notice: split the root on $x_2$ and the error drops $3/8 \to 1/8$ in one move; split it on $x_1$ or $x_3$ and the error does not move at all. Then try to reach $0$ starting from $x_3$ — you can, but it takes twice as many nodes. Selected leaf is outlined in the accent colour.

Greediness: why this algorithm is not optimal, and why we do it anyway

The notes are careful to flag this, and you should be too:

Key idea

The construction algorithm is a greedy approach towards ERM (empirical risk minimisation, see Chapter 5). Greediness is suboptimal but helps computational efficiency.

Why it is suboptimal. True ERM would search over all trees of a given size; greedy commits to the root split on a one-step lookahead, judging each attribute by what it does alone and never reconsidering — and a split that looks useless alone can be indispensable in combination. Why we do it anyway: finding the smallest consistent tree is NP-hard, while greedy costs $O(N \cdot d)$ per node.

The canonical failure: XOR

Example

Let $d = 2$ and $y = x_1 \oplus x_2$ (exclusive-or). The complete dataset is four rows:

$i$$x_1$$x_2$$y$
1000
2011
3101
4110

Baseline: 2 zeros, 2 ones → majority vote is a tie → predict 1 → 2 mistakes out of 4.

Split on $x_1$: $x_1{=}1$ gives rows 3, 4 with labels $1, 0$ — a 1–1 tie, 1 mistake. $x_1{=}0$ gives rows 1, 2 with labels $0,1$ — another tie, 1 mistake. Total $2/4$. The split bought nothing.

Split on $x_2$: by symmetry, also $2/4$. Also nothing.

So the one-step criterion reports that both attributes are worthless, even though the pair of them determines $y$ exactly. (The same is true of mutual information here: $I(Y;x_1) = I(Y;x_2) = 0$. XOR defeats every one-step-lookahead criterion, not just error rate — this is worth knowing, because students often assume entropy rescues XOR. It does not.)

How the algorithm still recovers

The part people forget — run the algorithm literally on XOR:

  1. At the root, all attributes tie. BestAttribute breaks the tie somehow — say it returns $x_1$.
  2. Left child ($x_1 = 1$) holds rows 3, 4 with labels $1, 0$. Not pure, and $A = \{2\}$ is not empty, so recurse. The only choice is $x_2$: row 3 has $x_2{=}0$ (label 1), row 4 has $x_2{=}1$ (label 0). Both children pure.
  3. Right child ($x_1=0$) holds rows 1, 2. Split on $x_2$: both children pure.

Final tree: depth 2, zero training error, perfect. The greedy criterion was blind, but the recursion kept going anyway because the stopping rule was "pure or out of attributes", not "gain is zero".

Common mistake

This is exactly why the stopping criterion "stop if the split doesn't reduce training error by much" — one of the options the notes list — is dangerous. On XOR it stops at the root with error $2/4$ and never discovers the perfect depth-2 tree. The cheap fix used in practice is to grow the tree out fully and then prune it back, rather than stopping early, because pruning judges a subtree by what it achieved, not by what its first split promised. beyond syllabus

On the XOR dataset, the greedy criterion assigns both attributes zero benefit. What does the algorithm as written in the pseudocode actually do?
Why: The base case on line 2 is "$A = \emptyset$ or all examples share a label" — neither is true at the XOR root, so the algorithm must split. It breaks the tie by whatever rule BestAttribute uses, recurses, and at depth 2 the remaining attribute separates each child perfectly. The lesson: greedy scoring can be blind at one level and still be rescued by the recursion below it — provided you did not add an early-stopping rule that quits on zero gain.

Evaluating decision trees

The pre-reading asks: here are two decision trees for the Iris task — which is better?

Key idea

You cannot tell. Comparing two models by staring at them is not a thing. You need (a) data and (b) a performance measure.

The measure for classification is the classification error rate:

$$\text{err} \;=\; \frac{1}{N} \sum_i \1\!\left(y^{(i)} \ne \hat y^{(i)}\right)$$

Naming the symbols: $N$ is how many examples you are evaluating on, $y^{(i)}$ the true label, $\hat y^{(i)} = h(x^{(i)})$ the tree's prediction, and $\1(\cdot)$ the indicator, contributing $1$ for a mismatch. The sum counts mistakes; dividing by $N$ makes it a rate, comparable across dataset sizes.

This is the empirical risk $\hat R(h)$ from Chapter 5 with the zero-one loss $\ell(y,\hat y) = \1(y \ne \hat y)$ plugged in — the general machinery specialised to classification.

Common mistake

Error rate treats all mistakes as equally bad, which is often wrong. The pre-reading's medical table charges $10$ for predicting "healthy" for an ill patient and $2$ for the reverse:

$\ell(y, \hat y)$$\hat y = 0$$\hat y = 1$
$y = 0$02
$y = 1$100

Everything here works with a weighted loss: replace "count the mistakes" with "add up the losses" in the majority vote and in BestAttribute, and the leaf predicts the cost-minimising class rather than the most common one.

The Iris comparison, worked in full

Example

reconstruction The pre-reading's data table and its two trees are figures that did not survive text extraction from the PDF, so I have reconstructed a plausible 7-row Iris table and two candidate trees that reproduce the stated result — Model A errs on $1/7$, Model B on $2/7$. The rows below are genuine measurements from Fisher's Iris dataset; the trees are mine.

$i$sepal lensepal widpetal lenpetal widspecies $y$
15.13.51.40.2setosa
24.93.01.50.2setosa
36.43.24.51.5versicolor
45.72.84.11.3versicolor
55.93.24.81.8versicolor
66.33.36.02.5virginica
76.53.25.12.0virginica
Figure 6 · Two candidate Iris trees (reconstruction)
MODEL A — petal-based MODEL B — sepal-based YesNo YesNo YesNo YesNo petal len < 2.5? petal wid < 1.75? setosa versicolor virginica sepal len < 5.5? sepal wid < 3.1? setosa versicolor virginica error rate 1/7 error rate 2/7
What to notice: both trees have the same shape — two internal nodes, three leaves, same three species. Shape tells you nothing about quality. Only running the data through them does.
$i$true $y$A: pathA: $\hat y$A wrong?B: pathB: $\hat y$B wrong?
1setosaPL 1.4 < 2.5 → Yessetosa·SL 5.1 < 5.5 → Yessetosa·
2setosaPL 1.5 < 2.5 → Yessetosa·SL 4.9 < 5.5 → Yessetosa·
3versicolorPL 4.5; PW 1.5 < 1.75versicolor·SL 6.4; SW 3.2 ≱ 3.1virginica✗
4versicolorPL 4.1; PW 1.3 < 1.75versicolor·SL 5.7; SW 2.8 < 3.1versicolor·
5versicolorPL 4.8; PW 1.8 ≱ 1.75virginica✗SL 5.9; SW 3.2 ≱ 3.1virginica✗
6virginicaPL 6.0; PW 2.5 ≱ 1.75virginica·SL 6.3; SW 3.3 ≱ 3.1virginica·
7virginicaPL 5.1; PW 2.0 ≱ 1.75virginica·SL 6.5; SW 3.2 ≱ 3.1virginica·

Counting the crosses and dividing by $N = 7$:

$$\text{err}(A) = \frac{1}{7}\sum_i \1(y^{(i)} \ne \hat y^{(i)}) = \frac{1}{7} \approx 0.143, \qquad \text{err}(B) = \frac{2}{7} \approx 0.286$$

Model A performs better on this dataset — the pre-reading's conclusion. Note the qualifier: seven flowers is far too few to conclude that petal measurements beat sepal measurements in general, since one flower is 14 percentage points of error rate.

Model A scores $1/7$ and Model B scores $2/7$ on these seven flowers. What have we learned?
Why: The error rate is the empirical risk on these 7 points. Generalisation is about the true risk $R(h) = \mathbb{E}[\ell(Y, h(X))]$, which we never observe; with $N=7$, the difference between $1/7$ and $2/7$ is a single flower and well inside the noise. And neither tree was chosen by searching all trees, so neither is the ERM solution. If you also trained on these 7 rows, the number is a training error and is biased optimistically — see overfitting.

Two more reconstructed examples

reconstruction The pre-reading illustrates "using decision trees" with two figures that did not survive PDF extraction — a cesarean-section tree and the Iris species tree — redrawn here. The structures are mine, not the professor's, though the attributes are standard for each problem.

Figure 7 · Medical classification — should this delivery be a cesarean section? (reconstruction)
YesNo YesNo YesNo Previous cesarean? Breech presentation? Fetal distress? C-section C-section C-section vaginal delivery
What to notice: an "overly simple" tree, as the pre-reading itself calls it — real obstetric decisions involve many more factors and are not made by a four-box flowchart. It is a teaching object, and the interpretability point is exactly why medicine is a favourite domain for trees: a clinician can point at the node that fired.
Figure 8 · Species classification — Iris, from four petal/sepal measurements (reconstruction)
YesNo YesNo YesNo petal length < 2.5 cm? petal width < 1.75 cm? petal length < 5.0 cm? setosa virginica versicolor virginica $\Y$ here has THREE values, not two — nothing in the algorithm cared.
What to notice: Iris has three classes. Neither the majority-vote formula nor the recursion assumed $|\Y| = 2$ — $\argmax_{k \in \Y}$ ranges over whatever $\Y$ is. Multi-class comes for free with decision trees, which is not true of, say, plain logistic regression.

Extension: beyond binary attributes, and decision boundaries

The notes list several extensions. Start with the one that changes the picture most.

Attributes with more than $\{0,1\}$ values

Two cases, handled differently.

Here is the notes' example with $\X = \R^2$, $\Y = \{0,1\}$, splitting first at $x_2 = 4.5$ and then at $x_1 = 3.5$:

Figure 9 · A real-valued tree and the regions it carves in $\R^2$
x₁ x₂ 4.5 3.5 0 label 1 label 0 label 1 Thick orange lines = the decision boundary YesNo YesNo Is x₂ ≥ 4.5? Is x₁ ≤ 3.5? Label 1 Label 0 Label 1 Each internal node = one line in the picture. Each leaf = one rectangular region.
What to notice: the root's test $x_2 \ge 4.5$ draws a line across the whole plane. The second test $x_1 \le 3.5$ draws a line only inside the lower half — because that node is only reached when $x_2 < 4.5$. The depth of a node is exactly how many constraints its region satisfies.
Definition

The decision boundary is the set of lines (in general, surfaces) that separate the region where the model outputs $0$ from the region where it outputs $1$.

In Figure 9 it is the horizontal segment at $x_2 = 4.5$ over $x_1 \le 3.5$, plus the vertical segment at $x_1 = 3.5$ below $x_2 = 4.5$. Notice it is not the whole of either line: where label-1 sits on both sides of a line, that stretch of line is not a boundary at all.

Why tree boundaries are always axis-aligned staircases

Proof

Every internal node tests a single coordinate against a constant: $x_j \ge t$. The set $\{x : x_j \ge t\}$ is a half-space whose bounding hyperplane is perpendicular to axis $j$ — i.e. axis-aligned.

A leaf is reached exactly when all the tests on its root-to-leaf path hold, so the region a leaf owns is an intersection of axis-aligned half-spaces, which is an axis-aligned box (possibly unbounded).

The model's $0$-region is a union of such boxes, and so is its $1$-region. A boundary between two unions of axis-aligned boxes can only consist of axis-aligned pieces. $\blacksquare$

Consequence for a diagonal boundary. If the truth is $y = \1(x_1 + x_2 \ge 5)$ — a clean 45° line — a tree can never draw it. It can only approximate it with a staircase of alternating horizontal and vertical splits, each shaving off one rectangle: roughly $O(1/\varepsilon)$ splits to get within $\varepsilon$, and every extra split thins the data, so leaves get sparse and the fit gets noisy. A tree cuts only with a guillotine held parallel to the table edges.

Intuition

The fix is not a better tree algorithm but a better feature: add the column $z = x_1 + x_2$ and one split on $z$ does the job. That is precisely the subject of feature engineering.

How threshold candidates are chosen beyond syllabus

You do not search all of $\R$: sort the $N$ values of $x_j$ and take the midpoints between consecutive distinct values. The partition changes only when $t$ crosses a data value, so there are at most $N-1$ candidates. Petal lengths $1.4, 1.5, 4.1, 4.5, 4.8, 5.1, 6.0$ give $1.45, 2.8, 4.3, 4.65, 4.95, 5.55$ — six, not infinitely many.

Extensions: attribute reuse and stopping criteria

You need not remove the chosen attribute

Lines 6–7 pass $A \setminus \{b\}$ down, but the notes say this is optional. For binary attributes, keeping $b$ is wasteful rather than wrong: every point in the left child already has $x_b = 1$, so a second test on $b$ sends them all one way and leaves the other child empty.

Common mistake

For real-valued attributes you must not remove the attribute. Look at Figure 9 and imagine the truth were a horizontal band $2 \le x_2 \le 4.5$. You need two thresholds on $x_2$ — one at $4.5$, another at $2$ further down the tree. Delete $x_2$ from $A$ after the first split and that band becomes unlearnable.

Real implementations (CART, scikit-learn) therefore never remove attributes. The consequence is that the depth bound "at most $d$" evaporates, and you need a real stopping criterion instead.

Different stopping criteria

Options, from the notes and from practice:

CriterionStop when…Risk
$A = \emptyset$every attribute has been used on this pathnone — but only reachable if you do remove attributes
Pure nodeall labels in $S$ are the samenone; the node is already perfect on training data
Gain threshold
"the split doesn't reduce training error by much"
the best available split improves the criterion by less than $\tau$blind to XOR and other interaction effects — stops too early
Depth limitdepth reaches $D_{\max}$crude but effective and very common
Minimum leaf sizea child would hold fewer than $m$ pointsthe most reliable single knob in practice
Key idea

Stopping criteria exist because of overfitting. Grown to purity, a tree memorises the training set: it will happily build a leaf holding a single noisy example and predict that example's label for the whole region around it. Training error $\to 0$; test error climbs.

Every criterion above is a way of saying "stop trusting the data before the leaves get too small to trust." This is the same bias–variance tension you meet again with regularisation in feature engineering and overfitting.

Intuition

Depth limit and minimum leaf size both enforce one rule: never make a claim about a region of feature space from two data points. A leaf holding 40 examples that are 90% positive is a defensible claim; a leaf holding 1 example is an anecdote.

Extension: the menu of BestAttribute criteria

The notes give three options, with the formula for each.

1. Minimise training error

Done above in full: split on each candidate attribute, majority-vote both children, add the mistakes, take the minimum. Simple, intuitive — and, as the next section shows, badly behaved.

2. Minimise Gini impurity beyond syllabus

The notes say "won't discuss here", so one line: for class proportions $p_k$,

$$G \;=\; 1 - \sum_{k \in \Y} p_k^2,$$

the probability that two points drawn at random from the node have different labels; choose the split minimising the weighted average of $G$ over the children, exactly as with conditional entropy. It is the CART and scikit-learn default, behaves almost identically to entropy, and needs no logarithm.

3. Maximise mutual information

Instead of "how many mistakes would a stump make?", ask "how much of the uncertainty in the labels does this attribute remove?" Quantifying that needs entropy, which is all of Chapter 7. The criterion, stated now:

$$b \;=\; \argmax_{a \in A} \; I(Y; a) \;=\; \argmax_{a \in A} \big[\,H(Y) - H(Y \mid a)\,\big]$$

This is also called the information gain method.

Why error rate is a broken splitting criterion

The pre-reading drops a warning and moves on: "error rate as a splitting criterion is problematic and will [be replaced] with other splitting criteria such as mutual information." That sentence is the hinge between this chapter and the next, so here is the demonstration rather than the promise.

Key idea

The defect: error rate only counts which class wins in each child. It is completely blind to by how much. A child that goes from 50/50 to 75/25 has become dramatically more certain, but the majority label did not change, so the error count did not change either. Error rate cannot see progress that does not immediately flip a prediction.

A dataset where every split has the same training error

Example

$N = 8$, two binary attributes $a$ and $b$, labels binary.

$i$$y$$a$$b$
1111
2111
3101
4101
5110
6100
7010
8000

Labels overall: 6 ones, 2 zeros.

No split at all. Majority vote $= 1$, wrong on rows 7 and 8: 2/8.

Split on $a$.

Split on $b$.

Common mistake

All three numbers are 2/8. Under the error-rate criterion, splitting on $a$, splitting on $b$, and not splitting at all are indistinguishable. The criterion has no opinion.

But the splits are obviously not equally good. Split $b$ finishes half the dataset permanently — the $b=1$ child is pure and will never need another node. Split $a$ leaves both children in exactly the same 3-to-1 state the parent was in; it achieved literally nothing.

Mutual information does have an opinion

The next chapter derives all of this; here is the punchline. With $H$ the entropy in bits:

SplitChild 1 (size, labels)Child 0 (size, labels)Training error$H(Y \mid \cdot)$$I(Y;\cdot)$
none$H(Y) = H(\tfrac{6}{8}) = 0.8113$2/8——
$a$4 pts, 3–1 → $H = 0.8113$4 pts, 3–1 → $H = 0.8113$2/8$0.8113$$0.0000$
$b$4 pts, 4–0 → $H = 0$4 pts, 2–2 → $H = 1$2/8$0.5000$$0.3113$

The arithmetic, since you should be able to do it by hand:

$$H(Y) = -\tfrac{6}{8}\log_2\tfrac{6}{8} - \tfrac{2}{8}\log_2\tfrac{2}{8} = 0.75(0.41504) + 0.25(2) = 0.31128 + 0.5 = 0.81128$$ $$H(Y \mid a) = \tfrac{4}{8}(0.81128) + \tfrac{4}{8}(0.81128) = 0.81128 \;\Longrightarrow\; I(Y;a) = 0.81128 - 0.81128 = \mathbf{0}$$ $$H(Y \mid b) = \tfrac{4}{8}(0) + \tfrac{4}{8}(1) = 0.5 \;\Longrightarrow\; I(Y;b) = 0.81128 - 0.5 = \mathbf{0.31128}$$
Key idea

Mutual information says, unambiguously: $a$ is worthless ($I = 0$ — the children are statistically identical to the parent) and $b$ is valuable ($I = 0.311$ bits — it purified half the data). Error rate could not tell them apart.

Hence the switch of criteria. Error rate is a fine way to evaluate a finished tree; it is a bad way to choose a split, because a split is progress toward a future prediction, and progress is measured in certainty, not in flipped labels.

Guided problemGrow the broken-criterion dataset to completion

Using the 8-row $(y, a, b)$ dataset above, build the full tree twice: once with a BestAttribute that breaks ties by preferring $a$, and once preferring $b$. Compare final trees. Assume attributes are removed from $A$ after use, and tie-break majority votes to $1$.

Step 1 — The "prefer $a$" tree

Root splits on $a$. Children: $a{=}1$ holds rows 1,2,5,7 (labels $1,1,1,0$); $a{=}0$ holds rows 3,4,6,8 (labels $1,1,1,0$). Neither pure; $A = \{b\}$ remains.

$a{=}1$ child, split on $b$: $b{=}1$ → rows 1,2 (labels $1,1$, pure); $b{=}0$ → rows 5,7 (labels $1,0$, tie → 1 mistake). $A$ is now empty, so both become leaves.

$a{=}0$ child, split on $b$: $b{=}1$ → rows 3,4 (pure, label 1); $b{=}0$ → rows 6,8 (labels $1,0$, tie → 1 mistake).

Result: 3 internal nodes, 4 leaves, depth 2, training error $2/8$.

Step 2 — The "prefer $b$" tree

Root splits on $b$. $b{=}1$ → rows 1,2,3,4, all label 1 → pure, immediate leaf. $b{=}0$ → rows 5,6,7,8 with labels $1,1,0,0$; $A = \{a\}$.

Split that child on $a$: $a{=}1$ → rows 5,7 (labels $1,0$, tie, 1 mistake); $a{=}0$ → rows 6,8 (labels $1,0$, tie, 1 mistake). $A$ empty, both leaves.

Result: 2 internal nodes, 3 leaves, depth 2, training error $2/8$.

Step 3 — Why is the training error the same?

Because with only two attributes there are four possible $(a,b)$ cells, and the data forces it. Look at the cells: $(1,1)$ holds rows 1,2 — both label 1. $(0,1)$ holds rows 3,4 — both label 1. $(1,0)$ holds rows 5,7 — labels $1,0$. $(0,0)$ holds rows 6,8 — labels $1,0$.

The two mixed cells each contain one point of each label, so no function of $(a,b)$ can classify all eight rows: the data is not separable by these features. Two mistakes is the floor. Both trees reach the floor.

Answer & the takeaway

Both trees hit the irreducible error of $2/8$, but the "prefer $b$" tree does it with one fewer internal node and one fewer leaf, because $b$ cleared half the dataset in a single move.

The takeaway, and the reason for Chapter 7: the criterion that could have told you to prefer $b$ is mutual information ($0.311$ vs $0.000$), not error rate (a dead tie). When two models have equal training error, the simpler one is preferable — fewer leaves means more data per leaf means a more trustworthy prediction. Error rate is structurally unable to express that preference; entropy is.

Guided problemA real-valued stump from scratch

One real-valued attribute $x \in \R$, binary label. Six training points, sorted by $x$:

$x$1.02.03.06.07.09.0
$y$001011

Find the best threshold split "Is $x \ge t$?" under the training-error criterion. Tie-break majority votes to $1$.

Step 1 — Enumerate the candidate thresholds

Midpoints of consecutive distinct values: $1.5,\ 2.5,\ 4.5,\ 6.5,\ 8.0$. Five candidates. (There is no candidate below 1.0 or above 9.0, because those give an empty child and the same error as no split.)

Step 2 — Score every candidate

Labels in order: $0,0,1,0,1,1$. For each $t$, the "$x \ge t$" group is a suffix and the "$x < t$" group is a prefix.

$t$$x < t$ labelsvoteerr$x \ge t$ labelsvoteerrtotal
1.50000,1,0,1,1122
2.50,0001,0,1,1111
4.50,0,1010,1,1112
6.50,0,1,0011,1101
8.00,0,1,0,1021102
Step 3 — Break the tie between $t = 2.5$ and $t = 6.5$

Both score $1/6$ under error rate. Error rate has, once again, no further opinion. Look at the children:

$t = 2.5$: left child $\{0,0\}$ is pure (2 points); right child is $\{1,0,1,1\}$, 3–1.
$t = 6.5$: left child $\{0,0,1,0\}$ is 3–1; right child $\{1,1\}$ is pure (2 points).

They are mirror images, so entropy ties them too: $H(Y\mid\cdot) = \tfrac{2}{6}(0) + \tfrac{4}{6}(0.8113) = 0.5409$ for both. A genuine, honest tie — which happens, and which is why implementations need a documented deterministic tie-break (e.g. smallest threshold).

Answer & the takeaway

Best stump: "Is $x \ge 2.5$?" → Yes: label 1, No: label 0. Training error $1/6$ (the point at $x=6.0$ with $y=0$ is misclassified). $t = 6.5$ is equally good and would be chosen by an implementation that prefers larger thresholds.

Takeaway. Real-valued attributes add a second search (over $t$) inside the first (over $j$), but the search is finite — at most $N-1$ thresholds per attribute — so the total work at a node is $O(N d)$ after sorting. Nothing conceptual changes; the node still asks one yes/no question and still partitions the data in two.

A node holds 100 points: 60 label-1 and 40 label-0. A candidate split produces children of (50 pos, 10 neg) and (10 pos, 30 neg). What does the error-rate criterion say about this split, and is it right?
Why: Parent error = 40 (minority count). Children: first votes 1 with 10 mistakes, second votes 0 with 10 mistakes, total 20. So error rate does register this split. The point of the comparison is different: error rate only ever counts minority points, so many structurally different splits map to the same score, and it will happily call a split that produces a pure child equal to one that does not. Entropy separates them because it charges for how mixed each child is, not just how many points are on the losing side.

Recap

Every statement worth memorising is in the Essentials box at the top. The one line to carry forward: error rate is a fine way to evaluate a finished tree and a bad way to choose a split, because it is blind to purity changes that do not flip a majority. Mutual information is not — that is Chapter 7, where $H$ and $I$ are built from scratch via a game of 20 questions.