Exploration vs exploitation
An agent has to choose between taking the best thing it knows and trying something that might be better — and getting that balance wrong is the most common reason RL fails.
- 14 min read
- 3 reading levels
- Updated
Read these first
On this page 10
One lesson, three depths. Pick the one that fits you today — you can switch any time.
Beginner — No maths. Plain English.
The short answer
Take the best thing you know, or try something new and risk a worse evening?
An agent faces that question on every single step, forever.
The analogy you have already lived
You have a favourite chai stall. You have been going for two years. It is good.
There is a new stall that opened last month, forty steps further. It might be better. It might be terrible.
Every evening you choose. Go to the one you trust, or spend one evening finding out about the other one. Going to your usual is exploiting — cashing in what you already know. Trying the new one is exploring — paying for information.
Here is the uncomfortable truth. If you never try the new stall, you will never know it was better. And you cannot know whether it was worth trying until after you have tried it.
Why this is not a small detail
It is tempting to treat this as a minor tuning question. It is not. It decides whether your agent learns anything at all.
An agent that never explores gets locked into the first thing that worked. It stops improving on day one, and it never finds out what it missed. Worse, it looks fine — the training curve is flat and stable, and nothing errors.
An agent that always explores never uses what it learned. It behaves like a coin toss forever.
Neither of those learns. The whole art is the path between them.
This part is confusing for almost everyone the first time. Read it twice — that is normal. The confusion is this. An action that looks bad might really be bad, or your estimate of it might be bad. You cannot tell those apart without spending more tries on it.
The trap, drawn out
Suppose there are three stalls. Stall A is mediocre. Stall C is genuinely the best. On your first visit, A happens to serve a great cup and C happens to serve a burnt one.
your beliefs after one visit each:
stall A **** (lucky cup)
stall B *
stall C * (unlucky cup)
a never-exploring agent from here:
goes to A. forever. thousands of times.
never returns to C. never learns it was wrong.One unlucky cup, and the best stall in the neighbourhood is written off permanently. That is not a made-up story — you will watch it happen in the code below.
The simplest fix in the world
Roll a die before you choose. Most of the time, go to your favourite. Now and then, pick a stall at random.
That is called epsilon-greedy, where epsilon is the small chance of going random. Being greedy means taking your current favourite. Epsilon is how often you refuse to be greedy.
It is crude. It explores blindly, revisiting stalls it already knows are bad. And it works well enough that it is still the default in a great deal of production code.
Explore more early, less later
On day one, you know nothing, so almost everything you do should be exploring. After a thousand days, you know a lot, and wandering off is mostly wasted.
So most systems start with a high chance of exploring and shrink it over time. This is called decay, and every agent in this section uses it.
day 1 |##########| almost all exploring
day 50 |###.......| mostly settled
day 500 |#.........| a small dose of curiosity, kept foreverThat last small dose usually stays. Worlds change. The stall you loved may hire a new cook.
Where you have already seen it
- A music app that mostly plays what you like and slips in one unfamiliar track.
- Food delivery apps showing you a restaurant you have never ordered from.
- A/B testing, where a fraction of visitors is deliberately shown the version nobody is sure about.
- Clinical trials — the same trade-off, with the stakes at their most serious. Every patient in the control group is exploration, and that is exactly why it is an ethical question and not only a mathematical one.
What is honestly hard here
Random exploration is close to useless in a big world. To reach an interesting room in a game, you might need forty correct actions in a row. Random flailing will not produce forty correct actions in a row before the sun burns out.
This is a genuine unsolved problem, and it is the reason that games needing long, precise sequences remain hard for reinforcement learning. Better exploration methods exist — trying things you are most uncertain about, or rewarding an agent for surprising itself. None of them fully solves it.
Remember this
- Exploit to use what you know. Explore to find out what you do not.
- Pure exploitation locks in an early accident and looks perfectly healthy while doing it.
- Explore a lot early, less later, and never quite stop.
What to learn next
- Multi-armed bandits — this trade-off in its purest form, with methods that beat epsilon-greedy.
- Q-learning — where exploration meets a full sequential problem.
- Probability — the uncertainty these methods are reasoning about.
Developer — Code and libraries.
Setup
pip install numpyWatching an agent lock itself out
Three chai stalls. Each either serves a good cup or a bad one, with a fixed hidden probability. Stall C is the best. The agent visits each stall once, then follows a rule for the next 497 days.
import numpy as np
TRUE = np.array([0.30, 0.55, 0.70]) # real chance each stall gives you a good chai
NAMES = ["stall A", "stall B", "stall C"]
DAYS = 500
def run(epsilon, seed):
rng = np.random.default_rng(seed)
counts = np.zeros(3)
means = np.zeros(3)
picks = np.zeros(3, dtype=int)
happy = 0
for day in range(DAYS):
if day < 3:
arm = day # try each stall once
elif rng.random() < epsilon:
arm = rng.integers(3) # explore
else:
arm = int(np.argmax(means)) # exploit
good = 1.0 if rng.random() < TRUE[arm] else 0.0
counts[arm] += 1
means[arm] += (good - means[arm]) / counts[arm] # running average, no list needed
picks[arm] += 1
happy += good
return happy, picks, means
for eps, label in [(0.0, "never explore (epsilon = 0.00)"),
(0.1, "explore a bit (epsilon = 0.10)"),
(0.5, "explore a lot (epsilon = 0.50)")]:
happy, picks, means = run(eps, seed=13)
print(f"{label}")
print(f" good chais in {DAYS} days : {int(happy)}")
print(f" visits per stall : {dict(zip(NAMES, picks))}")
print(f" what it believes : {np.round(means, 2).tolist()}")
print()
print("best possible on average:", int(DAYS * TRUE.max()), "good chais")never explore (epsilon = 0.00)
good chais in 500 days : 136
visits per stall : {'stall A': 498, 'stall B': 1, 'stall C': 1}
what it believes : [0.27, 0.0, 0.0]
explore a bit (epsilon = 0.10)
good chais in 500 days : 349
visits per stall : {'stall A': 15, 'stall B': 22, 'stall C': 463}
what it believes : [0.27, 0.5, 0.72]
explore a lot (epsilon = 0.50)
good chais in 500 days : 304
visits per stall : {'stall A': 87, 'stall B': 124, 'stall C': 289}
what it believes : [0.32, 0.55, 0.72]
best possible on average: 350 good chaisThis output is the whole lesson
The greedy agent got 136 out of a possible 350. It visited stall A 498 times and the other two once each. On its single visit to B and its single visit to C, both served a bad cup. Their estimates stayed at zero and were never revisited.
Look at what it believes at the end: [0.27, 0.0, 0.0]. It is convinced that two of the three stalls never serve a good cup. It has been wrong for 497 consecutive days and has no way of finding out.
Nothing crashed. No warning was printed. A dashboard would show a stable, converged agent.
Ten percent exploration got 349 out of 350. It found C, its final estimate of 0.72 is close to the truth of 0.70, and it spent 37 days of the 500 checking the alternatives. Those 37 days were the price of not being wrong forever.
Fifty percent exploration got 304. It knows the most — its estimates [0.32, 0.55, 0.72] are the most accurate of the three. And it performs worse, because half its days are spent at stalls it already knows are inferior. Knowledge you do not act on has a cost.
Line by line
means[arm] += (good - means[arm]) / counts[arm] — the running average. This is exactly the same shape as every learning update in this section: estimate += step_size * (new_observation - estimate). With a step size of 1/n it computes the true mean; with a fixed step size it tracks a changing world instead. That single choice is the difference between an agent that assumes the world is static and one that does not.
if day < 3: arm = day — one forced visit each, so nothing starts at a completely uninformed zero. Without it, argmax on an all-zero array returns index 0 and stall A gets picked forever regardless of epsilon. That failure is silent, which is what makes it dangerous.
seed=13 — chosen deliberately, because with this seed the greedy agent's early luck went to the worst stall. Change it to seed=1 and the greedy agent gets lucky and does fine. That is the point: greedy is not reliably bad, it is unreliable. One run proves nothing.
Decaying epsilon: the version you should actually write
Fixed exploration keeps paying the same tax forever. Decay it instead.
epsilon = max(0.05, 1.0 - day / 200) # 1.0 on day 0, floor of 0.05 from day 190The floor matters. Drive epsilon to exactly zero and the agent can never recover from a world that changed. A permanent five percent is cheap insurance.
Common mistakes
Starting the estimates at zero when rewards are non-negative. Zero is pessimistic, so an arm that gives a bad first sample looks correct and is abandoned. Start them high instead — optimistic initialisation — and every arm has to be tried before it can be dismissed. Set means = np.ones(3) * 2.0 and even a greedy agent explores on its own for a while.
Decaying epsilon by episode when the episodes get longer. In a task where good agents survive longer, per-episode decay means your exploration collapses in wall-clock terms far faster than you intended. Decay by environment step.
Evaluating with exploration still switched on. Your reported score includes deliberately random actions. Always run a separate greedy evaluation with epsilon set to zero, and report both numbers.
Concluding an algorithm is better from one seed. Run five. Report the spread. This field has a long history of results that evaporated when someone changed the seed.
Try it yourself
Change TRUE to [0.68, 0.69, 0.70] — three stalls that are nearly identical. Run all three epsilons again. You will find the gap between them almost vanishes, because when every option is equally good, exploring costs you almost nothing. Then try [0.05, 0.05, 0.70] and watch the greedy agent's failures become catastrophic. The value of exploring depends entirely on how much the options differ.
What to learn next
- Multi-armed bandits — this trade-off in its purest form, with methods that beat epsilon-greedy.
- Q-learning — where exploration meets a full sequential problem.
- Probability — the uncertainty these methods are reasoning about.
Researcher — Mathematics and papers.
The formal trade-off
Exploration is not a heuristic bolted onto RL. It is intrinsic: the agent controls its own data distribution, so the sampling policy determines what is estimable.
The standard measure is regret. Over $T$ steps, $$ \mathcal{R}(T) = T \mu^* - \mathbb{E}\left[ \sum_{t=1}^{T} \mu_{a_t} \right] $$ where $\mu^*$ is the mean reward of the best action and $\mu_{a_t}$ that of the action taken at $t$. Sublinear regret, $\mathcal{R}(T)/T \to 0$, is the minimum bar: it means the agent eventually behaves optimally.
A purely greedy policy has $\Theta(T)$ regret — linear, with a constant probability of locking onto a suboptimal arm forever, exactly as the code above shows. Fixed-$\epsilon$ greedy also has $\Theta(T)$ regret, since it wastes $\epsilon T$ pulls on uniformly random arms. Only a decaying schedule with $\epsilon_t \propto 1/t$ achieves logarithmic regret, and the constants are poor (Auer, Cesa-Bianchi and Fischer, 2002).
GLIE and convergence
Tabular Q-learning converges to $Q^*$ with probability 1 under Robbins-Monro step sizes and infinite exploration: every state-action pair must be visited infinitely often. The standard packaging is GLIE — Greedy in the Limit with Infinite Exploration:
- Each $(s,a)$ is visited infinitely often: $\lim_{t\to\infty} N_t(s,a) = \infty$.
- The policy converges to greedy: $\lim_{t\to\infty} \pi_t(a \mid s) = \mathbb{1}[a = \arg\max_{a'} Q_t(s,a')]$.
$\epsilon_t = 1/t$ satisfies both. A fixed $\epsilon$ satisfies (1) but not (2); a schedule decaying too fast satisfies (2) but not (1). This is why an $\epsilon$ floor is a practical compromise rather than a theoretically clean choice — it buys robustness to non-stationarity at the cost of the asymptotic guarantee.
Better than random
Optimism in the face of uncertainty. Initialise values above the maximum achievable return, or add an explicit uncertainty bonus. Every unvisited action looks attractive until measured. UCB-style bonuses of the form $c\sqrt{\ln t / N_t(a)}$ give $O(\log T)$ regret in bandits; see multi-armed bandits. Lifting this to MDPs gives UCRL2 (Jaksch, Ortner and Auer, 2010) with regret $\tilde{O}(D|\mathcal{S}|\sqrt{|\mathcal{A}|T})$, where $D$ is the diameter of the MDP.
Posterior sampling. Maintain a distribution over MDPs, sample one, act optimally in the sample. PSRL (Osband, Russo and Van Roy, 2013) achieves Bayesian regret competitive with UCRL2 and is usually far better empirically. Bootstrapped DQN (Osband et al., 2016) approximates this with an ensemble of value heads, giving temporally extended exploration that $\epsilon$-greedy cannot produce.
Intrinsic motivation. Add a bonus for novelty. Count-based methods use $1/\sqrt{N(s)}$, generalised to continuous spaces by pseudo-counts from a density model (Bellemare et al., 2016). ICM (Pathak et al., 2017) rewards prediction error of a learned forward model. RND (Burda et al., 2018) rewards error in predicting a fixed random network's output on the current state, sidestepping the noisy-TV problem where stochastic transitions produce permanently high prediction error.
Deep exploration
The distinction that matters at scale is between dithering and deep exploration. $\epsilon$-greedy perturbs each action independently, producing a random walk in action space. The probability of executing a specific length-$H$ sequence by chance is $\epsilon^H |\mathcal{A}|^{-H}$ — hopeless for $H$ beyond about 20.
Deep exploration commits to a coherent hypothesis for a whole episode: sample a value function, act greedily with respect to it, then update. This is what posterior sampling and bootstrapped ensembles buy. Montezuma's Revenge, requiring roughly 100 correct actions before any reward, was the canonical demonstration that dithering does not scale; Go-Explore (Ecoffet et al., 2021) eventually solved it by explicitly returning to promising states before exploring from them.
The honest state of the field
There is no exploration method that is uniformly best, and there is no free lunch. Optimism needs a well-specified uncertainty estimate, which deep networks do not reliably provide. Intrinsic motivation changes the objective and can dominate the extrinsic reward. Posterior sampling requires a tractable posterior.
For most practical problems the highest-value intervention is not a better exploration algorithm; it is a denser reward or a better state representation. That is a less satisfying answer than a new bonus term, and it is more often correct.
References
- Auer, Cesa-Bianchi and Fischer (2002), Finite-time Analysis of the Multiarmed Bandit Problem.
- Jaksch, Ortner and Auer (2010), Near-optimal Regret Bounds for Reinforcement Learning.
- Osband, Russo and Van Roy (2013), (More) Efficient Reinforcement Learning via Posterior Sampling — arxiv.org/abs/1306.0940.
- Bellemare et al. (2016), Unifying Count-Based Exploration and Intrinsic Motivation — arxiv.org/abs/1606.01868.
- Osband et al. (2016), Deep Exploration via Bootstrapped DQN — arxiv.org/abs/1602.04621.
- Burda et al. (2018), Exploration by Random Network Distillation — arxiv.org/abs/1810.12894.
- Ecoffet et al. (2021), First return, then explore, Nature.
What to learn next
- Multi-armed bandits — this trade-off in its purest form, with methods that beat epsilon-greedy.
- Q-learning — where exploration meets a full sequential problem.
- Probability — the uncertainty these methods are reasoning about.