A multi-armed bandit is a problem where you repeatedly choose one of several options, each with an unknown reward rate, and see the reward only for the option you chose. The goal is to collect as much reward as possible while you are still learning which option is best, which forces a trade-off between exploiting the current favourite and exploring the others. Epsilon-greedy, upper confidence bound (UCB) and Thompson sampling are the three standard algorithms for it.
Bandits are the smallest problem in which exploration has a price, which is why courses on reinforcement learning start with them, and they sit behind adaptive A/B tests, ad allocation and clinical trial designs. This guide derives the three algorithms and their regret bounds, runs them against each other in seeded simulations, and measures the part most introductions skip: what an adaptive bandit costs you in statistical power and bias.
What is a multi-armed bandit? A concrete example#
The name comes from slot machines, once called one-armed bandits, and the problem was posed formally by Robbins in 1952 [1]: a gambler facing a row of them must decide which levers to pull, and how often, without knowing their payout rates. Suppose you have five versions of a sign-up page and each visitor either converts or does not. Unknown to you, their conversion rates are 0.30, 0.45, 0.50, 0.55 and 0.60. A visitor sent to the 0.30 page costs 0.30 conversions in expectation; one sent to the 0.55 page costs only 0.05, but that page is also the hardest to tell apart from the best.
Two naive strategies fail in opposite directions. Splitting traffic evenly for 10,000 visitors (a classic A/B/n test) learns the rates well but sends four fifths of visitors to worse pages, losing exactly 1,200 conversions in expectation. Always sending visitors to whichever page looks best so far (pure greedy) often locks onto the wrong page after a few unlucky early visitors. In our simulation below the greedy strategy ended on the best page in only 42% of runs. Bandit algorithms sit between the two, exploring in proportion to how plausible each arm still is and shifting traffic to the winner as evidence arrives.
Regret: how bandit algorithms are scored#
Write for the mean reward of arm , for the best mean, and for the gap of arm . If is the number of times arm was pulled in the first steps, the expected regret is
Here is the arm chosen at step , and the expectation is over both the rewards and any randomness in the algorithm. The second form is the useful one: regret is a weighted count of mistakes, where pulling an arm with a small gap is a small mistake and pulling a terrible arm is a big one. A good algorithm therefore stops pulling clearly bad arms quickly and spends its exploration on the arms that are close to the best. Every regret number below is this quantity (pseudo-regret), averaged over seeded runs.
Linear regret means mistakes at a fixed rate forever (the uniform split loses 0.12 conversions per visitor); regret growing like means mistakes become ever rarer. How slowly can it grow? Lai and Robbins answered this in 1985 [3]. For any algorithm that is reasonable on every instance (its regret is for every ),
is the Kullback-Leibler divergence between Bernoulli distributions with means and : how distinguishable one pull of arm is from one pull of the best arm. The bound says each suboptimal arm must be pulled about times, or the algorithm risks never finding out that it is suboptimal. Arms that look almost like the best one are expensive to rule out. For our five arms the constant is 19.5, so the asymptotic rate at is . Almost all of that constant comes from the 0.55 arm: its gap is only 0.05 and its KL divergence from the 0.60 arm is 0.0051, contributing 9.7 on its own.
Is a multi-armed bandit reinforcement learning?#
Yes, in the sense that it is the simplest case of it. A Markov decision process has states, actions, transitions and rewards; a bandit is an MDP with a single state that every action returns you to. What disappears is the hard part of full reinforcement learning, credit assignment over time: in a bandit, an action's consequences arrive immediately and do not change what happens next, so there is no need for Bellman equations or bootstrapped value estimates. What remains is the other hard part, the exploration-exploitation trade-off, in its purest form.
| Problem | What the learner sees before acting | Does the action change the future? | Typical method |
|---|---|---|---|
| Multi-armed bandit | Nothing | No | Epsilon-greedy, UCB, Thompson sampling |
| Contextual bandit | A context vector (user, prompt, patient) | No | LinUCB, linear or neural Thompson sampling |
| Full reinforcement learning | A state | Yes, through transitions | Q-learning, policy gradients |
The bandit estimates are the one-state version of the action values used everywhere else in RL, and the exploration rules below reappear almost unchanged: epsilon-greedy is the default behaviour policy in Q-learning, and optimism in the face of uncertainty is the idea behind count-based exploration bonuses in larger problems [11].
Epsilon-greedy#
Keep a running average of the rewards from each arm. With probability pull the arm with the highest average; with probability pull an arm chosen uniformly at random. The average is updated incrementally after each pull of arm :
where is the number of pulls of arm including this one and is the reward just observed. This "old estimate plus step size times error" form is the template for every value update in reinforcement learning; replace with a constant step size and it is the Q-learning update with no next state.
Epsilon-greedy explores blindly: it spends as much traffic on the 0.30 arm, obviously bad after a few hundred pulls, as on the 0.55 arm, which is genuinely hard to rule out. With a constant its regret grows linearly, at roughly times the average gap per step. Auer, Cesa-Bianchi and Fischer showed that decaying like gives logarithmic regret, but their schedule needs the smallest gap, which you do not know [4]. We also run the gentler schedule , which needs no knowledge of the gaps.
Upper confidence bound (UCB)#
UCB replaces random exploration with optimism. For each arm it computes a plausible upper limit on the mean, given the data so far, and pulls the arm whose upper limit is highest. UCB1, from Auer and colleagues [4], first pulls each arm once and then chooses
The first term is the estimated mean and the second is an exploration bonus that shrinks as an arm is pulled more ( grows) and slowly grows for arms that are neglected ( grows). The bonus comes from Hoeffding's inequality: for rewards in , the true mean exceeds with probability at most . An arm is pulled either because it looks good or because we know little about it, and both reasons fade as evidence accumulates. Auer and colleagues proved the finite-time bound
which holds at every , not just in the limit. It is logarithmic, as Lai and Robbins require, but with a loose constant: for our five arms it evaluates to about 2,950 at , while UCB1's measured regret is 282.
A worked example#
After 100 steps on a two-arm problem, suppose arm A has been pulled 60 times with a mean of 0.55 and arm B 10 times with a mean of 0.40. With , UCB1 scores arm A at and arm B at . UCB1 pulls B. Its mean is lower, but ten pulls are too few to rule out that B is better. Both indices exceed 1, an impossible conversion rate: UCB1's bonus is deliberately conservative, which is why its constant is large.
Thompson sampling#
Thompson sampling is the oldest of the three, proposed in 1933 for allocating patients between two treatments [2], and it took almost eighty years for its regret to be analysed [5, 6]. It keeps a posterior distribution over each arm's mean, draws one sample from each posterior, and pulls the arm whose sample is highest. For 0/1 rewards with a uniform prior the posterior is a Beta distribution:
where and are the numbers of successes and failures observed on arm . The effect is probability matching: each arm is pulled with exactly the posterior probability that it is the best arm. An arm that is probably bad is still tried occasionally, in proportion to how plausible it is that it is actually best, and never more than that.
In the worked example, arm A's posterior is , with mean 0.548 and standard deviation 0.063, and arm B's is , with mean 0.417 and standard deviation 0.137. By simulation, a draw from B beats a draw from A 19.6% of the time, so Thompson sampling sends about one in five of the next visitors to B, where UCB1 sent the next one to B with certainty.
Kaufmann, Korda and Munos proved that for Bernoulli rewards Thompson sampling matches the Lai-Robbins constant exactly [6]: it is asymptotically optimal, not just logarithmic. Chapelle and Li found it hard to beat on display advertising and news recommendation data [7].
How do the algorithms compare? A seeded simulation#
Setup (simulation). The five Bernoulli arms from the example, horizon , 2,000 independent runs per algorithm, numpy seed 20261101. We report mean regret at with a 95% interval for the mean, the 99th percentile across runs (the bad-luck case), and the share of all pulls that went to the best arm.
| Algorithm | Mean regret at T = 10,000 | 99th percentile | Pulls on best arm |
|---|---|---|---|
| Uniform split (A/B/n test) | 1,200 (exact) | 1,200 | 20% |
| Greedy (ε = 0) | 529 ± 27 | 2,999 | 42% |
| ε-greedy, ε = 0.01 | 246 ± 12 | 1,010 | 64% |
| ε-greedy, ε = 0.1 | 185 ± 5 | 578 | 81% |
| ε-greedy, ε = min(1, K/√t) | 154 ± 4 | 571 | 85% |
| UCB1 (c = √2) | 282 ± 1.5 | 367 | 68% |
| UCB, c = 0.5 (tuned, no guarantee) | 65 ± 2.2 | 277 | 91% |
| Thompson sampling, Beta(1, 1) prior | 70 ± 1.5 | 195 | 91% |
Four things stand out. Greedy's median run loses about 500, but one run in ten loses 1,500 or more because it locked onto a worse arm early, and its 99th percentile, 2,999, is worse than the uniform split. UCB1 is the most predictable (smallest spread across runs), but its conservative bonus costs four times Thompson sampling's regret. Thompson sampling with nothing tuned matches a UCB whose constant was tuned on this very instance. And constant ε-greedy does well over this horizon, but its curve bends upwards as the linear exploration cost takes over.
The dashed Lai-Robbins line sits above Thompson sampling's curve. That is not a contradiction: the bound describes the limit, and lower-order terms dominate at moderate horizons when one gap is only 0.05. Rerun to 100,000 steps (400 runs), Thompson's regret reached 108 ± 4 and was growing at 15.3 per unit of , still below the 19.5 slope it must eventually reach; UCB1 reached 627 ± 7, growing at 152 per unit of , almost eight times the optimal rate.
As a cross-check, we ran the 10-armed Gaussian testbed of Sutton and Barto [11] (2,000 random problems, 1,000 steps). Over the last 100 steps, greedy chose the optimal arm 34.7% of the time and averaged a reward of 1.02; ε = 0.01 reached 59.0% and 1.31; ε = 0.1 reached 80.3% and 1.37; UCB with reached 86.0% and 1.49, against 1.55 for an oracle. These match the curves in the book's Figures 2.2 and 2.4.
UCB vs Thompson sampling#
Thompson sampling usually wins on regret, in the literature [7, 9] as in our table. UCB still has real advantages, and the deployment matters more than the regret curve.
| Consideration | UCB | Thompson sampling |
|---|---|---|
| Regret on Bernoulli arms | Logarithmic; UCB1's constant is loose | Asymptotically optimal [6]; lowest in our runs |
| Determinism | Deterministic given the data; easy to audit and replay | Randomised; needs a logged seed to replay |
| Delayed or batched feedback | Every step in a batch picks the same arm | Different draws spread a batch across plausible arms |
| Prior knowledge | No natural place for it | Encoded in the prior (for example, Beta from a past test) |
| Non-Bernoulli rewards | Needs a bounded or sub-Gaussian range for the bonus | Needs a posterior; approximate posteriors for complex models |
| Tuning | The constant c matters a lot (282 vs 65 above) | Little to tune, beyond the prior |
The batching row matters: production systems update every few minutes, not after every impression. A deterministic rule then sends a whole batch to one arm, while Thompson sampling spreads it in proportion to the posterior [7, 9].
Multi-armed bandit vs A/B testing#
An A/B test fixes the allocation so that, at the end, you can estimate the difference between arms with a known error rate. A bandit changes the allocation to collect reward during the test. Most comparisons say the bandit sacrifices some certainty; we measured how much.
Setup (simulation). Two arms with conversion rates 10% and 12%, 20,000 visitors, 4,000 seeded replications. Three designs: a 50/50 split; Thompson sampling with Beta(1, 1) priors; and Thompson sampling with a floor that keeps each arm's share of traffic at or above 20%. At the end, each run applies the usual two-proportion z-test at the 5% level to whatever data the design collected, which is what an analyst who exports the logs would do. We also reran everything with both arms at 10%, to measure false positives.
The bandit does what it promises: it loses 29 conversions instead of 200, and it ends with the right arm ahead in 99.8% of runs. But the naive analysis of its data is compromised in three ways. Power falls from 99.6% to 79.7%, because the median run shows the worse arm to only 1,122 visitors. The estimates are biased: the losing arm's average measured rate is 9.29% rather than 10%, so the estimated lift is 2.7 points instead of the true 2.0. This is a general property of adaptively collected data: an arm that has an unlucky streak is sampled less and never gets the chance to recover, so sample means are biased downwards [12]. Most striking, when the two arms are identical, the naive z-test declares a winner 12.3% of the time instead of 5%.
The 20% floor recovers almost everything: power 95.7%, false positive rate 5.1%, no visible bias, at a cost of 81 lost conversions, still 60% fewer than the A/B test. Use a pure bandit when the goal is reward and nobody will report the effect size, an A/B test when the estimate is the product, and a floor (or an analysis built for adaptive data) when you need both. For more on getting intervals and sample sizes right, see our guides on statistical significance and how many samples an evaluation needs.
What is a contextual bandit?#
In a contextual bandit the learner sees a feature vector before each choice: who the user is, what the query was, which patient is being treated. The best arm can differ by context, so the learner estimates a model of reward given context and arm. LinUCB, introduced for news article recommendation [8], assumes the expected reward of arm is linear in the context, , and picks
where is the ridge regression estimate from past contexts and rewards (with the sum of over pulls of arm ), and sets the width of the confidence bonus. The bonus is large for contexts unlike anything this arm has seen, which is UCB's optimism lifted to a regression. Thompson sampling generalises the same way, by sampling from a Gaussian posterior [9]. Contextual bandits also produce logged data that can be reused to evaluate a new policy offline, which is the bridge to offline reinforcement learning.
Bandits in LLM training and evaluation#
Bandits show up around language models in two places, and it is worth being precise about both.
Training. A common formulation of fine-tuning from human feedback treats each prompt as a context, the whole response as a single action, and the reward model's score as the reward, with the episode ending after one response. The InstructGPT paper describes its RL environment in exactly these terms, as "a bandit environment" [13]. That makes response-level RLHF a contextual bandit with an enormous action space, optimised by policy gradient methods rather than by the index rules above. The wider picture is in our guide to reinforcement learning for LLMs.
Evaluation. Picking the best of several prompts, decoding settings or checkpoints on a limited budget looks like a bandit, and adaptive allocation can save calls. Two cautions carry over. Regret is the wrong objective: you want to identify the best option or estimate its score, a different problem called best-arm identification or pure exploration [10]. And scores from adaptively allocated samples are biased, with the losers looking worse than they are. If the result will be reported, freeze the allocation or correct for it, and compute intervals as you would for any evaluation. The same applies when evaluating RL agents.
Code: the three algorithms in numpy#
This is a complete, runnable implementation of the three algorithms as described above, on the five-arm example. With 50 seeds it prints mean regrets close to the table (for example, about 216, 273 and 76 for ε-greedy, UCB1 and Thompson sampling; ε-greedy's spread across runs is wide, so its 50-run mean moves more).
import numpy as np
def run_bandit(mu, T, policy, seed=0, eps=0.1, c=np.sqrt(2)):
"""One run on a Bernoulli bandit. Returns cumulative pseudo-regret."""
rng = np.random.default_rng(seed)
K = len(mu); n = np.zeros(K); s = np.zeros(K); regret = 0.0
for t in range(1, T + 1):
if policy == "eps-greedy":
means = np.where(n > 0, s / np.maximum(n, 1), np.inf) # untried arms first
a = rng.integers(K) if rng.random() < eps else int(np.argmax(means))
elif policy == "ucb":
a = t - 1 if t <= K else int(np.argmax(s / n + c * np.sqrt(np.log(t) / n)))
elif policy == "thompson":
a = int(np.argmax(rng.beta(1 + s, 1 + n - s))) # Beta(1,1) prior
r = rng.random() < mu[a]
n[a] += 1; s[a] += r
regret += max(mu) - mu[a]
return regret
mu = np.array([0.30, 0.45, 0.50, 0.55, 0.60])
for p in ["eps-greedy", "ucb", "thompson"]:
regs = [run_bandit(mu, 10_000, p, seed=k) for k in range(50)]
print(f"{p:11s} mean regret {np.mean(regs):6.1f}")
Choosing an algorithm#
| Situation | Recommendation | Why |
|---|---|---|
| 0/1 or bounded rewards, reward during the test matters | Thompson sampling with a Beta(1, 1) prior | Lowest regret in practice, almost nothing to tune |
| Decisions must be deterministic and replayable | UCB, with c checked in simulation | Same data, same choice; auditable |
| Need a valid effect estimate at the end | A/B test, or a bandit with an allocation floor | Pure bandits bias estimates and inflate false positives |
| Reward depends on user or item features | Contextual bandit (LinUCB or linear Thompson sampling) | One arm is rarely best for everyone |
| Rates drift over time | Discounted or sliding-window estimates, plus a floor | Stationary algorithms stop exploring arms that later improve |
| Quick baseline or teaching | ε-greedy with a decaying ε | Easy to explain; competitive over short horizons |
Failure modes#
Non-stationarity. Every guarantee above assumes the arms' rates are fixed. Real conversion rates drift with seasons, campaigns and novelty effects. A stationary algorithm that has stopped exploring an arm will not notice when it improves. Discount old observations, use a sliding window, or keep an exploration floor.
Delayed rewards. If conversions arrive hours after the impression, the algorithm makes many choices on stale counts. Deterministic rules suffer most; include the delay in any simulation used to choose settings.
The wrong reward. A bandit optimises exactly the reward you give it. Optimise click-through and it will find the most clickable variant, whether or not that is the most useful one. This is the bandit-sized version of reward hacking.
Reading bandit logs as an experiment. As measured above, a z-test on adaptively collected data can double the false positive rate and inflate effect sizes.
Greedy by accident, or over-tuned. Turning exploration off "once things look stable" turns any algorithm into greedy, with greedy's heavy tail. At the other extreme, UCB with c = 0.5 won our table only on the instance it was tuned for; Thompson sampling came within 5 units with nothing tuned.
The next step up is to let actions change the state, which brings in Markov decision processes and the value functions built on them.
Frequently asked questions#
What is a multi-armed bandit?
It is a repeated choice among several options whose reward rates are unknown. After each choice you see only the reward of the option you picked, and your choices do not change any state. The aim is to maximise total reward, which means balancing exploitation of the current best option against exploration of options that might be better.
Why is it called a multi-armed bandit?
Slot machines used to be called one-armed bandits, because of the lever on the side and the way they take your money. A gambler facing a row of machines with unknown payout rates, deciding which levers to pull and how often, is the picture behind the name. The problem was posed formally by Herbert Robbins in 1952.
Is a multi-armed bandit reinforcement learning?
Yes, it is the simplest case. A bandit is a Markov decision process with a single state, so actions have immediate rewards but no effect on the future. That removes credit assignment over time and leaves the exploration-exploitation trade-off on its own, which is why reinforcement learning courses usually start with bandits.
Which is better, UCB or Thompson sampling?
On Bernoulli rewards Thompson sampling usually has lower regret and is asymptotically optimal. In our seeded five-arm simulation it lost 70 units of reward over 10,000 steps against 282 for UCB1. UCB is deterministic and easier to audit and replay, while Thompson sampling handles batched or delayed feedback better and accepts prior knowledge.
When should I use a bandit instead of an A/B test?
Use a bandit when the reward collected during the test matters more than a precise effect estimate. Use an A/B test when the estimate is the deliverable. In our simulation of 10% vs 12% conversion, Thompson sampling cut lost conversions from 200 to 29 but power fell to 80% and false positives rose to 12%; a 20% allocation floor restored both.
What is regret in a multi-armed bandit?
Regret is the expected reward lost compared with always choosing the best arm. It equals the sum over arms of each arm's gap to the best mean times the expected number of times that arm was pulled. Good algorithms have regret that grows only logarithmically with the number of steps, and the Lai-Robbins bound says no reasonable algorithm can do better.
What is a contextual bandit?
A contextual bandit observes a feature vector, such as user or query features, before each choice, and the best arm can depend on it. Algorithms such as LinUCB fit a reward model per arm, for example a linear one, and add an uncertainty bonus. Unlike full reinforcement learning, the choice still does not affect future contexts.
Sources#
- H. Robbins. Some aspects of the sequential design of experiments, 1952. doi.org
- W. R. Thompson. On the likelihood that one unknown probability exceeds another in view of the evidence of two samples, 1933. doi.org
- T. L. Lai, H. Robbins. Asymptotically efficient adaptive allocation rules, 1985. doi.org
- P. Auer, N. Cesa-Bianchi, P. Fischer. Finite-time Analysis of the Multiarmed Bandit Problem, 2002. doi.org
- S. Agrawal, N. Goyal. Analysis of Thompson Sampling for the multi-armed bandit problem, 2012. arxiv.org
- E. Kaufmann, N. Korda, R. Munos. Thompson Sampling: An Asymptotically Optimal Finite Time Analysis, 2012. arxiv.org
- O. Chapelle, L. Li. An Empirical Evaluation of Thompson Sampling, 2011. papers.nips.cc
- L. Li, W. Chu, J. Langford, R. E. Schapire. A Contextual-Bandit Approach to Personalized News Article Recommendation, 2010. arxiv.org
- D. Russo, B. Van Roy, A. Kazerouni, I. Osband, Z. Wen. A Tutorial on Thompson Sampling, 2018. arxiv.org
- T. Lattimore, C. Szepesvári. Bandit Algorithms, 2020. doi.org
- R. S. Sutton, A. G. Barto. Reinforcement Learning: An Introduction (2nd ed.), 2018. incompleteideas.net
- X. Nie, X. Tian, J. Taylor, J. Zou. Why Adaptively Collected Data Have Negative Bias and How to Correct for It, 2018. arxiv.org
- L. Ouyang, J. Wu, X. Jiang, D. Almeida, C. L. Wainwright, et al.. Training language models to follow instructions with human feedback, 2022. arxiv.org