Skip to content
AI360XpertBeta

AdaBoost

Fit a one-cut stump, make the rows it missed count for more, and fit again. The final call is a weighted vote where the accurate stumps speak louder.

Rows the first stump misses grow from 0.10 to 0.17 while the rest shrink to 0.07, so the next stump moves its cut to cover them
Rows the first stump misses grow from 0.10 to 0.17 while the rest shrink to 0.07, so the next stump moves its cut to cover them

Why Does This Exist?

You run a belt that must pull hollow walnuts before packing. Each nut gets two cheap numbers: weight in grams and ring frequency when a paddle taps it. Hollow nuts skew lighter and higher, but shell thickness varies and the belt shakes, so one cut on either number lands near 70 percent correct. Neither cut ships, and you cannot buy a better sensor.

You need a way to turn two blunt rules into one sharp call. That is what boosting does: fit simple rules in sequence, each cleaning up after the last. AdaBoost was the first method that made the sequence work. It hands the next learner the same rows with new weights, heavier on the rows the run keeps missing.

This page covers that reweighting plus the vote that follows. The parent page on boosting sets the family against bagging. The sequel on gradient boosting keeps the loop and swaps the loss.

The one idea you need first is the weak learner. Here it is a stump: one threshold on one feature, the smallest decision tree you can draw. Its weighted error is the total weight on the rows it gets wrong, not a plain miss count. Everything below is arithmetic on those two objects.

Think of It Like This

A flashcard deck that puts misses back on top

You work through a deck of flashcards for a quiz. Get a card right and it slides to the bottom. Get one wrong and it goes back on top, so you meet it again within a few cards. You never choose what to study. The order does it for you, and the cards you keep missing show up most.

Each card is a training row and its place in the deck is its weight. A correct answer shrinks that weight and a miss grows it, which is why the next stump spends its one cut on your weak spots.

Where it stops: a deck has no vote across rounds and no measure of how sure each pass was. And one misprinted card with a wrong answer returns to the top forever, until you study nothing else. That is not a quirk of the analogy. It is AdaBoost on mislabelled rows, and the reason the field moved on.

How It Actually Works

Call row ii the pair (xi,yi)(x_{i}, y_{i}). Here xix_{i} means the two sensor numbers for nut ii and yiy_{i} means its label, written as +1+1 for hollow and −1-1 for sound. Give every row a weight wiw_{i}, with all wiw_{i} summing to one, starting at wi=1/nw_{i} = 1/n for nn rows. Call the one cut rule hh, with h(xi)=+1h(x_{i}) = +1 or −1-1 for each nut. You fit hh to minimize weighted error, not plain accuracy.

The vote each stump earns

Score the stump by its weighted error ε\varepsilon, which means the total weight on the rows it gets wrong. Then give it its vote:

α=12(ln⁡1−εε)\alpha = \frac{1}{2}\left(\ln\frac{1 - \varepsilon}{\varepsilon}\right)

In plain words, α\alpha says how loudly this stump speaks in the final vote. At ε=0.5\varepsilon = 0.5 the fraction inside is one, its log is zero, so a coin flip stump gets α=0\alpha = 0 and is ignored. As ε\varepsilon falls toward zero, α\alpha climbs with no ceiling. Worse than a coin flip gives a negative α\alpha, which flips that stump backward. You need each stump to beat a coin flip on its weighted data, or the round contributes nothing.

Why the mistakes always end up holding half

Push the weights toward the misses. Multiply every misclassified row by eαe^{\alpha} and every correct row by e−αe^{-\alpha}, then divide by ZZ, where ZZ means the normalizer that brings the total back to one:

wi←wi×exp⁡(−αyih(xi))Z then rescale so ∑wi=1w_{i} \leftarrow \frac{w_{i} \times \exp\left(-\alpha y_{i} h\left(x_{i}\right)\right)}{Z} \text{ then rescale so } \sum w_{i} = 1

Check the signs. When the stump is right, yih(xi)=+1y_{i} h(x_{i}) = +1 and the factor is e−αe^{-\alpha}, a shrink. When it is wrong, the product is −1-1 and the factor is e+αe^{+\alpha}, a grow. The math always lands the same way: after rescaling, the rows this stump missed hold exactly half the total weight. So the next stump faces a problem where the last round failures count as much as everything else combined. That is the whole trick. No sampling, no copies, just a distribution that tilts.

Worked example: ten nuts, three misses

Start with ten nuts, so each wi=0.10w_{i} = 0.10. Your first stump misses three of ten. Its weighted error is ε=0.30\varepsilon = 0.30, and its vote is α=0.5×ln⁡(0.70/0.30)≈0.424\alpha = 0.5 \times \ln(0.70/0.30) \approx 0.424.

