The Problem
Decision trees solved one major representation problem. They allowed us to learn complex, non-linear decision boundaries without forcing every prediction through one global equation.
Unfortunately, they created another problem. A single decision tree is unstable. Small changes in the training data can produce a very different tree.
Imagine training a tree to predict whether Jessie will order a burger. Last week the root question might have been:
Hungry? yes -> Burger no -> Salad
This week you collect a few more restaurant visits and retrain. Now the first question becomes:
Friends ordering burgers > 2? yes -> Burger no -> Hungry?
Nothing about Jessie changed dramatically. Only a few examples changed. This is high variance: the learned model moves too much when the training set moves a little.
How can we keep the flexibility of decision trees while making their predictions more stable?
Core Intuition
Instead of trusting one decision tree, build many. Each tree is trained slightly differently. Each tree makes its own prediction. The forest combines all of those predictions into one final answer.
One tree might overreact to a strange training example. Another might split on a noisy feature. A third might find a useful rule. When many trees vote, the individual quirks begin to cancel out.
One tree
Flexible, interpretable, but unstable.
Many different trees
Still flexible, but their errors are less synchronized.
Vote or average
A smoother prediction that usually generalizes better.
Random Forest is an ensemble method. An ensemble combines many models into one predictor. Its central idea is simple: a group of imperfect but diverse models can be more reliable than any one member of the group.
Interactive Demo
Turn off both randomness switches and the trees move together. Turn them back on and the individual votes vary, so one new example changes the forest more gently.
Add a new example and compare the vote with randomness on and off. The forest is useful because the individual trees can change without forcing the whole prediction to swing wildly.
Mathematics
Random Forest has two mathematical stories. First, there is the algorithm: the computations performed to train and predict. Second, there is the reason it works: variance reduction through averaging low-correlation models.
The Algorithm
Suppose the training set is . We want to build decision trees.
1. Bootstrap sampling
For each tree, sample n training examples with replacement. Some rows appear more than once, and some rows are left out entirely.
2. Random feature selection
At each split, choose only m candidate features out of d total features. The tree must pick the best split from that smaller random set.
3. Grow each tree
Train every tree independently using the same impurity reduction rule from decision trees. Random Forests usually allow deep trees rather than pruning them aggressively.
4. Aggregate predictions
For classification, take the majority vote. For regression, average the predictions.
Bootstrap sampling means each tree receives a new dataset created by sampling rows from with replacement. Because replacement is allowed, a row can be chosen multiple times.
Random feature selection means a split does not compare every possible feature. If the original data has features, the split considers only randomly selected features, where . For classification, a common default is:
At every node, the tree still chooses the split with the largest impurity reduction, just as in the decision-tree chapter.
After the trees are trained, prediction is aggregation. For classification, each tree predicts one class and the forest returns the mode.
For regression, the forest averages the tree predictions.
Why It Works
Random Forest works because it reduces variance. A single tree can change a lot when the training data changes. Averaging many trees makes the final prediction less sensitive to any one tree.
Averaging only helps if the trees are not identical. If every tree makes the same mistake, the forest repeats that mistake. Random Forest therefore injects randomness in two places: the rows each tree sees and the features each split can consider.
Suppose every tree has variance . If the trees were completely independent, the variance of the average prediction would be:
Real trees are not completely independent. They are correlated because they are trained on data from the same underlying problem. A useful approximation is:
Here is the average correlation between trees. This equation explains the design of the method. Increasing shrinks the second term. Reducing correlation shrinks the first term.
Why Bootstrap Sampling?
If every tree receives the same dataset and can inspect every feature, many trees will learn similar boundaries. Their errors will be highly correlated, so averaging provides little benefit.
Bootstrap sampling creates natural diversity. In one bootstrap sample, the probability that a particular training example is not chosen is:
So a bootstrap sample contains about 63.2 percent unique examples on average, and about 36.8 percent of the original rows are omitted from that tree. Those omitted rows are called out-of-bag examples and can later be used to estimate performance.
Complexity
If training one tree costs approximately , then training trees costs approximately:
Prediction also scales with the number of trees because every tree makes one prediction. Random Forest is slower than a single tree, but it usually gives much better generalization.
Implementation
This implementation assumes you already have a decision-tree builder that accepts a random subset of features when choosing each split. Random Forest adds three pieces: bootstrap sampling, repeated tree training, and majority voting.
import numpy as np
class RandomForestClassifier:
def __init__(self, n_trees=100, max_depth=None, max_features="sqrt"):
self.n_trees = n_trees
self.max_depth = max_depth
self.max_features = max_features
self.trees = []
def _feature_count(self, n_features):
if self.max_features == "sqrt":
return max(1, int(np.sqrt(n_features)))
if self.max_features == "all":
return n_features
return int(self.max_features)
def _bootstrap_sample(self, X, y):
n = len(X)
indices = np.random.choice(n, size=n, replace=True)
return X[indices], y[indices]
def fit(self, X, y):
self.trees = []
m = self._feature_count(X.shape[1])
for _ in range(self.n_trees):
X_sample, y_sample = self._bootstrap_sample(X, y)
tree = DecisionTreeClassifier(
max_depth=self.max_depth,
max_features=m,
)
tree.fit(X_sample, y_sample)
self.trees.append(tree)
return self
def predict_one(self, x):
votes = [tree.predict_one(x) for tree in self.trees]
values, counts = np.unique(votes, return_counts=True)
return values[np.argmax(counts)]
def predict(self, X):
return np.array([self.predict_one(x) for x in X])The important design detail is inside the tree. At each node, the tree should pick a fresh random subset of features before searching for the best split. That is what keeps the trees from all choosing the same obvious feature at the root.
Interview Discussion
Why are decision trees unstable?
A tree makes greedy split decisions. A small data change can alter an early split, and every later split depends on that earlier choice.
Why is bootstrap sampling performed with replacement?
Replacement makes each tree see a different dataset of the same size as the original. Some examples repeat and some are omitted, which creates diversity.
Why are features sampled randomly?
Feature sampling lowers correlation between trees. It prevents every tree from relying on the same strongest feature at the same split.
Does Random Forest reduce bias or variance?
Its main effect is variance reduction. Individual trees are often high-variance models, and averaging many decorrelated trees stabilizes them.
Why can a forest generalize well even if each tree overfits?
Each tree overfits in a slightly different way. If those errors are not perfectly correlated, voting or averaging cancels out many of them.
Why is Random Forest harder to interpret than one tree?
One tree is a readable chain of rules. A forest may contain hundreds of trees, so the final prediction is distributed across many paths and votes.
Active Recall
1. Explain Random Forest to someone who has only learned decision trees.
2. Why are two sources of randomness used instead of one?
3. Why can a forest generalize better than a single tree even if every tree overfits?
4. What does the correlation term rho explain in the variance equation?
5. Describe the training algorithm without looking at the equations.
Common Mistakes
- Believing every tree sees the same dataset.
- Forgetting that bootstrap sampling is performed with replacement.
- Thinking Random Forest mainly reduces bias. Its main job is variance reduction.
- Assuming more trees usually cause overfitting. More trees usually make the forest more stable.
- Forgetting that feature sampling happens at each split, not just once per tree.
Connection To Gradient Boosting
Decision trees introduced flexible non-linear decision boundaries, but they suffered from high variance. Random Forest preserves that flexibility while stabilizing the prediction through bootstrap sampling, random feature selection, and aggregation. Gradient Boosting asks the next question: can each new tree focus specifically on the mistakes made by the previous trees?