Concepts / Decision Trees

Decision Trees

Decision trees are widely used models for classification and regression tasks.

  • Programming
Interactive lab

Try it: Decision Tree (ID3)

How ID3 grows a decision tree greedily: label the node by majority vote, compute the gain of every remaining attribute, split on the best one, and recurse until the node is pure or no attributes are left — then classify a new row by walking the tree.

How it works

  1. Start with one root leaf holding every row and give it the majority label.
  2. If all rows agree, or no attributes are left, the node stays a leaf.
  3. Otherwise compute for each remaining attribute (C = entropy, training error or Gini).
  4. Split on the attribute with the largest gain and repeat on every child with that attribute removed.
  5. Classify a query by following its attribute values from the root to a leaf.

Default run (15 steps): ID3 starts with one root leaf holding all 14 rows (9 Yes / 5 No); its majority label is Yes. Impurity measure: entropy. … The query reaches the leaf Humidity = Normal: prediction Play = Yes.

Simplified: A fixed 4-attribute categorical table (at most 14 rows) with a Yes/No label. A value with no rows becomes a leaf with the parent's majority label, and a tied majority keeps the parent's label; real trees also prune.

Educational simulation

Loading the simulation…

A Game of 20 Questions

Decision trees are widely used models for classification and regression tasks. A decision tree learns a hierarchy of if/else questions, and the answers to those questions lead to a decision. This article starts from that everyday intuition and works toward the code you can use to test it.

Imagine you need to tell apart four animals: bears, hawks, penguins, and dolphins. Your goal is to reach the right answer by asking as few if/else questions as possible. The game is a useful model because every question you ask has one of two answers, and the answer you get determines what you ask next.

What do you think happens?

Which single question would you ask first to narrow four animals down to two?

  • Can it fly?

  • Does it have feathers?

  • Does it live in water?

Reveal answer
Answer:

Does it have feathers?

The source's first good question is whether the animal has feathers, because that narrows the possibilities to just two animals.

Tracing the Animal Questions

Follow the questions for one animal. If the answer to the feathers question is yes, you ask whether the animal can fly, which separates hawks from penguins. If the answer is no, the remaining choices are dolphins and bears, and you ask whether the animal has fins to tell them apart. Each path through the questions ends at a final answer.

Has feathers?Can fly?HawkHas fins?PenguinDolphinBearyesnoyesnoyesno
For one animal, which question is asked first, which branch is taken next, and where does the path end in a final prediction?

Each question in this structure is a node, and the answers are the edges that connect a node to the next question. A node that holds the final answer is called a terminal node, or a leaf. The sequence of questions can be written as a decision tree, which is a model that distinguishes four classes using three features: has feathers, can fly, and has fins.

A decision tree model does not need a person to write these questions by hand. Learning from data means learning the sequence of if/else questions that reaches the true answer most quickly. In machine learning these questions are called tests. Real data is usually made of continuous features rather than yes/no features, so the tests usually take the form 'Is feature i larger than value a?'

How the Algorithm Chooses Each Test

To build a tree, the algorithm searches over all possible tests and finds the one that is most informative about the target variable. The source illustrates this with a two-dimensional dataset of two half-moon shapes, called two_moons, containing 75 points per class. For that dataset, the first chosen test is x[1] <= 0.0596, which best separates the points of class 1 from the points of class 2.

The top node, called the root, represents the whole dataset: 75 points of class 0 and 75 points of class 1. After the first split, the left node holds 2 points of class 0 and 32 of class 1, and the right node holds 48 points of class 0 and 18 of class 1. The first split separates the classes well, but each side still contains some points of the other class. The algorithm therefore repeats the search for the best test inside each region. For the two-moons data, the most informative next split for both the left and right regions is based on x[0].

x[1] <= 0.0596root: 75 class 0, 75 class1x[0] test2 class 0, 32 class 1Splits continueuntil each leaf is purex[0] test48 class 0, 18 class 1yesnorepeat searchrepeat search
At each node, which feature and threshold get chosen, and how is the data partitioned into child nodes?

This recursive process yields a binary tree of decisions, with each node containing a test. Each test splits the part of the data under consideration along one axis. Because each test concerns only a single feature, the regions of the resulting partition always have axis-parallel boundaries. The recursion stops when each region, which is each leaf, contains only a single target value. A leaf whose data points all share the same target value is called pure.

