Notes / Reinforcement Learning / Note 1 of 9

Leer en español

Multi-armed bandits

How to choose again and again among options whose payoffs can only be learned by trying them, estimating what each is worth and balancing trying the others against using the best one found so far.

An angler spends a season at a lake. Each morning she fishes one of four spots, the pier, the reeds, the rocks or the bridge, and keeps what she catches. Some spots hold more fish than others, but nobody has told her which.

? pier ? reeds ? rocks ? bridge mean catch

A morning's catch says how good the spot she chose was that day, and nothing about the three she passed by. To find the best spot she must sometimes fish spots that look worse, giving up fish today: that is exploring. To catch many fish she must fish the spot that looks best, exploiting what she has learned. This note is about balancing the two. Nothing on the lake tells her that another spot is better on a given morning: there is one situation only, and the notes after this one add situations that change the best choice.

A k-armed bandit problem is choosing again and again among k actions, each giving a random reward whose distribution depends only on the action and does not change over time, so as to collect as much reward as possible over many choices. The name comes from slot machines, called one-armed bandits: this is a machine with k levers. On the lake, k = 4: the actions are the four spots, each morning is a time step t, and a morning's reward is its catch.

The note goes through five ideas:

  1. estimating what each spot is worth, and choosing from the estimates;
  2. updating an estimate without storing every catch;
  3. following the fish when they move;
  4. making the starting estimates drive the exploring;
  5. learning preferences instead of values.

Throughout this page, estimates are drawn in blue ink, and what they move toward, the catches and the true means, in red ink.

1Values of actions

Write At for the spot fished on morning t and Rt for its catch. Each spot a has a value, the catch to expect when fishing it:

q*(a) ≐ E[Rt | At = a]

The value of an action is the reward to expect after taking it. The star marks the true value, which the angler never sees, and ≐ reads “is defined as”.

On the lake, q*(pier) = 1, q*(reeds) = 3, q*(rocks) = 4 and q*(bridge) = 2 fish a morning. Her estimate on morning t, Qt(a), is the average of the catches the spot has given so far:

Qt(a) ≐ Σt−1i=1Ri · 𝟙Ai=aΣt−1i=1𝟙Ai=a

Here 𝟙Ai=a is 1 if spot a was fished on morning i and 0 if not, so both sums keep only the mornings spent at a. A spot never fished gets a default estimate, such as 0. The more a spot is fished, the closer its average comes to q*(a), by the law of large numbers: the average of more and more draws settles on their mean. This is the sample-average method.

The simplest way to choose is greedy: fish the spot with the largest estimate, the greedy action, breaking ties at random.

At ≐ argmaxa Qt(a)

An ε-greedy angler is greedy on most mornings, but with a small probability ε she picks a spot at random among all k, the greedy one included. The greedy spot is then fished with probability 1 − ε + ε/k, and each other spot with ε/k. With k = 4 and ε = 0.2:

  • the greedy spot gets 0.85 and each other spot 0.05;
  • when two spots tie for the largest estimate, they split the 0.8 of greedy mornings, so each gets 0.4 + 0.05 = 0.45, and the other two keep 0.05.

A greedy angler who starts with every estimate at 0 can stop exploring after a single morning:

  1. On the first morning all four estimates are 0, and the tie is broken at random.
  2. A catch is never negative, so if the first one is above zero, that spot's estimate rises above 0 while the other three stay at 0.
  3. Its average stays above 0 whatever it catches next, so the other spots are never tried again.

The figure follows one such season. Each row is a morning, with the four estimates before it; the spot fished is shaded yellow, and its catch is in red.

estimate of each spot before the morning morning pier reeds rocks bridge catch 1 0 0 0 0 5 2 0 5 0 0 2 3 0 3.5 0 0 1 4 0 2.67 0 0 3 5 0 2.75 0 0 1 6 0 2.4 0 0 4 7 0 2.67 0 0 0 8 0 2.29 0 0 3
One greedy season from estimates of 0. The reeds win the first morning's tie and give 5 fish; the other estimates stay at 0 from then on, and the season spends all 300 mornings at the reeds without ever trying the rocks, the best spot.

