Gradient Boosting as Functional Gradient Descent
Gradient boosting is ordinary gradient descent, except the thing being updated at each step is not a vector of weights but an entire function, added to the model one small correction at a time.
Prerequisites: Why Ensembles Work: The Ambiguity Decomposition, Decision Trees and CART
A golfer does not try to hole every shot from the tee. They hit the ball as well as they can, look at where it landed relative to the hole, and hit again — this time aiming to correct exactly the distance and direction still remaining. Each shot is a small, targeted fix for whatever error the previous shots left behind, and a handful of imperfect shots, each correcting the last, gets the ball in the hole more reliably than trying to nail an impossible single stroke. Gradient boosting builds a model the same way: instead of fitting one model that tries to get everything right at once, it fits a short sequence of weak models, each one aimed squarely at whatever the current combination still gets wrong.
From weight updates to function updates
Ordinary gradient descent updates a vector of numbers — the weights of a model — by stepping a little in the direction that most reduces a loss: . That direction is a vector, because is a vector.
Gradient boosting asks the same question about the model's predictions themselves, treated as one giant object to be optimized directly, without ever parameterizing them by a fixed set of weights. At round , the current model is a function — everything built so far, added together. The next round asks: which small function, added on top of , would most reduce the loss? That small function is found by computing the negative gradient of the loss with respect to the current predictions, one number per training point, and then training a weak learner — almost always a shallow decision tree — to approximate that vector of numbers as a function of . The tree is then added in:
In words: the new model equals the old model, plus a small step (controlled by a learning rate ) in the direction of a freshly fit tree , where that tree was trained specifically to point toward "what would most reduce the loss from here." This is gradient descent — same update rule, same "small step in the downhill direction" logic — except each step is an entire tree rather than a nudge to a fixed set of numbers, which is why it is called functional gradient descent.
Squared error makes the gradient a familiar object
For squared-error loss , the negative gradient with respect to works out to
In words: for the most common loss function, the "negative gradient" that boosting fits at each round is nothing more exotic than the residual — actual value minus current prediction. This is why the plainest description of gradient boosting is "repeatedly fit a small tree to whatever error is still left over," and it is also literally, exactly, gradient descent in disguise.
Worked example 1: two boosting rounds by hand
Four points: with targets . Boosting starts from the simplest possible model, the mean: for every .
Round 1. Residuals, : . A shallow tree finds the split vs. that best separates these: the left group averages , the right group averages . With learning rate :
Sum of squared errors falls from 's to 's .
Round 2. New residuals, : . This time the best split is vs. : the left group () averages , the right group () is just .
Sum of squared errors: .
Each round fit a small tree to the residual left over from the previous round, exactly the negative-gradient object the formula above says it should, and each round's addition drove the total squared error down.
Worked example 2: the gradient looks different for a different loss
For classification with log loss, the gradient is not the raw residual but , where is the current model's predicted probability (after passing through a sigmoid). Three points with true labels and current predicted probabilities :
A tree is fit to these three numbers exactly as before — the mechanism is identical, only the formula defining "what counts as the gradient" changed, because it changed with the loss function. This is the general recipe: pick any differentiable loss, compute its negative gradient with respect to the current predictions, and boosting fits trees to chase that gradient down to zero, round after round.
The explorer above shows ordinary gradient descent taking steps down a loss curve — small steps that converge, or overshoot if the step size is too large. Gradient boosting is the same picture with one difference: instead of a step being "move this one number a little," a step is "add this whole tree." Drag the step size in the explorer and notice the same overshoot risk that a poorly tuned learning rate creates in boosting — too large a learning rate and each added tree overcorrects the previous round's error rather than gently reducing it.
A gradient-boosted model is a sum of many weak trees, each one trained to predict the negative gradient of the loss — the residual, for squared error — left behind by everything added before it. It is gradient descent where each step is a function, not a number.
What this means in practice
This view explains two of gradient boosting's most important knobs directly. The learning rate is exactly the step size in a gradient descent update — too large and successive trees overcorrect and oscillate, exactly as an overshooting step does in ordinary gradient descent; too small and training needs far more rounds to converge. The number of boosting rounds is exactly the number of gradient steps taken, and taking too many is the direct boosting analogue of training a model for too many epochs — it starts fitting the noise in the residuals rather than genuine signal, which is why boosted models are almost always paired with early stopping on a held-out validation set. Because each round only ever sees the residual, not the raw target, a single mislabeled or outlier data point can dominate several rounds' worth of pseudo-residuals — robust loss functions (Huber loss instead of squared error) exist specifically to blunt that.
Practice
- Continuing worked example 1 for a third round, the residuals after are . What would you expect the sum of squared error to do — keep falling, flatten, or start rising — if boosting continued for many more rounds without a validation check?
- Why does gradient boosting with squared-error loss fit each tree to the literal residual , while gradient boosting with log loss fits each tree to instead?
- What single hyperparameter plays the same role in boosting that the step size plays in ordinary gradient descent, and what goes wrong if it is set too high?
It is tempting to describe boosting as "each tree corrects the previous tree's mistakes" as if the trees were reacting to each other directly — they are not. Every tree is fit independently to a gradient signal computed from the current combined model, not to the previous tree's own errors; there is no direct relationship between tree and tree except that 's addition changed the residuals then sees. The second common confusion is mixing up boosting with bagging: bagging (random forests) trains many trees independently and in parallel on resampled data specifically to reduce variance via the ambiguity decomposition; boosting trains trees sequentially and dependently, each one targeting the specific error the ensemble so far has left behind, and it primarily reduces bias, not variance.
Related concepts
Practice in interviews
Further reading
- Friedman, Greedy Function Approximation: A Gradient Boosting Machine (2001)
- Mason, Baxter, Bartlett & Frean, Boosting Algorithms as Gradient Descent (1999)