To predict for a new point, start at the root and go left or right depending on whether each test is fulfilled, until a leaf is reached. The prediction is the majority target in that region, or the single target when the leaf is pure. For regression, the traversal is the same, but the output is the mean target of the training points in the leaf the point falls into.

Why Pure Leaves Overfit

If you keep building the tree until all leaves are pure, the model becomes very complex and highly overfit to the training data. Pure leaves mean the tree is 100 percent accurate on the training set, because each training point sits in a leaf whose majority class is correct. The source shows that the decision boundary of such a tree focuses heavily on single outlier points that lie far from the other points of their class. That is not how one would expect a useful boundary to look.

The source gives two common strategies to prevent this. The first is to stop creating the tree early, which is called pre-pruning. The second is to build the full tree and then remove or collapse nodes that contain little information, which is called post-pruning, or just pruning.

Tracing Depth Against Accuracy

The source examines pre-pruning on the Breast Cancer dataset. It first builds a tree with the default setting, which grows the tree until all leaves are pure, and it fixes random_state so that internal tie-breaking is repeatable. The code below is a generated sketch in that same style. It loads the data, splits it, and compares a shallow tree with a deep one. Run it, then read the two printed numbers for each depth.

python
Notes on the code
  • max_depth=None lets the tree grow until its leaves are pure, the default behavior the source describes
  • random_state fixes tie-breaking so that repeated runs can be compared fairly
  • score on the training data and score on the test data are the two numbers to compare

The source reports that the default tree reaches a training accuracy of 1.000, which is what you should expect for a tree grown deep enough to memorize all the training labels. Its test accuracy is 0.937, slightly worse than the linear models the source examined earlier, which reached around 95 percent. The gap between those two numbers is the signature of overfitting.

When a result differs from what you expected, check the training and test accuracy lines separately. A high training score alongside a lower test score points to overfitting in the tree's structure. The depth limit is the setting that changed between runs, so it is the first place to look.

Forests, Averaging, and n_estimators

A random forest is not one tree. It is a collection of decision trees, and the trees are stored in the estimator_ attribute of the fitted model. Each tree is trained on its own bootstrap sample of the training points, and at each split only a random subset of the features is considered. Each tree therefore learns a somewhat different decision boundary. The forest combines them by averaging their predicted probabilities, and that combined prediction is what you get from predict or score.

The parameter n_estimators sets the number of trees in the forest. For random forests, larger is always better, because averaging more trees yields a more robust ensemble and reduces overfitting. The catch is that the returns diminish, and each extra tree costs more memory and training time. The practical rule is to build as many trees as your time and memory budget allow. When you compare settings, the jump from one tree to five should typically be larger than the change from twenty to one hundred.

max_features and max_depth in a Forest

The parameter max_features controls how random each tree is. At every split, a tree considers only a subset of the features, and max_features sets the size of that subset. A smaller value makes each tree more different from the others, and the source says a smaller max_features reduces overfitting. The defaults are good starting points: the square root of the number of features for classification, and log base 2 of the number of features for regression.

The parameter max_depth still applies pre-pruning inside a forest, limiting how complex each individual tree becomes. The source is explicit, though, that a forest gets its robustness from averaging many trees, not from making each tree tiny. Adding max_features or max_leaf_nodes can sometimes improve performance and can drastically reduce the space and time needed for training and prediction. Often the defaults already work well, so these settings are worth adjusting only after you have a baseline score to compare against.

A forest also reports feature importances, computed by aggregating importances over all its trees. The source considers these more reliable than the importances of a single tree. Because each feature is judged across many trees, a feature ranked highly is useful across many trees, while a feature that appears in only a few trees receives little weight. Read the plot as a summary of many trees rather than a full explanation of each prediction.

Boosting and the Role of learning_rate

Gradient boosted trees are a different ensemble. Instead of building trees independently, they are built one after another, and each new tree tries to correct the mistakes of the previous one. The individual trees are usually shallow, with depth between one and five in the source's description. The main idea is to combine many simple weak learners, and the parameters therefore behave differently from the random forest case.