Over 1,000 seasons of 300 mornings, 9 greedy seasons in 10 never leave their first spot (the others caught nothing on their first morning, so the tie stayed open), and greedy fishes the rocks on about 29% of mornings all season long. Exploring fixes this:

AnglerFish per morning, mornings 291–300With exact estimates
Greedy2.614
ε = 0.053.823.925
ε = 0.23.673.7

The last column is what each angler would catch with exact estimates: 4 for greedy, the best possible, by fishing the rocks every morning, and less with ε, since exploring still sends her to worse spots on some mornings. With ε = 0.2 she finds the rocks sooner, fishing them on 76% of mornings 91–100 against 62% with ε = 0.05, but later in the season her many random mornings cost her more. Exploring costs fish today and pays later.

2Averaging as you go

Averaging every catch means storing every catch. The average can instead be updated after each one, keeping one number and one count per spot. Take a single spot and count its own mornings: Ri is now the catch of its ith morning, and Qn its estimate after it has been fished n − 1 times:

Qn ≐ R1 + R2 + ⋯ + Rn−1n − 1

The first n − 1 catches add up to (n − 1)Qn, so after the nth catch the average is Qn+1 = [Rn + (n − 1)Qn]/n, which rearranges to

Qn+1 = Qn + 1n[Rn − Qn]

It holds for n = 1 too, giving Q2 = R1 whatever the starting guess Q1. Two counters are now in play: t counts the mornings of the season, and n the mornings at one spot. Over six mornings, for the rocks:

tSpotCatchnQ(rocks) after
1reeds20
2rocks510 + 1(5 − 0) = 5
3rocks325 + ½(3 − 5) = 4
4pier14
5rocks634 + ⅓(6 − 4) ≈ 4.67
6rocks244.67 + ¼(2 − 4.67) = 4

The rocks end at 4, the plain average of 5, 3, 6 and 2. Each line of the table has the same shape:

NewEstimate ← OldEstimate + StepSize [Target − OldEstimate]

The bracket is an error, how far the estimate is from the target, here the latest catch. A single catch is a noisy target, but on average it points the right way, and the step size, here 1/n, sets how far to move. Every method in these notes moves an estimate a step toward a target; the Monte Carlo and TD notes do it with other targets. A step size is written α, or αn(a) when it changes from one catch to the next.

The algorithm

A simple bandit algorithm, ε-greedy with sample averages:

  1. For every spot a, set Q(a) ← 0 and N(a) ← 0.
  2. Choose A: with probability 1 − ε, the spot with the largest Q, breaking ties at random; with probability ε, a spot at random.
  3. Fish A and observe the catch R.
  4. Set N(A) ← N(A) + 1 and Q(A) ← Q(A) + [R − Q(A)]/N(A).
  5. Repeat from step 2 every morning.

3When the fish move

A sample average weighs the first catch as much as the latest. That is right while the spots stay the same, but a lake changes, against the “does not change over time” of the bandit problem defined above. In a nonstationary problem the true values drift while the agent plays, and recent rewards deserve more weight. The usual way to give it is a constant step size α, with 0 < α ≤ 1:

Qn+1 ≐ Qn + α[Rn − Qn]

Rewritten as αRn + (1 − α)Qn, it can be unrolled by putting in the same update for Qn, then for Qn−1, down to Q1:

Qn+1 = αRn + (1 − α)[αRn−1 + (1 − α)Qn−1]
= αRn + (1 − α)αRn−1 + (1 − α)2Qn−1 = ⋯
= (1 − α)nQ1 + Σni=1α(1 − α)n−iRi

It is a weighted average of the start and every catch. Each update multiplies the old estimate by 1 − α, so a catch's weight shrinks by that factor with every later catch. The catches' weights form a geometric sum, α[1 + (1 − α) + ⋯ + (1 − α)n−1] = 1 − (1 − α)n, so with Q1's (1 − α)n they add up to 1.

An exponential recency-weighted average gives each past reward a weight that decays exponentially with the number of rewards that came after it.

