Machine Learning Slides 📂 Introduction · 11 of 17 61 min read

Random Forest Explained — Bagging, OOB Score

A visual, beginner-friendly guide to Random Forest — the ensemble that turned decision trees into a production workhorse. Learn bagging with bootstrap sampling, random feature subsets at every split, majority-vote aggregation, out-of-bag validation for free, feature importance via MDI vs permutation, key hyperparameters like n_estimators and max_features, sklearn implementation, six common pitfalls and seven golden rules.

🌲

Random Forest

The ensemble that made decision trees production-worthy — hundreds of diverse trees voting together to crush variance, resist overfitting, and hand you free feature importance and out-of-bag validation.
Bagging Random Features Majority Vote OOB Score

Press Next → or use ← → arrow keys

Section 01

What Is A Random Forest?

A jury of 300 decides better than one confident juror
A single decision tree is like one enthusiastic juror who reads every file and confidently gives a verdict — often right, sometimes catastrophically wrong. Change one file and their whole verdict flips.

A Random Forest assembles 300 jurors. Each one reads a different random slice of the evidence and considers only a random subset of questions. Their individual mistakes point in every direction, so when they vote, the errors cancel out and the truth emerges. That's the entire idea.
💡
The Working Definition

A Random Forest is an ensemble of decision trees, each trained on a bootstrap sample of the data with a random subset of features at every split. Classification predictions are the majority vote; regression predictions are the average across all trees.

300+Typical tree count
~63%Unique rows per tree
√pFeatures per split (classif)
n_jobs=-1Embarrassingly parallel
Section 02

The Architecture — From One Dataset To One Prediction

FULL DATASET N rows · p features bootstrap 1 random rows + features bootstrap 2 random rows + features bootstrap 3 random rows + features bootstrap N random rows + features 🌳Tree 1 🌳Tree 2 🌳Tree 3 🌳Tree N FOREST PREDICTION majority vote · or · mean 1️⃣ 2️⃣ 3️⃣ 4️⃣
🧩
Four-Step Recipe

1️⃣ Start with the full dataset. 2️⃣ Draw many bootstrap samples (rows with replacement). 3️⃣ Grow one deep tree per sample, considering only a random subset of features at each split. 4️⃣ Aggregate the trees — vote for classification, average for regression. That's the whole model.

Section 03

Bootstrap Sampling — Rows Drawn With Replacement

Dataset of 10 rows → 4 trees, each gets a bootstrap sample Tree Rows in bootstrap sample (with replacement) Out-of-Bag rows Tree 1 1 3 3 5 7 7 9 2 4 4 6 8 10 Tree 2 2 6 6 1 8 10 10 4 9 4 3 5 7 Tree 3 3 7 10 2 2 5 6 8 8 1 4 9 Tree 4 5 9 5 4 1 7 7 3 3 6 2 8 10 unique pick duplicate (drawn twice) out-of-bag each tree gets ~63% unique rows · ~37% left out for free validation
🎲
Same Size, Different Sample

Every bootstrap sample has the same number of rows as the original dataset — but drawn with replacement. Some rows appear twice or three times; others don't appear at all. Those absent rows become each tree's out-of-bag test set.

Section 04

Random Feature Subsets — The Second Diversity Trick

Bootstrap sampling shuffles the rows. Random feature subsampling shuffles the columns — at every single split, each tree considers only a random handful of features. This is what stops one dominant feature from bossing every tree the same way.

Classification default
max_features = √p
With 100 features, each split considers only ~10. Encourages weak features to shine on some trees.
Regression default
max_features = p / 3
Slightly more features per split — regression benefits from smoother averaging.
🎲
Why It Works
forces diversity
Without feature subsampling, one dominant predictor would win the root split on every tree — and every tree would look the same.
🧠
The Result
uncorrelated errors
Trees make different mistakes on different examples. When 300 diverse trees vote, the mistakes cancel.
🎚️
First Thing To Tune
max_features
This parameter has the biggest impact on accuracy. Tune it first via CV; the rest are usually fine at defaults.
🎯
Bagging + Feature Randomness = Random Forest

Plain bagging (row sampling only) gives you an ensemble of similar trees. Adding random feature selection at every split is what turns bagging into a Random Forest — and what makes it dramatically stronger than plain bagged trees.

Section 05

Aggregation — Majority Vote & Averaging

New email arrives → 5 trees classify → majority wins 🌳 Tree 1 🌳 Tree 2 🌳 Tree 3 🌳 Tree 4 🌳 Tree 5 SPAM ✓ SPAM ✓ NOT ✗ SPAM ✓ SPAM ✓ TALLY · SPAM: 4 · NOT: 1 PREDICT → SPAM confidence 4/5 = 80%
TaskAggregationExample
ClassificationMajority vote4 of 5 trees say SPAM → SPAM
Classification (probabilities)Average predicted probabilities(0.9 + 0.85 + 0.3 + 0.7 + 0.95) / 5 = 0.74 → SPAM
RegressionMean of predictions(₹85L + ₹92L + ₹78L + ₹88L + ₹90L) / 5 = ₹86.6L
Section 06

