Ensembles

An ensemble combines the predictions of many models into one, and is usually more accurate and more robust than any of its members. The two dominant strategies attack different parts of the error: bagging trains many high-variance models independently on resampled data and averages them, cutting variance; boosting trains weak, high-bias models one after another, each correcting the errors of the ensemble so far, cutting bias. Built on decision trees, these give random forests and gradient-boosted trees — the strongest general-purpose models for tabular data.



1. Bagging vs Boosting

Bagging (Parallel) vs Boosting (Sequential) Bagging — reduces variance Training data Tree 1bootstrap 1 Tree 2bootstrap 2 Tree 3bootstrap 3 Average / vote Boosting — reduces bias Tree 1shallow errors Tree 2fits residuals errors Tree 3fits residuals Weighted sumF = Σ η·fₘ

Bagging (bootstrap aggregating) draws B bootstrap samples, fits a deep tree to each in parallel, and averages predictions or takes a majority vote. Random forests add random feature subsets at every split to decorrelate the trees. The ~37% of rows left out of each bootstrap give a free out-of-bag error estimate. Boosting fits trees sequentially: each new shallow tree is fit to the gradient of the loss (the residuals, for squared error) of the current ensemble, and is added with a small learning rate η. AdaBoost reweights misclassified samples; gradient boosting (XGBoost, LightGBM, CatBoost) generalizes to any differentiable loss.

2. Deep Dives

Bagging (Random Forest)

Bootstrap samples, parallel deep trees, feature subsampling and out-of-bag error — variance reduction with few knobs.

Gradient Boosting (XGBoost, LightGBM)

Sequential shallow trees fit to loss gradients; learning rate, early stopping and the libraries that dominate tabular ML.

Random Forest Classifier

A worked random forest classification model with scikit-learn.

3. Why Ensembles Work

Why Averaging Helps: Variance of an Average of Correlated Models number of models B variance Var(avg) = ρσ² + (1 − ρ)σ²/B Green: ρ = 0 → variance → 0 Blue: ρ = 0.3 → floor at 0.3σ² Yellow: ρ = 0.7 → floor at 0.7σ² Decorrelating trees lowers the floor.

If B models each have variance σ2 and pairwise correlation ρ, their average has variance ρσ2 + (1 − ρ)σ2/B. Adding models drives the second term to zero but leaves the first: averaging only helps as much as the members disagree. That is why random forests subsample features (lower ρ) and why diverse model types make better ensembles than copies of one model. Boosting works differently: it is a stagewise additive model, Fm(x) = Fm−1(x) + η fm(x), performing gradient descent in function space, so it can keep reducing bias — and will eventually overfit unless stopped early.

4. Voting and Stacking

Beyond tree ensembles, heterogeneous models can be combined directly. Voting averages the predicted probabilities (soft voting) or labels (hard voting) of different models. Stacking trains a meta-model, often a regularized linear model, on the out-of-fold predictions of base models, learning how much to trust each. Stacking can add a little accuracy at the cost of complexity and latency; it is common in competitions and less common in production, where a single well-tuned gradient-boosted model often suffices.

Bagging / Random ForestGradient Boosting
ReducesVarianceBias (and variance with shrinkage)
Base treesDeep, independentShallow, sequential
TrainingParallelSequential per tree (parallel within)
Tuning effortLowModerate: learning rate, depth, rounds
Overfitting with more treesNo (plateaus)Yes — use early stopping

5. Ensembles in Code


from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import (RandomForestClassifier, HistGradientBoostingClassifier,
                              StackingClassifier)

X, y = load_breast_cancer(return_X_y=True)
cv = StratifiedKFold(5, shuffle=True, random_state=0)

tree = DecisionTreeClassifier(random_state=0)
forest = RandomForestClassifier(n_estimators=500, oob_score=True, random_state=0, n_jobs=-1)
gbm = HistGradientBoostingClassifier(learning_rate=0.05, max_iter=500,
                                     early_stopping=True, random_state=0)