With α = 0.25 and Q1 = 0, the rocks' four catches from section 2 (5, 3, 6 and 2) give estimates of 1.25, 1.69, 2.77 and 2.57. The figure shows the weights in the last one.

weight in the estimate 0 0.1 0.2 0.3 0.316 Q1 = 0 0.105 R1 = 5 0.141 R2 = 3 0.188 R3 = 6 0.25 R4 = 2 the start and the catches, oldest first
The weights in the rocks' estimate after four catches, with α = 0.25. The latest catch counts most, and the start still keeps 0.316, more than any catch, which is why the estimate, 2.57, sits so far below the catches' average of 4. The start's weight, (1 − α)n, falls under 0.05 only after 11 catches.

Now let the water warm at morning 151: the fish leave the rocks for the reeds, the rocks' mean falls from 4 to 1 and the reeds' rises from 3 to 5. To compare a sample average with α = 0.25 alone, suppose the angler kept fishing the rocks and every catch was exactly the mean.

rocks’ estimate 0 1 2 3 4 0 10 20 30 mornings after the water warms water warms sample average α = 0.25 true mean
The rocks' estimate after 150 catches of exactly 4, then catches of exactly 1. After 1, 5, 10 and 30 mornings, the sample average reads 3.98, 3.90, 3.81 and 3.50, held up by the 150 earlier catches; with α = 0.25 it reads 3.25, 1.71, 1.17 and 1.00.

With random catches and ε = 0.2, over 1,000 seasons, the share of mornings at the best spot (the rocks until the warming, the reeds after it) is:

MorningsSample averageα = 0.25
141–150, before the warming81%76%
161–17015%81%
191–20048%84%

Before the warming, the sample average does a little better, since its estimates are less noisy. After it, the sample average keeps going back to the rocks, and from morning 151 to 300 it catches 3.46 fish a morning against 4.34 with α = 0.25.

Both updates are one update with a step size αn(a) that may change from catch to catch:

Qn+1 = Qn + αn(a)[Rn − Qn]

With αn(a) = 1/n it is the sample average, and with a constant α the recency-weighted one. The estimates converge to the true values, with probability 1 (in all but impossibly unlucky seasons), when

Σ∞n=1αn(a) = ∞ and Σ∞n=1α2n(a) < ∞

The first sum must grow without limit, so that the steps can always overcome the start and unlucky catches; the second must stay finite, so that the steps end up small enough to settle. Sample averages meet both: the sum of 1/n reaches 7.49 by n = 1,000 and keeps growing, while the sum of 1/n2 stays below 1.645. A constant α fails the second, so its estimates never settle and keep following the latest catches, which is what a changing lake needs. Schedules that meet both often learn slowly or need tuning, and since most problems change over time, a constant α is the usual choice in practice.

4Optimistic starts

Every method so far depends on the starting estimates Q1(a): it is biased by them, its estimates pulled toward the start and so, on average, off from q*(a). How long the bias lasts depends on the step size:

  • with sample averages it disappears after a spot's first catch, since Q2 = R1;
  • with a constant α it only shrinks, as (1 − α)n: from Q1 = 8, the catches 5, 3, 6 and 2 with α = 0.25 still give 5.11, and 2.53 of that is the start.

So the start is a choice, a way to put in prior knowledge or to drive the exploring. The greedy angler of section 1 started at 0, below every spot's value, and stayed at her first spot. A constant α would not have freed her: a catch of 0 only multiplies her estimate by 1 − α, so it never falls back to 0. Start her at 8 instead, above every spot's mean, and almost every catch disappoints, so the greedy choice moves on to the spots still at 8, until all have been tried. The figure is drawn as in section 1.

estimate of each spot before the morning morning pier reeds rocks bridge catch 1 8 8 8 8 2 2 2 8 8 8 4 3 2 8 4 8 1 4 2 8 4 1 4 5 2 4 4 1 3 6 2 3.5 4 1 6
One greedy season from estimates of 8, with sample averages. Each catch pulls its spot far below 8, so each morning goes to a spot not yet tried. On morning 5 the reeds and the rocks tie at 4 and the reeds win; their catch of 3 leaves the rocks ahead, and the season spends the remaining 295 mornings at the rocks.