Out-Of-Bag Score — Free Cross-Validation

10-row dataset · each tree "trains" on some rows, is "tested" on the rest Row → 1 2 3 4 5 6 7 8 9 10 Tree 1 OOB OOB OOB Tree 2 OOB OOB OOB Tree 3 OOB OOB Tree 4 OOB OOB OOB OOB score = accuracy on the amber cells across every tree = unbiased test estimate · no separate hold-out required
🎁
Free Validation, No Split Needed

Every tree naturally misses ~37% of the rows. Test each tree only on its missing rows, aggregate the results — you get a validation score for free, using 100% of your data for training. Enable it with oob_score=True. Read it via model.oob_score_. Ship the number.

Section 07

Why It Works — Variance Reduction Made Visible

One deep tree · high variance refit on 4 samples → 4 different decision curves Forest of 300 trees · low variance votes cancel individual mistakes → one smooth answer
ModelBiasVarianceTest error trend
Shallow single treeHIGHlowPlateau — underfits
Deep single treelowHIGHOverfits · very unstable
Random Forest (300 deep trees)low-mediumLOWStable · production-ready ✅
📉
More Trees Never Hurt

Adding more trees to a Random Forest cannot increase test error — it only helps or plateaus. The variance-reduction ceiling flattens around 300–500 trees; past that you're paying for compute without gaining accuracy.

Section 08

Hyperparameters — Seven Dials That Matter

ParameterTypicalEffect
n_estimators300–500Number of trees. Bigger is safer; diminishing returns after 300.
max_features'sqrt' · 'log2'Features per split. Tune this first — biggest lever.
max_depthNoneDepth cap. Leave unlimited unless memory-bound.
min_samples_leaf1–10Min samples at any leaf. Increase to fight overfitting on noisy data.
bootstrapTrueRow sampling with replacement. Disabling removes the core diversity mechanism.
oob_scoreTrueFree unbiased validation. Set it always.
class_weight'balanced_subsample'Handles imbalanced classes automatically.
🎛️
Tuning Order That Wastes The Least Compute

1. max_features — biggest accuracy impact per unit of tuning effort. 2. min_samples_leaf — protects against overfitting. 3. n_estimators — increase last, until OOB score plateaus. Everything else can safely stay at default.

Section 09

Feature Importance — Which Predictors Actually Matter

Mean Decrease in Impurity · averaged across 300 trees → median_income 0.524 avg_occupancy 0.133 house_age 0.109 latitude 0.089 bedrooms_ratio 0.024 ← barely used
📊
MDI
mean decrease in impurity
Fast. Free from every fit. Biased toward numeric and high-cardinality features. Good first look.
🔀
Permutation Importance
shuffle-and-measure
Model-agnostic. Unbiased. Slower — requires re-scoring after shuffling each feature. Trust this more.
🎯
SHAP Values
per-prediction attribution
Explains individual predictions, not just global rankings. Great when regulators or business teams need "why this row?"
Section 10

Strengths & Weaknesses

🛡️
Overfitting-Resistant
More trees never hurt. Bagging + feature randomness collapse variance without inflating bias.
Embarrassingly Parallel
Trees are independent. n_jobs=-1 uses every core — 8-core machine trains 8× faster.
📏
No Scaling Needed
Trees split on thresholds, not distances. Age 25 alongside income ₹5,00,000 — no problem.
🐢
Slower Predictions
300 tree traversals per sample vs 1 for a single tree. Batch predictions are fine; ultra-low latency needs care.
🔍
Harder To Explain
"Which of 300 trees decided this?" — you can't print a Random Forest the way you can print one tree. Use SHAP for auditability.
💾
Memory-Heavy
300 deep trees = lots of nodes to store. Cap max_depth or reduce n_estimators when RAM-bound.
🥊
Random Forest vs Gradient Boosting

Random Forest — trees built independently in parallel. Forgiving of bad hyperparameters. Great baseline. Ship first, tune later. Gradient Boosting (XGBoost, LightGBM, CatBoost) — trees built sequentially, each correcting the previous one's mistakes. Higher peak accuracy but needs careful tuning and overfits if you're not watching. Use RF first; upgrade when you need the last 2–3%.

Section 11

Implementation — RandomForestClassifier In A Dozen Lines

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score, GridSearchCV
from sklearn.inspection import permutation_importance