stack = StackingClassifier(
    estimators=[("rf", forest), ("gbm", gbm)],
    final_estimator=make_pipeline(StandardScaler(), LogisticRegression()),
    cv=5,
)
for name, m in [("single tree", tree), ("random forest", forest), ("grad boosting", gbm), ("stacking", stack)]:
    s = cross_val_score(m, X, y, cv=cv, scoring="roc_auc")
    print(f"{name:<14} ROC-AUC {s.mean():.3f} +/- {s.std():.3f}")

print("OOB accuracy:", round(forest.fit(X, y).oob_score_, 3))

6. Worked Example: Why Averaging Helps

Plug numbers into the variance formula above. Suppose each tree has prediction variance σ2 = 1. With B = 100 fully independent trees (ρ = 0) the average has variance 1/100 = 0.01. Real bootstrap trees are correlated; with ρ = 0.5 the variance is 0.5 + 0.5/100 = 0.505, and adding a thousand more trees only reduces it to about 0.5. With ρ = 0.2 (as random feature subsets aim for) it falls to about 0.208. The lesson: past a few hundred trees, more trees barely help; decorrelating them is what moves the floor. That is why random forests restrict each split to a random subset of features (a common default is √p for classification).

For majority voting on classification, if five independent classifiers are each correct 70% of the time, the majority is correct whenever at least three are, which happens with probability about 0.84. That gain shrinks quickly as errors become correlated, and voting among models worse than chance makes things worse.

7. Stacking Without Leakage

Out-of-Fold Stacking Fold 1..K split training data Base model A predict held-out fold Base model B predict held-out fold Base model C predict held-out fold OOF prediction matrix n rows x 3 columns Meta-learner logistic / ridge

Stacking trains a meta-model on the predictions of base models. The meta-model must learn from predictions on data the base models did not see, otherwise it learns to trust whichever model overfit the most. The standard recipe produces out-of-fold predictions: split the training data into K folds, train each base model K times, each time predicting the held-out fold, and stack those predictions into a matrix. The meta-learner (usually a simple regularized linear model) trains on that matrix. At inference, base models refit on all data (or the K fold models averaged) feed the meta-learner. scikit-learn's StackingClassifier and StackingRegressor implement this with the cv argument.

Stacking pays off when base models are diverse (a tree ensemble, a linear model on different features, a neural network); stacking five variants of the same gradient-boosting model rarely adds much over tuning one.

8. Choosing and Tuning an Ensemble

Random forestGradient boostingStacking / blending
Main knobsn_estimators, max_features, min_samples_leaflearning_rate, n_estimators (early stopping), max_depth / num_leaves, subsamplingChoice of base models, meta-learner regularization
Tuning effortLowModerateHigh
Overfitting riskLowHigher without early stoppingLeakage if not out-of-fold
TrainingParallelSequential trees (parallel within a tree)Multiplies cost by number of models and folds
Best forStrong, quick baselineTop accuracy on tabular dataSqueezing the last gains, competitions

In production, every extra model is extra latency, memory and maintenance. A single well-tuned gradient-boosting model often captures most of the benefit. Ensembles also complicate explanation, though tree-specific SHAP values (Lundberg et al., 2020) make tree ensembles reasonably interpretable.

Further reading: Breiman, L. (1996), "Bagging predictors"; Breiman, L. (2001), "Random forests"; Freund, Y. & Schapire, R. (1997), AdaBoost; Friedman, J. (2001), "Greedy function approximation: a gradient boosting machine"; Wolpert, D. (1992), "Stacked generalization"; Chen, T. & Guestrin, C. (2016), "XGBoost".

Supervised LearningSectionthe parent paradigm. Decision Treesclassificationthe base learner for both bagging and boosting. ClassificationSectionwhere ensembles usually lead on tabular data. RegressionSectionensembles work equally well for continuous targets. Machine LearningSectionsection home.