Over 1,000 seasons, the share of mornings 291–300 spent at the rocks:

AnglerStartStep sizeAt the rocks
Greedy01/n29%
Greedy81/n78%
Greedy80.2593%
ε = 0.0500.2577%

With sample averages the optimism buys about one try of each spot (a first catch of 8 or more, which is rare, keeps a spot in the running), and an unlucky first catch can still bury the rocks for good. With α = 0.25 it fades over several catches and keeps the angler trying for longer. The last two rows share a step size, which makes them the fair comparison, and the optimistic start wins.

It helps only once, at the start. If the water warms at morning 151, the start has long been forgotten, and nothing in it sends the angler to look for what changed. A third way to direct exploring, upper-confidence-bound selection, prefers spots whose estimates are still uncertain because they have been fished little; this note does not go into it.

5Preferences instead of values

Instead of estimating values, the angler can learn a preference Ht(a) for each spot and choose spots with probabilities that grow with it, by a softmax, whose exponential makes every probability positive and whose division by the sum makes them add up to 1:

Pr{At = a} ≐ eHt(a)Σkb=1eHt(b) ≐ πt(a)

A preference is a number that makes an action more likely the larger it is compared with the others. It means nothing in fish. πt(a) is the probability of taking action a on step t. A rule that gives each action a probability is a policy, and πt is the first one in these notes.

Only differences between preferences matter: the softmax of 0.3, −0.1, 0.5 and 0 is 0.275, 0.185, 0.336 and 0.204, and adding 5 to every preference leaves it unchanged. The preferences start equal, here at 0, so every spot starts at 0.25. After each morning they are updated:

Ht+1(At) ≐ Ht(At) + α(Rt − Rt)(1 − πt(At)),
Ht+1(a) ≐ Ht(a) − α(Rt − Rt)πt(a) for all a ≠ At

Here Rt, the baseline, is the average of the catches before morning t, with R1 ≐ R1. A catch above the baseline raises the preference of the spot fished and lowers the others; a catch below it does the opposite. The others move by their probabilities, which add up to 1 − πt(At), exactly what the spot fished moves, so the sum of the preferences never changes: starting at 0, it stays 0. Replaying section 2's six mornings, the same spots and catches, with α = 0.1:

  • Morning 1 changes nothing, since R1 = R1.
  • Morning 5 is a catch of 6 at the rocks against a baseline of 2.75, the average of 2, 5, 3 and 1, and π(rocks) rises from 0.319 to 0.387.
  • Morning 6 is a catch of 2 against a baseline of 3.4, and π(rocks) falls to 0.360. Had morning 6 alone used no baseline, the same catch of 2 would have raised it to 0.426.
before morning 5 pier 0.193 reeds 0.244 rocks 0.319 bridge 0.244 after morning 5: catch 6, baseline 2.75 pier 0.176 reeds 0.219 rocks 0.387 bridge 0.219 after morning 6: catch 2, baseline 3.4 pier 0.183 reeds 0.229 rocks 0.360 bridge 0.229 0 0.25 0.5 probability of fishing the spot, π
The probabilities of the four spots before morning 5 and after mornings 5 and 6, marked in blue as what the angler has learned. A good catch at the rocks takes probability from the other three spots; a poor one gives some back.

The baseline makes a catch count as good or bad compared with the usual catch. Without it, any catch of a fish or more raises the spot fished, the poor spots included, and the angler tells the spots apart more slowly. Over 1,000 seasons:

PreferencesAt the rocks, mornings 291–300
With the baseline98%
Without a baseline86%

Why the update works

The update is stochastic gradient ascent on the expected catch. Exact gradient ascent would move each preference along the slope of the expected reward:

Ht+1(a) ≐ Ht(a) + α∂E[Rt]∂Ht(a), E[Rt] = Σx πt(x)q*(x)

