VivaPrep
← Jaber Notes

Jaber Notes · 8 of 16

Ensemble Methods

Bagging, random forests, AdaBoost, GBM, XGBoost, LightGBM, stacking.

Why combining models wins: the bias-variance view of bagging, random-forest feature randomization, AdaBoost's weight-update derivation, GBM as functional gradient descent, and the XGBoost/LightGBM tricks that dominate tabular ML.

Visual reference

Bias–variance tradeoff

sweet spotunderfitoverfitmodel complexity →errortrainval
As model complexity grows, training error keeps falling — but validation error bottoms out then rises again. The gap between the two curves after the sweet spot is overfitting.
Ensembles combine multiple weak learners into a strong one. This is the dominant approach in tabular ML competitions.

Table of contents

  1. Why ensembles work (theory)
  2. Bagging
  3. Random forest
  4. AdaBoost (derivation)
  5. Gradient boosting machines (GBM)
  6. XGBoost, LightGBM, CatBoost (modern GBDT)
  7. Stacking and blending
  8. Practical comparison and when to use what

1. Why ensembles work (theory)

1.1 Bias-variance view

Averaging reduces variance without increasing bias:

Let f^1,,f^M\hat{f}_1, \ldots, \hat{f}_M be models trained on different samples, each with expected prediction fˉ\bar{f} and variance σ2\sigma^2. If the models are uncorrelated, the variance of their average:

Var ⁣(1Mmf^m)=σ2M.\text{Var}\!\left(\frac{1}{M}\sum_m \hat{f}_m\right) = \frac{\sigma^2}{M}.

Variance decreases by factor MM. Bias stays the same (E[fˉ]\mathbb{E}[\bar{f}] = E[f^m]\mathbb{E}[\hat{f}_m] for unbiased models).

In reality, models are correlated (same training distribution). If pairwise correlation is ρ\rho:

Var ⁣(1Mmf^m)=ρσ2+1ρMσ2.\text{Var}\!\left(\frac{1}{M}\sum_m \hat{f}_m\right) = \rho\sigma^2 + \frac{1-\rho}{M}\sigma^2.

Floor is ρσ2\rho\sigma^2. To benefit from ensembling: maximize diversity (low ρ\rho).

1.2 Wisdom of crowds

If each of MM classifiers is right with probability p>0.5p > 0.5 and errors are independent, majority vote is right with probability:

P(majority correct)=k=M/2M(Mk)pk(1p)Mk1 as M.P(\text{majority correct}) = \sum_{k=\lceil M/2 \rceil}^M \binom{M}{k} p^k(1-p)^{M-k} \to 1 \text{ as } M \to \infty.

2. Bagging (Bootstrap Aggregating)

2.1 Algorithm (Breiman, 1996)

  1. For m=1,,Mm = 1, \ldots, M:

a. Draw a bootstrap sample Dm\mathcal{D}_m of size nn by sampling with replacement from D\mathcal{D}. b. Train a model f^m\hat{f}_m on Dm\mathcal{D}_m.

  1. Aggregate:
  • Regression: f^(x)=1Mmf^m(x)\hat{f}(\mathbf{x}) = \frac{1}{M}\sum_m \hat{f}_m(\mathbf{x}).
  • Classification: majority vote or average probabilities.

2.2 Out-of-bag (OOB) error

Each bootstrap sample includes ~63.2% of training points (limn1(11/n)n=1e10.632\lim_{n\to\infty}1-(1-1/n)^n = 1-e^{-1} \approx 0.632). The remaining ~36.8% are out-of-bag (OOB).

Evaluate model f^m\hat{f}_m on its OOB samples → free estimate of generalization without a separate validation set.

2.3 Pasting

Bagging without replacement (draw subsamples of size < n). Less variance reduction but more diversity per model.


3. Random Forest

3.1 Additional randomization over Bagging

Random forests (Breiman, 2001) = bagging of decision trees + random feature subsets at each split:

  • At each node, choose the best split among a random subset of mm features (not all pp).
  • Default: m=pm = \sqrt{p} for classification, m=p/3m = p/3 for regression.

This reduces correlation among trees (key insight): trees trained on different features diverge more.

3.2 Why random features reduce correlation

Two trees grown on the same bootstrap without feature randomization will tend to split on the same strong features at the top → highly correlated → limited variance reduction.

With feature randomization: each tree sees different feature subsets → different splits → lower correlation → better ensemble.

3.3 Feature importance

