AI Engineering Learning Hub

Decision Trees

Decision trees explained: how Gini impurity picks the best split, why trees overfit, and how max_depth and ensembles fix it.

What it is

A decision tree predicts by asking a sequence of yes/no questions about the features: is credit score above 650, is income above 40,000, is the loan amount below 20,000. Each question splits the data into two groups, and the questions continue until a group is pure enough, meaning almost all of its rows share one answer. That final group is a leaf, and its majority answer becomes the prediction.

Unlike linear or logistic regression, there are no weights and no gradient descent. The tree is built greedily, top down: at each node it tries every feature and every cut point, measures how much purer the two child groups would be, and keeps the best split.

The result reads like a flowchart, which is why trees are popular when people need to understand or audit a decision.

Why it's needed

Trees handle things that linear models struggle with: non-linear relationships, interactions between features, mixed numeric and categorical data, and no need for feature scaling. They are also fully interpretable, so a loan officer can see exactly why an application was declined.

They also matter as building blocks. Random forests and gradient boosting, which win most tabular-data competitions and power a lot of production scoring systems, are ensembles of decision trees. Understanding one tree is the prerequisite.

How it works

  • Start at the root with all rows. For each feature and each candidate threshold, split the rows into two groups.
  • Score each split with Gini impurity, 1 - sum(p_class^2), or entropy. A pure group scores 0; a 50/50 group scores the maximum.
  • Choose the split with the lowest weighted impurity across the two children, then repeat the process on each child.
  • Stop when a group is pure, has too few rows, or the tree reaches max_depth. That node becomes a leaf.
  • Predict by walking a new row from the root to a leaf and returning the leaf's majority class, or the mean value for regression.
  • Control overfitting with max_depth, min_samples_leaf and min_samples_split, or by pruning after growth.

Code example

import numpy as np
from sklearn.tree import DecisionTreeClassifier, export_text
from sklearn.model_selection import train_test_split

# Toy loan data: [credit_score, income_k, loan_k] -> approved (1) / declined (0)
rng = np.random.default_rng(1)
X = np.column_stack([rng.integers(500, 800, 300), rng.integers(20, 120, 300), rng.integers(5, 50, 300)])
y = ((X[:, 0] > 640) & (X[:, 2] < X[:, 1] * 0.5)).astype(int)
y[rng.random(300) < 0.08] ^= 1   # flip 8% of labels to simulate real-world noise

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=1)

for depth in (None, 3):
    tree = DecisionTreeClassifier(max_depth=depth, random_state=1).fit(X_train, y_train)
    print(f"max_depth={depth}: train {tree.score(X_train, y_train):.2f}  test {tree.score(X_test, y_test):.2f}")

# The depth-3 tree reads like a set of business rules
print(export_text(tree, feature_names=["credit_score", "income_k", "loan_k"]))

Use cases

  • Loan approval and credit risk decisions where every rule must be explainable
  • Customer churn or fraud flags on mixed numeric and categorical data
  • Quick, scale-free baselines on tabular data
  • The base learner inside random forests and gradient-boosted models

Common mistakes

  • Growing the tree with no depth limit and reporting a training accuracy of 100 percent.
  • Trusting a single tree's feature importances, which shift a lot when the training data changes slightly.
  • Expecting a tree to extrapolate; it can only predict values it saw in training leaves.
  • One-hot encoding a high-cardinality categorical feature, which spreads the signal across many weak splits.
  • Using a tree on a problem that really is linear, where it needs many splits to approximate a simple line.

Interview questions

How does a decision tree choose the best split?
It evaluates every feature and threshold and picks the split whose two child groups have the lowest weighted impurity, measured with Gini impurity or entropy. The chosen split is the one that makes the groups purest, meaning each is dominated by a single class. This happens greedily, one node at a time, with no look-ahead.
Why are decision trees so prone to overfitting?
Without a limit, a tree keeps splitting until every training row sits in a pure leaf, which means it has memorised the data, noise included. Each leaf might hold one or two rows, and those rules do not generalise. max_depth, min_samples_leaf and pruning stop it early.
Gini impurity or entropy: does the choice matter?
Rarely in practice. Both measure how mixed a group is and usually choose the same splits. Gini is slightly faster since it has no logarithm, which is why scikit-learn uses it by default. Entropy, via information gain, is the textbook choice from the ID3 and C4.5 algorithms.
What is the difference between a decision tree and a random forest?
A random forest trains many trees, each on a random sample of rows and a random subset of features at each split, then averages their votes. Individual trees overfit in different ways, so the average cancels most of the noise. You lose single-tree interpretability but gain a lot of accuracy and stability.
Do decision trees need feature scaling?
No. A split asks whether a value is above or below a threshold, and that comparison is unaffected by scaling. This is one reason trees are convenient on raw tabular data with mixed units.
How does a decision tree handle regression?
Same structure, different scoring. Instead of impurity it minimises the variance of the target within each child group, and a leaf predicts the mean target of its rows. The prediction is a step function, so it cannot extrapolate beyond the training range.
How would you explain a tree's decision to a non-technical stakeholder?
Walk the path from root to leaf as a list of plain rules: credit score above 640, loan under half of income, therefore approved. scikit-learn's export_text prints exactly that, which is why trees are favoured in regulated settings.
Ask the AI assistant about this topic

Get new topics by email

One short, practical AI-engineering lesson whenever a new topic is published. No spam, unsubscribe any time.

Need this built for your product?

I build production RAG pipelines, LLM automations and voice agents. Open to freelance projects and full-time roles.