The values q*(x) are unknown, so this slope cannot be computed. Four steps show that the update above follows it on average:

  1. A baseline adds nothing. The values q*(x) do not depend on the preferences, so the slope reaches only the probabilities: ∂E[Rt]/∂Ht(a) = Σx q*(x) ∂πt(x)/∂Ht(a). The probabilities always sum to 1, so their changes sum to 0: Σx ∂πt(x)/∂Ht(a) = 0. Any number Bt that does not depend on x can therefore be subtracted:
    ∂E[Rt]∂Ht(a) = Σx (q*(x) − Bt) ∂πt(x)∂Ht(a)
  2. The sum becomes an expectation. Multiplying each term by πt(x)/πt(x) weights it by the probability of fishing x, which makes the sum an expected value over the spot chosen, At:
    = E[(q*(At) − Bt) ∂πt(At)∂Ht(a) / πt(At)]
  3. What was observed replaces what is unknown. Choose Bt = Rt, which is built from the catches before t and so does not depend on the spot chosen at t. Then put the catch Rt in place of q*(At). By the law of total expectation, the expected value can be taken first over the catch for a given At; the other factors depend only on At, and E[Rt | At] = q*(At), so the result is the same.
  4. The softmax's slope. In πt(x) = eHt(x)/Σb eHt(b), raising Ht(a) grows the sum, and the numerator too when x = a. By the quotient rule, the slope is πt(a) − πt(a)2 for x = a and −πt(x)πt(a) for any other x; together, ∂πt(x)/∂Ht(a) = πt(x)(𝟙a=x − πt(a)), where 𝟙a=x is 1 if a = x and 0 if not. The πt(At) cancels:
    ∂E[Rt]∂Ht(a) = E[(Rt − Rt)(𝟙a=At − πt(a))]

One sample of this expectation in place of the slope gives

Ht+1(a) = Ht(a) + α(Rt − Rt)(𝟙a=At − πt(a)) for all a,

the update of the preferences in one line. With a = At the indicator is 1, which gives the first line of the update above, and for every other a it is 0, which gives the second. Using one sample, right only on average, in place of the exact slope is what makes the ascent stochastic. The baseline does not change the expected update, whatever number it is, as long as it does not depend on the spot chosen, but it changes how much single updates vary, and so how fast the preferences settle.

6Summary

The key ideas next to their NumPy equivalents. r holds this morning's catch and a its spot, r_hist and a_hist the earlier ones, r_a the catches of spot a so far, oldest first and this morning's included, q, n and h the estimates, counts and preferences, k the number of spots and rng a NumPy random generator.

Sample average
Qt(a) = mean of the rewards when a was taken
q[a] = r_hist[a_hist == a].mean()
Greedy choice
At = argmaxa Qt(a), ties at random
best = np.where(q == q.max())[0]
a = rng.choice(best)
ε-greedy choice
ε/k each, plus 1 − ε for the greedy action
if rng.random() < eps:
    a = rng.integers(k)
else:
    a = rng.choice(best)
Incremental average
Qn+1 = Qn + [Rn − Qn]/n
n[a] += 1
q[a] += (r - q[a]) / n[a]
Constant step size
Qn+1 = Qn + α[Rn − Qn]
q[a] += alpha * (r - q[a])
Its weights
Qn+1 = (1 − α)nQ1 + Σi α(1 − α)n−iRi
i = np.arange(1, n[a] + 1)
w = alpha * (1-alpha) ** (n[a]-i)
q_next = (1-alpha) ** n[a] * q1
q_next += w @ r_a
Optimistic start
Q1(a) above every value, here 8
q = np.full(k, 8.0)
Softmax
πt(a) = eHt(a) / Σb eHt(b)
pi = np.exp(h - h.max())
pi /= pi.sum()
Gradient bandit
Ht+1(a) = Ht(a) + α(Rt − Rt)(𝟙a=At − πt(a))
onehot = np.arange(k) == a
step = alpha * (r - r_bar)
h += step * (onehot - pi)
Baseline
Rt = average of R1, …, Rt−1; R1 = R1
if r_hist.size:
    r_bar = r_hist.mean()
else:
    r_bar = r