# ── Sane production defaults ─────────────────────
rf = RandomForestClassifier(
    n_estimators=300,
    max_features='sqrt',
    min_samples_leaf=2,
    oob_score=True,           # free validation
    n_jobs=-1,                 # use every core
    class_weight='balanced_subsample',   # imbalance handling
    random_state=42,
)
rf.fit(X_train, y_train)

print(f"OOB score:  {rf.oob_score_:.4f}")   # no test set needed
print(f"CV score:   {cross_val_score(rf, X, y, cv=5, n_jobs=-1).mean():.4f}")

# ── Tune max_features first ─────────────────────
grid = GridSearchCV(rf, param_grid={
    'max_features':      ['sqrt', 'log2', 0.3, 0.5],
    'min_samples_leaf': [1, 2, 5, 10],
}, cv=5, scoring='roc_auc', n_jobs=-1).fit(X_train, y_train)

# ── Trustworthy feature importance ──────────────
perm = permutation_importance(rf, X_test, y_test, n_repeats=10, n_jobs=-1)
for i in perm.importances_mean.argsort()[::-1]:
    print(f"{cols[i]:20s}  {perm.importances_mean[i]:.4f}")
Two Non-Negotiable Flags

n_jobs=-1 — trains 8× faster on an 8-core box. There's no reason to leave it at 1. oob_score=True — a free validation metric that costs nothing extra. Skipping either is leaving performance on the table.

Section 12

Common Pitfalls — What Silently Bites Practitioners

📏
Scaling Features
wasted effort
Trees don't care about magnitude — they split on order. Applying StandardScaler to RF adds noise and CPU cost with zero benefit.
🎯
Accuracy On Imbalance
the classic trap
99% "not fraud" data → majority-class-always model scores 99%. Use F1, ROC-AUC or PR-AUC; set class_weight='balanced_subsample'.
💾
Trusting MDI Blindly
high-cardinality bias
MDI over-values numeric and many-value columns. Confirm with permutation_importance before dropping features.
🔒
Single-Core Training
n_jobs=1 default
Leaving n_jobs at its default is wasting hours on multi-core hardware. Always n_jobs=-1.
🌱
Shallow Trees
wrong knob to tune
In RF, trees should be deep. Variance is controlled by averaging, not by shallow trees. Don't inherit habits from single-tree tuning.
🎲
Non-Reproducible Runs
forgotten random_state
RF is stochastic. Without random_state, two runs give different scores and no one can reproduce your result.
Section 13 · Part 1

Golden Rules — 1 to 4

🌲 RANDOM FOREST DISCIPLINE · RULES 1–4
1
Always set n_jobs=-1. Trees train independently — parallelisation is essentially free. Not using every core is throwing away 8× speed on modern hardware.
2
Enable oob_score=True. You get an unbiased validation metric for free using rows each tree never trained on. No holdout split required.
3
Skip feature scaling — it's wasted CPU. Trees split on thresholds, not distances. Reserve StandardScaler for logistic regression, SVM and KNN.
4
Tune in order: max_features, min_samples_leaf, n_estimators. Feature subset size drives accuracy most. Leaf size fights overfitting. Add more trees last until the OOB score stops improving.
Section 13 · Part 2

Golden Rules — 5 to 7

🌲 RANDOM FOREST DISCIPLINE · RULES 5–7
5
On imbalanced data, use class_weight='balanced_subsample'. Report F1 and ROC-AUC — never accuracy. Consider probabilistic thresholds tuned on validation for the operating point.
6
More trees cannot overfit — only help or plateau. If validation improves, add more. When the curve flattens, stop. There's no "too many trees" risk except compute cost.
7
Verify MDI with permutation_importance before acting on it. MDI overrates numeric & high-cardinality columns. Permutation importance is slower but honest. Drop features only when both agree.
The Random Forest Deployment Checklist

✅ n_jobs=-1 · ✅ oob_score=True · ✅ random_state set · ✅ max_features tuned via CV · ✅ class_weight for imbalanced data · ✅ Permutation importance verified · ✅ OOB and test scores within 2%.

FINAL

Random Forest — The Reliable Default Of Tabular ML

🌳×300A jury of independent trees
Bag + √pRow + feature randomness
Vote / MeanAggregate to predict
OOBFree validation baked in
7Hyperparameters that matter
7Golden rules
🎯
The Foundation Is Set

You now understand bagging, random feature subsampling, out-of-bag scoring, and why a forest crushes a single tree's variance. Random Forest is the reliable default for tabular ML — quick to train, forgiving of bad tuning, and often good enough to ship without a second thought.

📚
Where To Go Next

Study Gradient Boosting (XGBoost, LightGBM, CatBoost) to squeeze out the final 2–3%. Then Extra Trees (a variance-happy cousin) and Isolation Forest (anomaly detection with the same architecture). Practise on Kaggle's Titanic, House Prices, and Bank Churn — RF is competitive on all three.

🌲 End of tutorial · Press to review, or click Restart