On-Policy First-Visit MC Control
Learn the best way to act straight from full episodes, with no model and no staged starts, by keeping every action slightly possible and improving the same policy you play.
Why Does This Exist?
Without a model of the environment you cannot plan ahead, so you must learn action values from experience and then act greedily in them. That creates a trap: a deterministic policy always picks the same action per state, so rival actions never get sampled, their values never get learned, and the agent can never find out it is wrong.
Theory papers dodge the trap with exploring starts, the assumption that every episode begins at a random state-action pair. Real systems cannot do that. A car cannot start mid-crash, a plant cannot boot into a fault, chess always opens from the same board. This page removes the assumption with epsilon-soft policies: every action keeps at least probability everywhere, so every reachable pair gets sampled infinitely often from ordinary fixed starts.
The price and the payoff both matter here. For the starting assumption this replaces, see Monte Carlo with exploring starts. For the prediction half of the machinery, see Monte Carlo control. For the exploration device itself, see epsilon-greedy.
The one idea you need first
Generalized policy iteration alternates evaluation (refresh toward the current policy's values) with improvement (point the policy at the best ). Monte Carlo evaluation needs complete episodes, because the return is only known at the end. First-visit counting keeps one return per state-action pair per episode, the earliest one, so correlated repeats inside loopy episodes do not pose as fresh data.
Think of It Like This
The touring comic with a fixed experiment budget
A comic plays a hundred identical theater dates. The crowd paid for laughs, which argues for the proven set every night. But proven-only means the act fossilizes, and the televised special needs new killers. Teleporting into the middle of an untested bit is not an option: every show starts at the same microphone check.
So the comic fixes a budget: 85 percent proven closers, 15 percent notebook experiments, every single night. A new bit that bombs tanks its own average on the spot, because the comic is sampling on-policy and feels the silence. A bit that erupts climbs the ranking and displaces an old closer within a week.
Where it stops: the comic drops the experiment budget to zero for the special. A fixed-epsilon agent never does. It keeps testing 15 percent of the time forever, which means it converges to the best stay-curious policy, not the best act it ever found.
How It Actually Works
An -soft policy satisfies for every state and action. The -greedy version piles the remaining mass on the current best action :
Improvement is safe inside this family. If is -greedy in , a short argument shows at every state: the uniform exploration baseline cancels out of both sides, and no weighted average can beat the maximum it is averaged against. The policy improvement theorem then gives everywhere. Each update either gains or holds still, and stillness means optimal among -soft policies.
The loop per episode: roll one trajectory under , walk it backward accumulating , and on the first visit of each pair update , then re-greedy the policy at that state.
Worked example
State has three actions, , . The exploration share per action is , so the greedy action holds . Current table: with 4 visits, with 2 visits, with 1 visit. Greedy action is at 0.80.
This episode an exploration roll picks at , then collects rewards 1, 4, 10. Walking backward:
Pair appears once, so its first visit counts: visits , and . Now , the greedy action flips to , and the 0.80 mass moves with it: , . One lucky exploration found a better action and the policy followed the evidence the same episode.
Code
These two helpers replay the episode arithmetic above:
def backward_returns(rewards: list[float], gamma: float = 0.9) -> list[float]: """Discounted return from each step, computed back to front.""" running = 0.0 out: list[float] = [] for reward in reversed(rewards): running = reward + gamma * running out.append(round(running, 2)) out.reverse() return out
def update_q(old_q: float, visits: int, new_return: float) -> tuple[int, float]: """First-visit incremental mean update for one state-action pair.""" visits = visits + 1 return visits, round(old_q + (new_return - old_q) / visits, 2)
print(backward_returns([1.0, 4.0, 10.0])) # -> [12.7, 13.0, 10.0]print(update_q(1.0, 2, 12.7)) # -> (3, 4.9)The returns match the hand walk, and the update lands exactly on 4.9 with 3 visits.
Watch Out For
A fixed epsilon never reaches the deterministic optimum
This method converges to the best -soft policy, not the best policy. With the agent keeps playing a random action 30 percent of the time at every state, forever, including states where a mistake is expensive. Near a cliff edge it learns a wide detour, because its values correctly price in its own future randomness.
If you need the deterministic optimum, anneal toward zero across episodes so exploration dies out, or switch to an off-policy method where the behavior stays curious and the target goes fully greedy.
Updating every visit leaks correlated returns
Inside one loopy episode the same pair can appear three times with three overlapping returns. Updating on all three treats one episode as three independent samples and biases early values, because the later returns contain the earlier ones. The backward walk must check each step against the pair's first-visit index and skip the repeats.
Record first-visit positions on the way forward, then gate the update on the way back. If your values oscillate in mazes but behave in hallways, a missing first-visit gate is the first suspect.
The Quick Version
- Epsilon-soft policies give every action at least probability, so all pairs get sampled without staged exploring starts.
- The method is on-policy throughout: it evaluates and improves the same -greedy policy that gathers the episodes.
- Epsilon-greedy improvement cannot lose value: each step moves to the best -soft policy or stays optimal.
- Returns accumulate backward per episode and update once per pair at its first visit; here 12.7 takes from 1.0 to 4.9 and flips the greedy action.
- A fixed epsilon converges below the deterministic optimum, so anneal it when the final policy must stop exploring.