In gradient boosting, learning_rate controls how strongly each tree corrects its predecessors. A higher learning rate lets each tree make stronger corrections, which allows more complex models. Increasing n_estimators also raises complexity, because the model has more chances to correct training mistakes. The two parameters are linked: a lower learning rate needs more trees to reach a model of similar complexity. This is the opposite of the random forest case, where a higher n_estimators is always better.

AspectRandom forestGradient boosting
How trees are builtIndependently, each on a bootstrap sampleSequentially, each correcting the previous tree's mistakes
Typical tree depthCan be deepUsually shallow, between one and five
Effect of more n_estimatorsAlways better, with diminishing returnsAdds complexity and can overfit
Where learning_rate actsNot a forest tuning lever in the sourceSets how strongly each tree corrects its predecessors
Overfitting remedyUse max_features and averaging across treesSmaller max_depth or a lower learning rate

Tuning emphasis for the two tree ensembles, drawn from the source's description

For boosting, the source suggests fixing n_estimators according to your time and memory budget, then searching over learning rates. The clearest demonstration in the source uses gradient boosting because it overfits badly until its depth is restricted. The default boosted model reaches a training accuracy of 1.000, which the source reads as a sign of likely overfitting. Two remedies are offered: a smaller maximum depth, or a lower learning rate.

Mistakes Learners Make with Tree Tuning

  • Common mistake

    Judging a tree by its training score alone

    What it looks like

    A default tree shows a training accuracy of 1.000 and the learner concludes the model is excellent.

    Why it fails

    A pure-leaf tree memorizes the training labels, so a perfect training score does not show that it generalizes.

    Do this instead

    Compare the training and test accuracy lines separately and treat a large gap as a sign of overfitting.

  • Common mistake

    Expecting more trees to always help in gradient boosting

    What it looks like

    Raising n_estimators on a boosted model to get a better score without changing anything else.

    Why it fails

    For boosting, more trees add complexity and can overfit, and the source ties n_estimators to learning_rate.

    Do this instead

    Fix n_estimators by your time and memory budget, then search over learning_rate.

  • Common mistake

    Changing several settings at once

    Why it fails

    When several parameters move together, you cannot tell which change caused a surprising score.

    Do this instead

    Change one setting at a time and connect each change to a specific line of code and a number in the output.

  • Common mistake

    Treating a feature importance as a direction

    What it looks like

    Concluding that a high worst radius value points toward a malignant sample because worst radius is the top feature.

    Why it fails

    Feature importances are always positive and say nothing about which class a feature points toward.

    Do this instead

    Use importances to rank how much a feature matters, then inspect the data separately to learn its direction.

Predict, Then Check the Tree

What do you think happens?

A tree is grown until all of its leaves are pure. What training accuracy should you expect?

  • About 0.5, because the tree is guessing

  • 1.000, because each training point sits in a pure leaf

  • Lower than the test accuracy

Reveal answer
Answer:

1.000, because each training point sits in a pure leaf

Pure leaves mean the tree is 100 percent accurate on the training set, which is why the source reads a training accuracy of 1.000 as a sign of overfitting.

MEDIUM

Modify the generated depth loop so that it also prints the depth-by-depth test scores in a list. Predict first which depth gives the highest test accuracy, then run the code and check whether your prediction matched. If the best depth is not the deepest tree, explain in one sentence which line of code controls depth and why a deeper tree did not win.

Hints
  • The line with max_depth controls how many questions the tree may ask in a row.
  • The source found that limiting depth reduced training accuracy and improved test accuracy.

Key Takeaways

  • A decision tree is a hierarchy of if/else questions, and the answers lead to a decision at a leaf.
  • The algorithm searches for the most informative test at each node and splits the data until every leaf is pure, which can overfit.
  • Pre-pruning stops growth early, for example with max_depth, while post-pruning grows the full tree and then removes low-information nodes.
  • In a random forest, more n_estimators is better with diminishing returns, and smaller max_features adds randomness that reduces overfitting. In gradient boosting, learning_rate and n_estimators are linked, and more trees can overfit.
  • When a score surprises you, compare training and test accuracy separately and change one setting at a time to find the line responsible.

Related concepts

More concepts starting with D