How to invent the decision tree algorithm from scratch
This lesson has two halves. In the first, you will build a working decision tree with your eyes and your hands — no formulas. In the second, you will discover that the real training algorithm is nothing more than what you just did, repeated by a patient loop that scores its choices with one small number.
By the endYou will be able to explain how a computer learns a decision tree by repeating one useful operation: ask a yes-or-no question that makes known outcomes less mixed. You will also trace a new example through the finished tree.
Starting point: you only need to compare numbers and follow a yes-or-no question. We will introduce every machine-learning term and unpack the mathematical notation when it first becomes useful.
Part one · build it by hand
Machine learning is not one single method
When people say machine learning, it can sound like the name of one technology. It is closer to a toolbox. The field is full of different algorithms, and each one learns patterns from examples in its own way, then uses those patterns to make predictions about examples it has never seen.
Neural networks are the famous family. They are behind striking results in text, images, audio, and video. But fame is not the same as fit. A great deal of everyday data lives in tables — customers, houses, plants, loans, medical measurements — and on tables, tree-based methods are often the strong, practical choice. To see why, start with what makes a table different from other data.
Each row describes one thing
A sentence is a sequence of words: order matters. An image is a grid of pixels: position matters. In our seed table, each row describes one seed, and the columns record named properties of that seed. Shuffling these rows would not change their meaning because no seed depends on the row before it.
Sequence
Order matterswords, events, sound
Grid
Position mattersimages, spatial maps
Table
Properties matterpeople, plants, products
In this kind of table, each row stands on its own, so we can ask the same small question of every row.
Think about people at a party. One person is tall, blond, and wearing glasses. Another is short, brunette, without glasses. This kind of data invites yes-or-no questions — is the person tall? are they wearing glasses? — and each answer divides the group in two. A table works the same way: a question about one column sends some rows one way and the rest the other way.
Hold on to that observation. Small questions are a natural way to organize tabular data, and — as we are about to see — they may be enough to predict something we do not know yet.
Our running example
Ten seeds and one prediction
Imagine we planted ten seeds. Each one received a certain number of sunlight hours per day and a certain number of liters of water per week. At the end of the experiment, each seed was either thriving or struggling.
Seed
Sunlight / day
Water / week
Outcome
A
1.0 h
1.4 L
Thriving
B
1.4 h
2.7 L
Thriving
C
2.0 h
1.9 L
Thriving
D
2.5 h
3.5 L
Struggling
E
3.2 h
2.4 L
Thriving
F
3.8 h
4.2 L
Struggling
G
4.3 h
1.5 L
Struggling
H
4.9 h
3.1 L
Struggling
I
5.5 h
2.0 L
Struggling
J
6.1 h
3.9 L
Struggling
Swipe horizontally to inspect every column.
Each row is one seed. Sunlight and water are features. The outcome is the label.
Entity
one seed
Features
sunlight and water
Label
thriving or struggling
Now a friend brings us seed K. It will get 3 hours of sunlight per dayand 2 liters of water per week. Can the ten old seeds help us predict what will happen to the new one?
This task is called classification: we are not predicting an exact height, we are choosing between two labels — thriving or struggling.
The first invention
A split is a question
Staring at the table row by row is hard, so let us spread it across two axes. Sunlight runs left to right, water runs bottom to top. Circles are thriving seeds; squares are struggling seeds.
The same ten rows are now points. Shape carries the outcome, so color is not required. No answer has been drawn for you yet.
A line on this graph can act like a yes-or-no question. A vertical line asks whether sunlight is at most some cutoff. A horizontal line asks the same kind of question about water. We have not chosen the feature or cutoff yet.
Your first job is only visual: find one line that leaves circles and squares less mixed on its two sides. There may be several reasonable attempts. Commit to one before asking the playground for its clearest answer.
Try it yourself
Where would you place the first line?
Choose sunlight or water, then drag the line directly across the graph. No formulas yet — just try to make the outcomes on each side look as uniform as possible. The opening line is only a starting guess, not the answer.
Playground 1 · use your eyes
Where would you draw the dividing line?
No formula yet
1 · Choose what to inspect
2 · Drag or click in the graph
Sunlight hours ≤ 2.25?
This is only a starting position. Move the line before revealing the answer.
The same ten seeds · move the question directly
What your line creates
Hover or focus a seed to find the same row or point on the left.
The yes branch contains 3 seeds: 3 thriving and 0 struggling. The no branch contains 7 seeds: 1 thriving and 6 struggling.
Use only your eyes:Does each side now contain outcomes that look more alike than the original table?
The reveal checks every available position and returnssunlight ≤ 3.5 hours. Seeds A through E answer yes: four are thriving and D is struggling. The other five answer no, and all five are struggling.
That question turned one mixed group into two less-mixed groups. The right group is finished because every seed in it struggles. The left group still contains both outcomes, so it needs another question. A cutoff such as 3.5 is called athreshold. A feature-and-threshold question that divides a group is called a split.
Turn one question into a structure
A mixed region can answer another question
One line is only the beginning. After a question divides the graph, each region holds a smaller version of the original problem. A region where every seed has the same outcome can stop. A mixed region can ask another question — using only the seeds inside it.
This is where lines become a tree. In the playground below, select a region, choose a feature, and cut only that region. The panel on the right records the exact same sequence of questions as a branching structure: the first cut is the root, each later cut hangs under the answer that led to it.
Build it by hand
Can you make every final region contain one outcome?
Start with the whole graph. After every cut, pick a mixed region and continue. There is more than one valid tree, so follow whatever pattern you can see.
Playground 2 · build the tree
Turn regions into a decision tree
0 questions · 0/1 regions clear
1Choose a region2Choose an axis3Click the region to cut
Data space · regions and axes are clickable
Tree controls
What your lines create · the same tree
A mixed leaf still contains circles and squares. Select it to keep growing.
The tree has 0 questions and 1 final regions; 0 are clear.
Keep seed K in view
Can the tree already make K's prediction?
If you opened the guided solution, answer its two questions for K: 3 hours of sunlight and 2 L of water. If you made a different tree, follow your own questions instead.
Reveal the guided path
K answers yes to sunlight ≤ 3.5 and yes to water ≤ 3.1, so it reaches the thriving leaf. We can already use the tree; the next part explains how a computer can choose those questions without our visual judgment.
The pivot of this lesson
Stop and look at what you just did
Whether you completed the tree yourself or opened the guided solution, the construction used no formula. A node is a question, its two answers are branches, and every final region is a leaf that makes a prediction. The construction used exactly three skills:
Propose. You slid a line across a region and it snapped between neighboring seeds.
Judge. You looked at both sides and decided whether the outcomes became more alike.
Repeat. Inside any region that stayed mixed, you did the same thing again.
Two of those skills are mechanical. Proposing lines is a loop over positions. Repeating is the same procedure applied to a smaller group. A computer can do both without any insight.
The third skill is the obstacle. “This side looks cleaner” is a judgment, not an instruction. To automate the whole process, we need to replace your eyes with a number — one score that says how well did this question separate the outcomes? That single replacement is the entire second half of this lesson. Everything else, you have already invented.
Part two · automate it
Only a few questions are worth asking
Before scoring questions, we should count them. A threshold like 2.25 can feel arbitrary — why not 2.3, or 2.31? Look at the sunlight column: 2.0 and 2.5 are neighboring values. Every line drawn between them sends the same rows to the same sides. All those thresholds are the same question wearing different numbers, so we test just one of them: the midpoint.
(2.0 + 2.5) / 2 = 2.25
This makes the search finite. Sort the distinct values of a column and take the midpoint of each neighboring pair: ten distinct values give nine candidate thresholds. Two features, nine thresholds each — at the root there are exactly18 questions worth testing, not infinitely many. The playgrounds above were already snapping your line to these midpoints.
So the computer can generate every question worth asking. What it still cannot do is pick the best one. “This looks cleaner” has to become a number.
Step one: measure the mixture of a single group
Forget splits for a moment and look at one group of seeds. What your eyes actually checked, side by side, was how mixed each group was. A useful mixture score should follow three rules:
A pure group scores 0. If every seed has the same outcome, there is no mixture.
An even mixture scores highest. A 50/50 group is as mixed as two classes can be.
Only the label counts matter. The score should not care where the seeds sit or what order they are in.
The standard choice for classification trees is Gini impurity, and it has a concrete meaning. Imagine drawing one seed label from a bowl, putting it back, and then drawing again. Putting it back keeps the odds the same on both draws. Gini is the chance that the two labels disagree.
Our full group has four thriving and six struggling seeds. Disagreement can happen in two orders. We can draw thriving and then struggling, or struggling and then thriving:
thriving, then struggling4/10 × 6/10 = 0.24struggling, then thriving6/10 × 4/10 = 0.24either disagreementGini = 0.24 + 0.24 = 0.48
In a pure group, disagreement is impossible, so Gini is 0. In a two-class group split evenly, disagreement is as likely as it can be, so Gini reaches 0.5.
Optional notation: compress the same calculation
Let p mean “the share of the group.” Here, p(thrive) is 0.4 and p(struggle) is 0.6. Squaring a share means multiplying it by itself, which is the chance of drawing that same label twice. So another way to count disagreement is to subtract every way the labels could agree from 1:
For more than two labels, mathematicians shorten “subtract the square of every class share” to Gini = 1 − Σ pₖ². The symbol Σ means “add one term for every class,” and the small k identifies which class a term belongs to. This compact form is not needed for the rest of this lesson.
That is close to the maximum possible value of 0.5 for two classes. It does not mean a model is wrong 48% of the time — there is no model yet. It only means the group still contains a strong mixture of both labels.
For two classes, Gini peaks at a 50/50 mixture and falls to zero as either class takes over the whole group — exactly the behavior we asked for.
Step two: score a question, not just a group
A question creates two groups, so we need to combine two Gini values into one score. Take the clearest first question, sunlight ≤ 3.5. The yes side has four thriving seeds and one struggling seed. The no side has five struggling seeds — pure, Gini 0:
Gini(yes side) = 1 − (4/5)² − (1/5)² = 0.32
Each side is weighted by the fraction of rows it received. Here the split happens to send five rows each way, so the weights are equal; the same rule also works when later splits create unequal groups:
score after the split = 5/10 × 0.32 + 5/10 × 0 = 0.16
Before the question, the group's Gini was 0.48. After it, the weighted mixture is 0.16. The improvement is called the Gini gain:
gain = 0.48 − 0.16 = 0.32
This is the number that replaces your eyes. A higher gain means the question removed more mixture. It uses nothing but label counts, so a computer can evaluate it for any candidate question in a few multiplications.
Check the idea
Why do we weight the two sides by their row counts?
Try to answer before opening the explanation.
Reveal the reasoning
Without weights, a tiny pure group could hide a large messy one. A split that isolates a single seed would look as good as a split that cleanly organizes half the table. The weights make each side matter in proportion to the rows it holds.
The score can compare any two candidates
To feel the score working, keep the feature fixed and move only the threshold. Before reading the numbers below, look at the two pictures and predict which question leaves less mixture behind.
Same data, same feature, different threshold. Make a visual prediction first, then open both score breakdowns. The candidate with the larger gain is the one that leaves less weighted mixture behind.
The whole algorithm
Two loops and a memory
Now every ingredient is on the table, and the algorithm almost writes itself. At the current group of rows:
For each feature — sunlight, then water —
for each midpoint threshold of that feature,
compute the Gini gain of the question they form,
and remember the best one seen so far.
That is the entire search: two nested loops and one remembered winner. There is no cleverness inside — the computer does exactly what you did in the first playground, except it checks all 18 questions and refuses to have taste. Watch it run.
Playground 3 · automate the choice
Let the computer try every question
0 of 18 questions tested
No line tested yet
The search has not started. Run it and watch the line sweep across both features, one question at a time.
The search ledger · one gain per question
for each threshold of Sunlight hours
for each threshold of Water / week
Each bar will record the gain of one question. The search keeps the tallest.
If you ran the search to the end, the numerical winner matched the pattern your eyes could see: sunlight ≤ 3.5 leaves all five high-sunlight seeds together in a pure struggling group and earns a gain of 0.320. The loop did not invent a new idea; it measured every possible line and confirmed the clearest one.
The third skill: repeat inside every mixed leaf
One search gives one question, and one question is not yet a tree. The winning split leaves F, G, H, I, and J in a pure struggling leaf — that side is done. The other side still holds both labels, so we run the exact same searchon A, B, C, D, and E alone. Water ≤ 3.1 separates D from the four thriving seeds, and every leaf is pure.
This pattern — a procedure that applies itself to the smaller problems it creates — is called recursion. The rule never changes; only the set of active rows shrinks. Step through it below and try to predict which group will split next.
One winner, two equivalent score views
The previous playground kept the largest gain. The two charts below keep the smallest weighted Gini after the split, one chart per feature. These choose the same winner because the starting Gini is fixed:gain = starting Gini − Gini after the split.
Playground 4 · automate the recursion
Watch local searches become a tree
0 of 2 splits committed
Recursion selected the root: only this region's 10 rows enter the next search.
Same points · the line sweeps only the active region
Local search · root0/18 thresholds
Sunlight hours
Water / week
The sweep has not started inside this region yet.
Each local winner enters the tree
rows waiting here10 samples
ABCDEFGHIJ
Region in focusroot10 rows in this search
The finished structure is worth a full look:
Swipe horizontally to follow the complete tree.
Two searches, two questions, three leaves. The regions you cut in the graph and the leaves of this tree are two views of the same partition.
Compare it with the tree you built by hand. The computer may not have made your exact cuts, but it followed your exact method — and now the two vocabularies line up:
Nodea group of rows and a question
Branchone answer to the question
Leafa final group and its prediction
Stress the mechanism
The same small questions can build complex boundaries
The seed dataset ended after two questions because its pattern was unusually cooperative. The algorithm is not limited to two cuts. Each new question acts only inside one existing region, so vertical and horizontal lines can compose into stripes, staircases, boxes, and many smaller rectangles.
Choose a point pattern below and predict what the tree will need before you run it. Then step through the same Gini search you just learned: iterate overx and y, try every midpoint threshold, keep the largest gain, and repeat inside the remaining mixed regions.
Playground 5 · vary the data
Watch the same search grow different trees
0 of 1 splits committed
One clean cut. One vertical question separates every point.
Recursion selected the root: only this region's 12 rows enter the next search.
Same points · the line sweeps only the active region
Local search · root0/22 thresholds
x
y
The sweep has not started inside this region yet.
Each local winner enters the tree
rows waiting here12 samples
123456789101112
Region in focusroot12 rows in this search
The invariant is now easier to see. A more elaborate boundary does not require a more elaborate kind of question; it requires more rounds of the same search. The diagonal becomes a staircase because this tree only asks one-feature, axis-aligned questions. The center island needs nested cuts because no single vertical or horizontal question can isolate the middle group.
More splits also mean more chances to fit accidents in the training points. That is why tree complexity cannot grow without a stopping rule.
When should the tree stop?
Our toy data becomes pure after two questions. Real data is noisier, and a tree that keeps splitting can end up memorizing tiny accidents of the training set. Practical trees therefore stop growing a branch when any of these hold:
The node is pure. Every active row has the same label.
No split has positive gain. The available questions do not improve the group.
The depth limit is reached. We refuse to ask more nested questions.
Too few rows remain. We avoid making a rule from a fragile group.
When a branch stops, its leaf predicts the most common label among its rows. It can also keep the class counts: a leaf with eight thriving and two struggling seeds is less certain than a leaf with ten thriving seeds, even though both predict thriving.
The tree is greedy
At each node, the search keeps the best split it can see right now. It never asks whether a slightly worse first split might enable much better later splits — testing every possible complete tree would be astronomically expensive. This shortcut makes training fast, and its cost is honesty about the word “best”: the winning split is only the best local choice, under the current score, for the current rows.
Prediction travels through the finished questions
Training searched through many questions; prediction only answers the ones that survived. A new row starts at the root and follows one branch at a time until it lands in a leaf.
Return to seed K
Seed K gets 3 hours of sunlight and 2 L of water. Where does it land?
Name each answer before opening the path.
Reveal the path
Sunlight is at most 3.5, so K goes left. Water is at most 3.1, so K goes left again — into the thriving leaf. This is a prediction from our tiny dataset, not a claim that this sunlight and watering plan causes a seed to thrive.
A perfect training result can be a warning
This tree classifies all ten training seeds correctly. That is convenient for teaching, because every step stays visible. On real data, perfection is often a symptom: the tree may have memorized the training rows instead of learning a pattern. This failure is called overfitting, and we detect it by testing on labeled data the tree never used while choosing its thresholds. Depth limits, minimum group sizes, minimum gain, and pruning all express the same principle: a new branch must earn its complexity.
Human ideafind a small question that reveals a pattern
Mathematical rulemaximize the drop in weighted mixture
Learned structurequestions connected by yes and no branches
Predictionanswer questions until a leaf is reached
Beyond the plane
More features, same two loops
Every playground so far used two features, and that was a choice of scenery, not of method. Two features fit on a screen, so each question could be drawn as a line. But look back at what the search actually consumed: it sorted one column, took midpoints, counted labels, and computed a gain. At no point did the algorithm look at the picture. It read columns.
So let it read more of them. The table below describes twelve greenhouse seedlings with three measurements each — sunlight, water, and temperature. A third feature would already need a three-dimensional graph, and a fourth would defeat drawing altogether. The table has no such limit, so this time the table itself is the data space.
Nothing in the recipe changes. For each feature — now three of them — and for each midpoint threshold of that feature, compute the Gini gain of the question they form and remember the best one seen so far. Twelve distinct values per column give eleven midpoints, so the root search tests exactly 3 × 11 = 33 candidates. Then the winning question divides the rows into two groups, and the same search runs again inside any group that stays mixed.
Watch it generalize
Which column would you ask about first?
Scan the table before running the search. While a question is being tested, the rows that answer yes light up, and the charts under the table record the weighted Gini of every threshold tried — the same ledger you already know, with one extra lane.
Playground 6 · beyond two features
Let the same search loop over three columns
0 of 3 splits committed
Recursion selected the root: only rows 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 enter the next search.
The table is the data space · highlighted rows answer yes to the current question
Seedling training data and current candidate routes
ID
Sunlight hours
Water / week
Temperature (°C)
Class
1
3.9
3
14
□Struggling
2
4.2
3.1
16
□Struggling
3
5
3.6
15
□Struggling
4
3.2
2.8
17
□Struggling
5
4.5
1
23
□Struggling
6
4.6
1.4
26
□Struggling
7
2
2.2
27
□Struggling
8
1.5
3.3
22
□Struggling
9
3.5
2.6
21
○Thriving
10
4
2.9
24
○Thriving
11
4.8
3.4
20
○Thriving
12
5.5
4
25
○Thriving
Local search · root0/33 thresholds
Sunlight hours
Water / week
Temperature (°C)
The sweep has not started inside this region yet.
Each local winner enters the tree
rows waiting here12 samples
123456789101112
Group in focusroot12 rows in this search · 33 candidates
The winning root question came from the temperature column — a feature no two-dimensional graph of sunlight and water could even display. The loop did not need to know that in advance; temperature simply produced the largest gain, so the memory kept it. The recursion then ran twice more: inside the warm group, water separated the three underwatered seedlings, and inside the warm, watered group, sunlight isolated the single shaded one. Three searches, three features, four pure leaves — every column earned its node by winning one local search.
This is the entire generalization. The loop never asks how many columns the table has; it only asks for the next one. Ten features would mean ten lanes in the ledger and a longer loop — not a new idea. The two-feature graphs of this lesson were scaffolding for your eyes. The algorithm was reading the table all along.
This is still a toy problem
Every playground in this introduction uses at most three numeric features, so every step of every search stays visible. Real tables can have far more columns, missing values, more than two classes, and categorical or ordinal columns. Those cases require decisions about valid questions, routing, encoding, stopping, and evaluation that this article does not cover. Our goal here was narrower: expose the main principle faithfully — iterate over features and thresholds, score every candidate with Gini, keep the best local split, and recurse.
Keep the smallest useful mental model
A decision tree is a repeated search for useful questions.
At each node, try every candidate split. Keep the one that most reduces the mixture of known labels. Then repeat only where the labels are still mixed.
You built the tree first and met the algorithm second — and that order was the point. The formula did not introduce a new idea; Gini gain only turned the judgment your eyes were already making into a number a loop could maximize. The diagram was never the starting point. It was the result.
You understand the mechanism if you can now…
look at a small table and propose a useful threshold;
explain why only midpoint thresholds need to be tested;
calculate Gini impurity and weighted Gini gain;
state the training algorithm as two loops plus recursion;
predict why different point geometries require different tree shapes;
explain why the winning split is only a local winner;
trace a new row from the root to a prediction.
One difficult idea each week
Get Grove in your inbox.
One visual article, its central experiment, and a question worth carrying forward. Double opt-in; leave whenever you want.