Grow the three misses: 0.10×e0.424≈0.10×1.528≈0.15280.10 \times e^{0.424} \approx 0.10 \times 1.528 \approx 0.1528. Shrink the seven hits: 0.10×e−0.424≈0.10×0.655≈0.06550.10 \times e^{-0.424} \approx 0.10 \times 0.655 \approx 0.0655. The total is 3×0.1528+7×0.0655≈0.91653 \times 0.1528 + 7 \times 0.0655 \approx 0.9165. Divide through by that total and each miss lands at 0.1670.167 while each hit lands at 0.0710.071. Add the three misses: 3×0.167=0.503 \times 0.167 = 0.50. Half, as promised. Those are the numbers drawn in the diagram above, and the snippet below repeats them.

The loss view that led to gradient boosting

Write the running vote as F(x)F(x), which means the α\alpha weighted sum of stumps so far. Call yF(x)yF(x) the margin: positive when the ensemble is right, large when it is confidently right. Years later the field showed AdaBoost had been doing gradient descent on one loss all along:

L(y,F)=e−yF(x) with margin yF(x)L\left(y, F\right) = e^{-y F\left(x\right)} \text{ with margin } yF\left(x\right)

A borderline nut sits near zero margin and costs little. A confidently wrong nut sits at a large negative margin, and e−yFe^{-yF} blows up there: margin −1-1 costs about 2.722.72, margin −3-3 costs about 20.0920.09, margin −5-5 costs about 148.41148.41. That shape is the trade. It chases hard rows fast, and it cannot let go of a wrongly labelled row. Keep the loop but swap this loss for a gentler one and you have gradient boosting. That swap is what ships now. Read this page for the reweighting idea, then reach for the sequel when you build.

Code

The whole update on the ten nut round above. The point is the check: the vote, the two new weights, and the half total you can verify by hand.

import numpy as np

def one_round(w: np.ndarray, wrong: np.ndarray) -> tuple[float, np.ndarray]:    err = float(w[wrong].sum())  # weighted error, not a plain miss count    alpha = 0.5 * np.log((1.0 - err) / err)  # this stump vote, rising as err falls    w = w * np.exp(np.where(wrong, alpha, -alpha))  # misses up, hits down    return alpha, w / w.sum()  # rescale so weights stay a distribution

missed = np.zeros(10, dtype=bool)missed[[2, 5, 9]] = True  # first stump calls three of ten wrongalpha, w = one_round(np.full(10, 0.1), missed)print(f"vote {alpha:.3f} | miss {w[missed][0]:.3f} each | hit {w[~missed][0]:.3f} each | misses hold {w[missed].sum():.3f}")# -> vote 0.424 | miss 0.167 each | hit 0.071 each | misses hold 0.500

Refit a stump on those weights, collect the next vote, repeat a few hundred times with shallow stumps, and classify a new nut by the sign of the vote weighted sum. When labels are clean that loop is hard to beat for its size. When they are not, read the first card below before you trust it.

Watch Out For

Training keeps improving while new nuts get worse

You add rounds and the training error keeps falling, but held out error bottoms out early and then climbs. Not a plateau. A climb.

That is the misprinted flashcard at work. A few wrongly labelled rows each pick up a factor of eαe^{\alpha} per round, and once they hold most of the weight every later stump fits them and little else. Inspect your heaviest rows first. AdaBoost sorts suspects to the top for you. If the top weights look mislabelled, fix the labels before you tune anything. If label noise stays, switch to a loss that does not compound, such as the log loss behind gradient boosting.

Deep trees as the weak learner

Your first tree already scores near zero weighted error, its vote comes out huge, and the ensemble memorizes the room in a handful of rounds.

Deep trees break the deal. The method assumes a stump that is only just better than a coin flip, so each round adds a small correction. A deep tree eats the whole problem at once and the later reweighting has nothing left to fix. Keep the base learner to a stump or depth two at most, and choose the round count on held out data with early stopping.

The Quick Version

  • AdaBoost fits one cut stumps in sequence, with each stump trained on weights that emphasize the rows missed so far.
  • Weighted error is the total weight on the rows a stump gets wrong, and its vote is alpha at half the log of correct weight over wrong weight.
  • The update multiplies missed rows by exp of alpha and correct rows by exp of minus alpha, then rescales, which always leaves the misses holding half the total.
  • The final call is the sign of the alpha weighted vote across stumps, with coin flip stumps ignored and worse stumps flipped.
  • The loop is gradient descent on exponential loss, so one mislabelled row can capture the ensemble and modern work uses gentler losses instead.