Split-based importance (MDI — Mean Decrease in Impurity): sum of impurity reduction from splits on feature jj across all trees, weighted by sample count.

Permutation importance: permute values of feature jj in OOB samples; measure drop in accuracy. More reliable (MDI is biased toward high-cardinality features).

from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance

rf = RandomForestClassifier(n_estimators=200, max_features='sqrt', oob_score=True)
rf.fit(X_train, y_train)

print("OOB score:", rf.oob_score_)
print("MDI importances:", rf.feature_importances_)

perm = permutation_importance(rf, X_val, y_val, n_repeats=10)
print("Permutation importances:", perm.importances_mean)

3.4 Hyperparameters

ParamEffectTypical range
n_estimatorsMore = better but diminishing returns100–1000
max_featuresReduce → less correlation, more bias'sqrt', 'log2', float
max_depthLimit depth of each treeNone (fully grown) or 5–20
min_samples_leafSmooth predictions1–20
bootstrapOOB estimationTrue

4. AdaBoost (derivation)

4.1 Intuition

Boosting: train models sequentially, each one focusing on the mistakes of the previous.

AdaBoost (Freund & Schapire, 1997): maintain a weight distribution over samples; harder examples get higher weight.

4.2 Algorithm (binary, yi{1,+1}y_i \in \{-1,+1\})

Initialize: wi(1)=1/nw_i^{(1)} = 1/n for all ii.

For m=1,,Mm = 1, \ldots, M:

  1. Train weak learner hmh_m on weighted distribution {wi(m)}\{w_i^{(m)}\}.
  2. Compute weighted error:
εm=i:hm(xi)yiwi(m)iwi(m).\varepsilon_m = \frac{\sum_{i: h_m(\mathbf{x}_i)\neq y_i} w_i^{(m)}}{\sum_i w_i^{(m)}}.
  1. Compute model weight (log odds of being correct):
αm=12log1εmεm.\alpha_m = \frac{1}{2}\log\frac{1-\varepsilon_m}{\varepsilon_m}.

Note: αm>0\alpha_m > 0 iff εm<0.5\varepsilon_m < 0.5 (better than random). Larger α\alpha for more accurate learners.

  1. Update sample weights (increase weight of misclassified):
wi(m+1)=wi(m)exp(αmyihm(xi)).w_i^{(m+1)} = w_i^{(m)} \cdot \exp(-\alpha_m y_i h_m(\mathbf{x}_i)).

If correctly classified: yihm(xi)=+1y_i h_m(\mathbf{x}_i) = +1 → weight multiplied by eαm<1e^{-\alpha_m} < 1. If misclassified: yihm(xi)=1y_i h_m(\mathbf{x}_i) = -1 → weight multiplied by e+αm>1e^{+\alpha_m} > 1.

  1. Normalize: wi(m+1)wi(m+1)/jwj(m+1)w_i^{(m+1)} \leftarrow w_i^{(m+1)} / \sum_j w_j^{(m+1)}.

Final prediction:

H(x)=sign ⁣(mαmhm(x)).H(\mathbf{x}) = \text{sign}\!\left(\sum_m \alpha_m h_m(\mathbf{x})\right).

4.3 AdaBoost minimizes exponential loss

It can be shown that AdaBoost is forward stagewise additive modeling with the exponential loss (y,f)=eyf\ell(y, f) = e^{-yf}:

J(f)=ieyif(xi).J(f) = \sum_i e^{-y_i f(\mathbf{x}_i)}.

Minimizing this greedily → exactly the AdaBoost update. The exponential loss is sensitive to outliers (upweights them exponentially) — this is a weakness.

4.4 Training error bound

1ni1[H(xi)yi]exp ⁣(2mγm2),\frac{1}{n}\sum_i \mathbf{1}[H(\mathbf{x}_i)\neq y_i] \leq \exp\!\left(-2\sum_m \gamma_m^2\right),

where γm=0.5εm\gamma_m = 0.5 - \varepsilon_m is the "edge" (how much better than random). If each weak learner is slightly better than random (γmγ>0\gamma_m \geq \gamma > 0), error decays exponentially to zero.


5. Gradient Boosting Machines (GBM)

5.1 Key insight (Friedman, 2001)

Generalize boosting to arbitrary differentiable loss functions by framing it as gradient descent in function space.

Setup: train an ensemble additively:

FM(x)=F0(x)+m=1Mνmhm(x),F_M(\mathbf{x}) = F_0(\mathbf{x}) + \sum_{m=1}^M \nu_m h_m(\mathbf{x}),

where hmh_m are weak learners (shallow trees) and νm\nu_m are step sizes (learning rate).

5.2 Gradient in function space

At step mm, we want to minimize iL(yi,Fm1(xi)+hm(xi))\sum_i L(y_i, F_{m-1}(\mathbf{x}_i) + h_m(\mathbf{x}_i)).

Functional gradient descent: the direction that decreases loss fastest is the negative functional gradient:

ri(m)=L(yi,F(xi))F(xi)F=Fm1.r_i^{(m)} = -\left.\frac{\partial L(y_i, F(\mathbf{x}_i))}{\partial F(\mathbf{x}_i)}\right|_{F=F_{m-1}}.

These are called pseudo-residuals. Fit the next tree hmh_m to predict these pseudo-residuals (regression tree, even for classification).

5.3 GBM algorithm

Initialize: F0(x)=argminciL(yi,c)F_0(\mathbf{x}) = \arg\min_c \sum_i L(y_i, c).

For m=1,,Mm = 1, \ldots, M:

  1. Compute pseudo-residuals: ri(m)=[L(yi,F)/F]F=Fm1(xi)r_i^{(m)} = -[\partial L(y_i, F)/\partial F]_{F=F_{m-1}(\mathbf{x}_i)}.
  2. Fit regression tree hmh_m to {(xi,ri(m))}\{(\mathbf{x}_i, r_i^{(m)})\}.
  3. Find optimal leaf output values (line search or closed form per leaf).
  4. Update: Fm(x)=Fm1(x)+νhm(x)F_m(\mathbf{x}) = F_{m-1}(\mathbf{x}) + \nu \cdot h_m(\mathbf{x}), with shrinkage ν(0,1]\nu \in (0,1].

5.4 Loss functions and their pseudo-residuals

LossL(y,F)L(y,F)Pseudo-residual rir_iUse case
Squared error(yF)2/2(y-F)^2/2yiF(xi)y_i - F(\mathbf{x}_i)Regression
Absolute erroryF|y-F|sign(yiF(xi))\text{sign}(y_i - F(\mathbf{x}_i))Robust regression
HuberHybrid MSE/MAESmooth thresholdRegression with outliers
Log-loss (deviance)[ylogp+(1y)log(1p)]-[y\log p + (1-y)\log(1-p)]yipiy_i - p_iBinary classification
Multinomial devianceMulticlass

5.5 Regularization in GBM

  • Shrinkage (learning rate ν\nu): smaller → more trees needed but better generalization. Typical: 0.01–0.1.
  • Subsampling (stochastic GBM): build each tree on a random subsample of data (e.g., 50%–80%). Reduces correlation between trees, speeds up training.
  • Tree constraints: max_depth (3–8 typical), min_samples_leaf.
  • L1/L2 regularization on leaf weights (XGBoost feature).

6. XGBoost, LightGBM, CatBoost (modern GBDT)

6.1 XGBoost (Chen & Guestrin, 2016)

Second-order approximation of the loss: use both gradient gig_i (first order) and Hessian hih_i (second order) for more accurate leaf updates.

For tree structure qq with leaf outputs w\mathbf{w}, the regularized objective at step mm:

L~i[giwq(xi)+12hiwq(xi)2]+γT+12λw2,\tilde{\mathcal{L}} \approx \sum_i [g_i w_{q(\mathbf{x}_i)} + \frac{1}{2}h_i w_{q(\mathbf{x}_i)}^2] + \gamma T + \frac{1}{2}\lambda\|\mathbf{w}\|^2,

where gi=L/y^ig_i = \partial L/\partial \hat y_i, hi=2L/y^i2h_i = \partial^2 L/\partial \hat y_i^2, TT = number of leaves, γ\gamma = leaf count penalty, λ\lambda = L2 on leaf weights.

Optimal leaf output for leaf jj: wj=GjHj+λw_j^\star = -\frac{G_j}{H_j+\lambda}, where Gj=ileaf jgiG_j = \sum_{i\in\text{leaf }j}g_i, Hj=ileaf jhiH_j = \sum_{i\in\text{leaf }j}h_i.

Split gain:

Gain=12[GL2HL+λ+GR2HR+λG2H+λ]γ.\text{Gain} = \frac{1}{2}\left[\frac{G_L^2}{H_L+\lambda} + \frac{G_R^2}{H_R+\lambda} - \frac{G^2}{H+\lambda}\right] - \gamma.

