Intuition
Feel the idea before the formula.
The problem it solves: you need a decision, and you need to be able to say why. A decision tree is a sequence of yes or no questions, each one asked of a single number or category, ending in a verdict. Nothing else on this site produces an explanation a person can read out loud and argue with. The interesting part is not how you follow a tree, which takes about ten seconds to learn. It is how the tree decides what to ask.
What to read first: nothing. This chapter stands on its own, and it leans on the two shared pages rather than repeating them. Evaluation and comparison is the scoring machinery module 4 hands off to, and it already fits a tree live. Bias and variance is the general shape of what the depth dial does, and module 5c here is one very literal instance of it.
Running example for the whole chapter: a groundsman deciding each Saturday morning whether the match goes ahead. Three readings are taken at nine o'clock: whether it is raining, the wind speed in km/h, and the standing water on the pitch in millimetres. Three hundred Saturdays have been recorded, two hundred to learn from and a hundred kept back. About one in eight went the other way from what the readings suggested, because the call is made by a person, pitches drain, and weather turns, and no set of questions can recover a decision that was never in the numbers.
Here is a tree somebody wrote by hand, the way a groundsman would if you asked them to put their reasoning on paper. Below it is one Saturday's readings.
Walk it. Read the question, look at the card, and click the branch that applies. You will reach a verdict in three clicks at most, and you will have done exactly what the algorithm does at prediction time, at exactly the same speed.
The path you have taken is lit. Everything else is still there, and this day will never visit it.
Three things are worth noticing about what you just did, because each one is a property of the whole family.
Now the part that makes trees click, and the reason this chapter has two pictures instead of one.
Drop the rain for a moment and keep the two numbers, so everything fits on a pair of axes. Every Saturday is a dot, placed by its wind speed and its standing water. Here is a tree on the left and that plot on the right, and they are the same object.
The tree
The same tree, as territory
Every question cuts the map with one straight line, and the line is always parallel to an axis. Answering it throws away everything on the other side. Two questions in and you are standing in a small rectangle, and the tree's verdict for that rectangle is simply whichever colour is commonest inside it.
That is the whole geometry of a decision tree, and it is worth holding onto because two of this chapter's four failure modes are direct consequences of it. A tree cannot draw a line that is not parallel to an axis. It can only ever cut the rectangle it is currently standing in. And because each cut is made without looking ahead, an early cut it cannot take back shapes everything below it.
The first tree came from a groundsman. The second one did not: it was fitted to the two hundred recorded Saturdays, and nobody chose either the features or the thresholds.
Which raises the only genuinely interesting question in the chapter. There are two columns and two hundred rows, so there are a few hundred distinct thresholds it could have asked about, and it has to pick one to ask first. It cannot try every possible whole tree, because the number of trees you can build from a few hundred candidate splits is larger than anything you would want to count.
So it does something cruder and almost always good enough: it asks which single question, right now, would tidy up this pile of Saturdays the most, takes that one, and then asks the same thing again on each half. Module 2 is entirely about what "tidy up" means, because that word is doing all of the work.
A pile of Saturdays, some played and some called off, and one question to ask about them. A good question separates them. A bad one leaves both halves as mixed as the pile you started with. To choose automatically, that has to become a number.
Drag the line. Everything to the left of it becomes one pile and everything to the right becomes another, and the bars show how mixed each pile is.
The bars are impurity: zero when a pile is all one colour, largest when it is an even mix. A question is good exactly when the two halves it produces are purer than the pile it split, weighted by how many Saturdays ended up in each. That difference has a name, information gain, and maximising it is the entire fitting procedure.
The weighting matters more than it looks. A question that peels off three Saturdays into a perfectly pure sliver has done almost nothing, because the other hundred and ninety-seven are exactly as mixed as before, and the weights say so.
Two functions do this job, they are the only two you will meet, and they answer the same question in slightly different handwriting. Both take the proportion of one class in a node and return a number that is zero at the extremes and largest in the middle.
Drag to either end and both fall to zero, which is what a pure node is: nothing left to learn here, every Saturday in this pile went the same way.
Gini has a reading worth knowing: it is the chance of getting it wrong if you picked a Saturday from this node at random and guessed its outcome by picking another Saturday from the same node at random. A node that is 90 percent played gives 2 × 0.9 × 0.1 = 0.18, so you would be wrong about one time in five.
Entropy comes from information theory and is measured in bits: it is how many yes-or-no questions you would need, on average, to learn the outcome of one Saturday from this node. An even split costs a full bit. A node that is 90 percent played costs 0.47 of a bit, because most of the time you already know.
The practical answer to which one to use is it does not matter very much, and anybody who tells you otherwise is selling something. They agree on the best split the overwhelming majority of the time. Entropy is slightly more eager near the ends, because its curve is steeper there, so it will occasionally pay more for carving out a small pure pocket. Gini has no logarithm in it and is therefore a little faster, which is why it is the default in scikit-learn.
On this data they happen to disagree, which is a useful thing to see rather than a problem. Gini's first question is wind above … km/h, and entropy's is wind above … km/h. Both are real thresholds in the rule the groundsman was actually following, both are defensible, and by depth four the two trees score the same on the hundred Saturdays neither of them saw.
There is no cleverness in how the best question is found. Every candidate threshold on every column is tried, the gain is computed for each, and the largest wins. Here is that search laid out for the root node, both columns at once.
Each column is drawn across the full width on its own scale, so the two are comparable in height rather than in position. Both curves are lumpy rather than smooth, and the lumps are real: the gain changes only when the threshold crosses an actual recorded Saturday, so the curve is a staircase with one step per distinct value in the column.
Then the whole thing happens again on each half, and again on each half of those, on smaller and smaller piles, until something makes it stop. That is the algorithm. Module 3 writes it out and runs it.
Notice what this search is not doing. It never asks whether a slightly worse question now would allow a much better one later. It takes the best question available at this instant, commits, and never revisits it. That is called being greedy, it is the reason fitting a tree is fast enough to be practical, and it is also why the tree you get is very rarely the best tree that exists.
This is where the choice of criterion genuinely starts to matter, and where both criteria quietly fail in the same way.
Suppose only one Saturday in twenty is called off. A node holding all two hundred Saturdays is then 95 percent played, and its Gini is 2 × 0.95 × 0.05 = 0.095, which is already close to pure. There is very little impurity left to remove, so every candidate split has a tiny gain, and a stopping rule phrased as "stop when the gain is below some minimum" will stop at the root. The tree predicts "played" for everything, scores 95 percent accuracy, and has learned nothing. It is the same trap as evaluation step 2a, arriving through a different door.
Four things to do about it, roughly in the order they are worth trying.
class_weight="balanced", it is one argument, and it changes the tree more than any choice of criterion ever will.predict_proba and set the threshold yourself against what a wrong call costs, which is the same argument the evaluation page makes about every classifier.The short version: "Gini or entropy" is almost never the question. "How are the two classes weighted" almost always is.
Four lines, and one of them calls the other three again.
Line 5 is the whole trick. Each half is a smaller version of the original problem, so the same procedure handles it, and the tree builds itself by doing one thing repeatedly on ever-smaller piles.
Here is that loop running on the two hundred recorded Saturdays. Turn the dial and the tree grows one level at a time, and the map grows with it, because they are still the same object.
The tree it has learned
The territory that makes
Take it up one level at a time and watch the two pictures move together. A new level in the tree is a new set of cuts on the map, always inside a rectangle that already exists, never across one. By the far end the map is a mosaic of slivers, several of which exist to accommodate a single Saturday that went the other way from its neighbours, and every one of those slivers is a memorised mistake rather than a rule.
Line 2 of the loop is the only thing standing between you and a tree with one leaf per row. Left alone, the recursion runs until every pile is pure, which on noisy data means until every pile is a single Saturday. Four rules do the stopping, and they are the tree's entire set of dials.
The first three stop the tree early, which is called pre-pruning and is cheap and a bit blind: a split with no gain today can still be the one that unlocks a good split tomorrow, and stopping early never finds out. Post-pruning does find out, at the cost of growing the whole tree first.
Because it is not affordable, and because the greedy version is usually close enough that nobody minds.
With two columns and two hundred rows there are a few hundred candidate splits at the root. To look two questions ahead you would evaluate every one of those against every candidate split in each of the two halves it produces, and the count starts multiplying immediately. Looking all the way ahead, which is to say finding the genuinely smallest tree that fits the data, is a known hard problem: nobody has an algorithm that does it quickly and nobody expects one.
The cost of being greedy is real and it has a name in this chapter's failure modes. An early split is never revisited, so a question that looked best at the root and was not can distort everything beneath it, and the only evidence you will ever see of the better tree you did not get is a slightly worse score. §5b is what that feels like from the outside.
The standard response is not a cleverer search. It is to grow many greedy trees on slightly different data and average them, which trades the explanation away and is the subject of the two asides at the end of this chapter.
You now have a tree for every depth from one to ten. Two questions are left, and only the second one is about trees.
The first is how to score a classifier at all, and the answer is not in this chapter, because it is the same answer for every classifier on the site and it has its own page. The second is how to use those scores to choose the depth, which is genuinely tree-specific and turns out to be harder and more interesting than it looks.
A tree predicts a label, so it is marked exactly like logistic regression or KNN: count the four things that can happen, then read precision and recall off the count. Below is this chapter's tree on the hundred Saturdays it has never seen, with the depth dial from §3a still in your hands.
Watch the last metric rather than the first. A leaf reports the mix of training rows that landed in it, so that mix is the probability, and a tree grown to purity has nothing but 0s and 1s to report. Every other model on the site emits a smooth spread of probabilities. This one runs out of them as it gets deeper, which is the single most consequential difference between a tree and its neighbours, and it has almost nothing to do with accuracy.
Now the hard question. The chart above uses a hundred Saturdays held back from fitting, and if you turn the dial until that number peaks you have done something subtly dishonest: you chose a setting by looking at the data you were going to report it on. Do that and the score stops being an estimate of anything.
The standard cure is k-fold cross-validation, and it is worth saying plainly what it does, because the name makes it sound harder than it is. Cut the two hundred training Saturdays into k blocks. Hide one block, fit on the rest, score on the hidden block. Do that k times so every block gets hidden exactly once, then average. No Saturday is ever scored by a tree that saw it, and every Saturday gets used for scoring once, which is the whole trick: you get k estimates out of one dataset.
Each row is one fold. The shaded block is hidden that time, the rest is what the tree is fitted on.
The third line is the one you never get. Every other page on this site has to stop at an estimate. This chapter's Saturdays are generated, which means the rule underneath them is known and we can draw four thousand more and simply measure how good each tree really is. So for once the answer is on the chart, and it is worth sitting with what it says.
Cross-validation picks depth 4, and it does so at every fold count from two to nine. The single held-out hundred picks depth 3. The truth is that depth 3 is right, by about four points. The careful method lost to the casual one.
That is not an argument against cross-validation, and the reason is sitting on the chart next to the answer. Look at the whiskers, not the line: at the fold count you have set, the folds disagree by … points about depth 3 alone, and the bands for depths 3, 4 and 5 overlap almost entirely. Cross-validation did not tell you "4". It told you "somewhere around 3 to 5, and I cannot separate them on two hundred rows", and then the argmax threw that away. The single split had no whiskers to show you and was right by luck; had the hundred fallen differently it would have said 5 just as confidently.
Two things follow, and they are the reason this module exists rather than being a link to the shared page.
The honest summary of the whole module: on two hundred noisy rows, no method on this chart can tell depth 3 from depth 4, and the one that admits it is the one to use. The ceiling here is about 88 percent, because twelve percent of these labels were flipped on the way in and nothing can recover them. Any tree scoring near that is done, and any story about the difference between 80 and 82 percent is a story about the split.
Two of these come straight out of the geometry in §1b, and the other two come from the greed in §2c. Knowing which is which tells you whether a fix is available.
Here is a rule a tree finds genuinely awkward: call the match off when wind and water together are too much, in the ordinary way where a bit of each is as bad as a lot of one. That is a diagonal line, and a tree has no diagonal to draw with.
It gets there. It just pays for a line that logistic regression would have drawn with two numbers, and every step of the staircase is a threshold fitted to the handful of Saturdays sitting near it.
The counters. Build the feature the tree cannot: if wind plus water is what matters, add a column that is wind plus water and the tree asks one question about it. Or use a model whose boundary is not axis-aligned, which is logistic regression for a straight line and KNN for an arbitrary one. Or accept the staircase, because with enough data it is a perfectly good approximation and this is only a real problem when data is short.
The greedy search commits to the root before it knows anything else, and the root is chosen by a gain comparison that is often close. Two candidate questions separated by a hundredth of a point are, for practical purposes, tied, and which one wins is decided by whichever Saturdays happened to be in your sample.
Each press drops ten percent of the Saturdays at random and refits from scratch. Same data source, same code, same settings.
Press it a dozen times. The accuracy barely moves and the tree keeps changing its mind about what to ask first. That matters more than it looks, because the tree's selling point is that a person can read it. A rule set that reorganises itself every time the data is refreshed is hard to defend to somebody who memorised last quarter's version, and "the model is unstable but its accuracy is stable" is a sentence that satisfies nobody outside the room.
The counters. Limit the depth, since shallow trees are far steadier than deep ones. Set a minimum leaf size, which stops the bottom of the tree reorganising over single rows. Or average many trees, which fixes the variance completely and throws the readability away, and is the first aside at the end of this chapter.
The dial from §3a against both accuracies at once. §4b already put the held-out curve on a chart in order to argue about choosing the depth; this is the same curve with the training score beside it, which is where the mechanism shows. It is also bias and variance in its most literal form, because here you can watch the slivers appear.
The blue line reaching a perfect score is not an achievement, it is the definition of the problem: a tree deep enough will always get every training row right, because it can always ask one more question until each row sits alone.
The counters are §3b's four rules, and the one worth reaching for first is a minimum leaf size rather than a depth cap, because it targets the slivers directly. Choose whichever you use by cross-validation rather than by eye, which is what §4b is about, and remember that the held-out hundred above is drawing a picture rather than making a decision.
A quieter failure, and the one most likely to be sitting in a model somebody already shipped. A column with two hundred distinct values offers two hundred candidate thresholds. A column with three offers two. The search takes the best gain it can find anywhere, so the column with more chances to get lucky wins more often than it deserves to.
Push that to the limit and it becomes obvious. Add a column holding the match's reference number, which is unique per Saturday and means nothing. There is always a threshold on it that separates the training data perfectly, the gain is enormous, and the tree will take it. It will then score flawlessly on the data it learned from and be worthless, because next Saturday's reference number is one it has never seen.
The counters. Drop identifiers and near-identifiers before fitting, and treat that as a rule rather than a judgment call. Be suspicious of any high-cardinality column near the root. And do not read feature_importances_ as a ranking of what matters, since impurity-based importance inherits this bias exactly: the column with the most candidate splits accumulates the most credit. Permutation importance asks a different and better question, which is how much the score falls when you scramble that column.
Every other model on this site is hard to argue with because you cannot see inside it. A tree is easy to argue with, and that turns out to cut both ways. A rule path reads like a reason, and people accept it as one: "declined because postcode was in this list and income was below that number" sounds like an explanation, and it is only a description of a route through a structure that was fitted to whatever happened before.
The tree did not decide that postcode should matter. Somebody put the column in the table, and the search took it because it separated the rows. A model that can recite its reasoning is not a model that has reasons, and the fluency is exactly what makes it persuasive to a committee that would have pushed back harder on a coefficient.
Which makes the readability a responsibility rather than a feature. If the tree is going to be shown to people, somebody has to read it, all of it, and be willing to say that a split is unacceptable even though it improved the score.
Everything so far has predicted a label. Trees predict numbers with two small changes and nothing else, which is worth a page because it is the version buried inside every gradient boosting model you will ever use.
The search, the recursion and the stopping rules are untouched. Which means the geometry is untouched too: a regression tree still carves the map into rectangles, and inside each rectangle it predicts one constant number. Its output is a staircase, and it cannot produce a value outside the range it was trained on, for the same reason KNN cannot: an average of stored answers is bounded by those answers.
That staircase is the honest reason a single regression tree is rarely used on its own. A straight line through the same data is smoother and needs two numbers. What the tree brings is that it will handle a threshold, an interaction and a sharp corner without being told any of them exist, and the bias and variance page fits one on its running example so you can see the staircase directly.
Trees are three lines to fit and an assistant will get them running immediately. The trap is different from the other chapters: the code is right, the default settings are actively bad, and the output is so readable that nobody checks.
Three lines that fit a DecisionTreeClassifier() with no arguments. That default has no depth limit and a minimum leaf size of one, so it grows until every leaf is pure: on this data that is thirty-nine leaves and a flawless training score. It will print that score proudly. It will then offer to plot the tree, which at full depth is a wall, and probably quote feature_importances_ as though it were a ranking of what matters.
export_text, not as a picture,
7. uses permutation importance rather than feature_importances_, and says in one sentence why."The model is the same three lines. Points 2 and 3 stop the defaults from choosing the depth for you, which on this data is the difference between 86 and 75 percent on unseen Saturdays. Point 5 is the one nobody asks for and the one that changes how you present the result, because it tells you up front whether the rule path you are about to show somebody survives a refresh of the data.
Two instructions worth adding whatever else you ask for. Say what your class balance is, because an assistant will not ask, and on a rare outcome it will hand you a tree that predicts the majority everywhere and a score that looks excellent, for the reason in §2c's aside. And ask for the tree as text rather than as a plot: export_text gives you something you can read, diff against last month's, and paste into a document, and a rendered PNG of a thirty-nine leaf tree gives you a wall nobody will ever check.
A single decision tree is rarely the most accurate thing you can fit, and it is very often the right thing to ship anyway. It is the only model on this site that a person with no statistics can follow end to end, check line by line, and object to a specific part of. When somebody has to be told why, in a room, that is not a nice-to-have.
| If your problem looks like this | Reach for | Because | The price you pay |
|---|---|---|---|
| Thresholds and interactions, mixed column types, and somebody has to be able to read the rule | A single pruned treethis chapter | No scaling, handles categories and numbers together, and the output is a rule path rather than a coefficient. | Unstable, only cuts parallel to the axes, and rarely the most accurate option. |
| The same shape of problem, and nobody has to read anything | Random forestor gradient boosting | Averaging or correcting many trees removes most of the instability and usually wins on score. | The readability, which was the reason to pick a tree in the first place. |
| A roughly straight boundary, and you want a probability you can threshold | Logistic regressiona chapter of its own | Calibrated by construction, stable, and a signed weight per feature. | One straight boundary, and every nonlinearity built by hand. |
| A strange boundary shape, few columns, and no time to fit anything | K-nearest neighboursa chapter of its own | No training at all, and the explanation is the neighbouring cases themselves. | Scales badly with columns and pays at prediction time forever. |
The search takes whatever separates the rows. If a proxy for something you would never use on purpose is in the table, it will be at the root, and it will be in the rule path you show people.
Depth is usually tuned for score. If the point of the tree is that somebody can follow it, the depth that a person can hold in their head is the binding constraint, and it is smaller than the one cross-validation picks.
"Wind above 30" means 30.1 and 29.9 are treated as different worlds. The data has no opinion about where that line goes, and the person standing at 29.9 will.
It describes the route, not the justification. The justification is whatever put those columns in the table, and that was a person.
Almost nobody ships one tree. Both of the things they ship instead start from the failure modes above, and they take opposite routes out of them.
§5b said a tree reorganises itself when the data changes slightly. A forest takes that instability and uses it.
Fit a tree to a random sample of the rows, drawn with replacement so some Saturdays appear twice and some not at all. Do it again, and again. And at every split, let each tree choose from a random subset of the columns rather than all of them, so the trees are forced to disagree about what to ask rather than all finding the same root. Then let them vote.
What the forest decides
Accuracy on the unseen hundred
Watch the left picture rather than the number. With one tree the regions are jagged, with hard corners drawn around individual Saturdays. Add trees and the corners soften, because a corner that exists in one tree and not in the other forty-nine loses the vote. The averaging is removing variance, which is the mechanism bias and variance §1 describes and this is what it looks like on real regions.
And here is the honest result, which most write-ups skip. The forest comfortably beats a fully grown tree, which is what it is for. It does not beat a single tree whose depth was chosen properly on this data, because the real rule here is a handful of axis-aligned thresholds and one small tree can express it exactly. Forests earn their keep when there are many columns and no time to tune, which describes most real projects and not this one.
What you pay is the whole of §1: fifty trees voting is a number, not a rule path, and the thing you chose a tree for is gone.
The opposite idea. A forest grows its trees independently and averages them, so each one is a full attempt at the problem. Boosting grows them in sequence, and each new one is deliberately bad at almost everything except the cases the previous ones got wrong.
Start with every Saturday weighted equally and fit the smallest possible tree: one question, two leaves, a stump. It will be poor. Then increase the weight on every Saturday it got wrong and fit another stump to the reweighted pile, so the next question is forced to care about the hard cases. Repeat, and let the stumps vote with a say proportional to how well each one did.
The stumps so far, and what they add up to
Accuracy as rounds are added
Dots are drawn at a size proportional to their current weight, so you can watch the algorithm's attention move. The amber line is the stump this round fitted, and the shaded regions are what all the rounds so far agree on.
Two things to do with the slider. Step through the first few rounds one at a time and watch the weights: after round one, a band of Saturdays swells because the first stump got them wrong, and round two's question lands somewhere that deals with exactly those. The sequence is not fitting the data, it is fitting what is left over.
Then take it to the far end. The training score keeps creeping up and the held-out score peaks around … rounds and then slips. Boosting overfits, slowly and later than a single deep tree, but it does overfit, and the number of rounds is a hyperparameter exactly like depth. The modern libraries with the familiar names are this idea with better mathematics underneath, and they still ask you how many rounds.
The trade is the same one twice over: both of these buy accuracy and stability with the readability that was the point of a tree. If you needed the explanation, you needed the single tree, and this whole section is about what you give up to leave it behind.