Reinforcement Learning

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.

On this page 10
  1. The short answer
  2. The analogy you have already lived
  3. Why this is not a small detail
  4. The trap, drawn out
  5. The simplest fix in the world
  6. Explore more early, less later
  7. Where you have already seen it
  8. What is honestly hard here
  9. Remember this
  10. What to learn next

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 forever

That 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

bash
pip install numpy

Watching 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.

explore_or_not.py
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")
Output
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 chais

This 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.

python
epsilon = max(0.05, 1.0 - day / 200)   # 1.0 on day 0, floor of 0.05 from day 190

The 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:

  1. Each $(s,a)$ is visited infinitely often: $\lim_{t\to\infty} N_t(s,a) = \infty$.
  2. 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.