Key features:

  • Weighted quantile sketch for approximate split finding (scalable).
  • Column block data structure (efficient access).
  • Missing value handling: learn default direction for missing values.
  • Regularization: alpha (L1), lambda (L2), gamma (min gain).

6.2 LightGBM

Innovations for speed on large datasets:

  • Gradient-based One-Side Sampling (GOSS): keep instances with large gradients (they contribute more), randomly sample instances with small gradients (with upweighting).
  • Exclusive Feature Bundling (EFB): bundle mutually exclusive sparse features (e.g., OHE columns) into one dense feature.
  • Leaf-wise growth: grow the leaf that reduces loss the most (vs. level-wise in XGBoost). Faster convergence but can overfit — limit via min_child_samples, num_leaves.
  • Result: 10–20× faster than XGBoost on large datasets.

6.3 CatBoost

Innovations for categorical features:

  • Target statistics for categoricals with an ordered (time-based) scheme to prevent leakage within the training set.
  • Oblivious trees: all nodes at the same depth use the same split. Faster prediction, regularization effect.
  • Symmetric quantile binning.

6.4 Hyperparameter guide

ParameterXGBoostLightGBMEffect
Depthmax_depthnum_leavesComplexity
LRlearning_ratelearning_rateStep size
Regularizationalpha, lambdareg_alpha, reg_lambdaLeaf penalty
Subsamplingsubsamplebagging_fractionData sampling
Feature samplingcolsample_bytreefeature_fractionFeature sampling
Min leafmin_child_weightmin_child_samplesLeaf size
import xgboost as xgb
model = xgb.XGBClassifier(
    n_estimators=500, learning_rate=0.05, max_depth=6,
    subsample=0.8, colsample_bytree=0.8, gamma=0,
    reg_alpha=0.1, reg_lambda=1.0,
    eval_metric='logloss', early_stopping_rounds=20,
    random_state=42
)
model.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=100)

import lightgbm as lgb
model = lgb.LGBMClassifier(
    n_estimators=1000, learning_rate=0.02, num_leaves=63,
    feature_fraction=0.8, bagging_fraction=0.8, bagging_freq=5,
    reg_alpha=0.1, reg_lambda=0.1,
    min_child_samples=20, random_state=42
)
model.fit(X_train, y_train,
          eval_set=[(X_val, y_val)],
          callbacks=[lgb.early_stopping(50, verbose=False)])

7. Stacking and blending

7.1 Stacking (stacked generalization)

Train a meta-learner on the predictions of base models:

  1. Split training data into kk folds.
  2. For each fold, train all base models on other folds, predict on this fold.
  3. Collect out-of-fold predictions as meta-features.
  4. Train a meta-learner (often logistic regression or LightGBM) on these meta-features.
  5. At test time: predict with all base models, feed to meta-learner.

Prevents leakage: base model's predictions on training data are always made on data it hasn't seen.

from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier

estimators = [
    ('rf', RandomForestClassifier(n_estimators=100, random_state=0)),
    ('gbm', GradientBoostingClassifier(n_estimators=100, random_state=0)),
]
meta_model = LogisticRegression()
stacker = StackingClassifier(estimators=estimators, final_estimator=meta_model, cv=5)

7.2 Blending

Simpler variant: use a holdout (not CV) to generate meta-features. Less data-efficient but faster.

7.3 Why stacking works

Different model classes have different biases. A meta-learner can learn which base model is better in which region of feature space, combining their strengths.


8. Practical comparison and when to use what

MethodBiasVarianceSpeedWhen
Single treeHighHighFastBaseline / interpretability
BaggingSame as baseLowerModerateBase = high-variance (trees)
Random ForestSlightly higherLowModerateGood default for tabular data
AdaBoostLowerSlightly higherModerateInterpretable boosting
GBMLowLowSlowerStrong performance
XGBoost/LightGBMLowLowFast (LGB faster)Default for tabular ML
StackingLowestLowMost expensiveCompetitions, maximum accuracy

Rule of thumb for tabular data:

  1. Start with LightGBM or XGBoost.
  2. Tune hyperparameters (especially learning_rate, num_leaves/max_depth, subsampling).
  3. Use early stopping with validation set.
  4. Add stacking as final step if marginal gains matter.

*File: notes/08_ensemble_methods.md — next: notes/09_unsupervised_learning.md*