Expected SARSA
Instead of gambling on a single randomly sampled next action, Expected SARSA takes the exact average value over all next actions, weighted by how likely each one is.
Why Does This Exist?
Temporal difference learning bootstraps: it updates a guess from another guess. SARSA builds its target from the exact next action the agent happened to sample:
Because is one random draw from an exploratory policy, this single sample injects noise into every update. Two identical visits to the same state can give wildly different targets: one step samples the good action, the next samples an exploratory blunder. To survive that noise you must shrink the learning rate, and learning crawls.
Q-learning dodges the noise by taking the greedy maximum, . But that assumes perfect future play. In a risky environment where the agent keeps exploring, Q-learning ignores its own future blunders and can march straight into penalties it should have priced in.
Expected SARSA takes the middle path that keeps the honesty without the noise. Instead of rolling the dice on one sampled action, compute the exact average over every next action, weighted by the policy:
One draw becomes an expectation. The sampling noise disappears, but the exploratory risk stays in the price.
The one idea you need first: an -greedy policy. With probability it picks the current best action, and with probability it picks uniformly at random. So the best action gets probability and every other action gets .
Think of It Like This
Three ways to grade a course
A course has safe assignments, dull busywork, and one brutal trap question.
The SARSA examiner rolls a die, picks one question, and awards that single score as your whole grade. Roll the safe one and you shine; roll the trap and you fail. Over infinite retakes the average is fair, but every single grade is a lottery ticket.
The Q-learning examiner assumes you answer only the easiest question, ignoring that the rules force you onto harder ones 10 percent of the time.
The Expected SARSA examiner opens the syllabus, multiplies each question by its exact probability, and assigns the weighted average. No dice. Every grade is smooth and predictable, and the trap question still drags the average down exactly as much as its probability warrants.
Where it stops: a syllabus is fixed, while in RL both the policy and the values shift as the agent learns, so the expectation must be recomputed at every step.
How It Actually Works
Write for the state, for the action taken, for the reward, and for where you land. The update is:
Here in is the step size, in discounts the future, and is the probability of each next action under the target policy. The sum is the expected next value, .
Why the variance vanishes
Condition on the transition . Standard SARSA's target varies with the sampled action, so whenever the policy gives positive probability to actions with different values, its variance is positive:
Expected SARSA replaces the draw with its mean, and a mean has no sampling variance:
Only environment noise remains (random transitions and rewards). Lower variance means you can run a larger without blowing up, which is why Expected SARSA converges faster than SARSA on tabular benchmarks.
One rule, two policies
Expected SARSA separates the behavior policy (what picks actions in the world) from the target policy (what the expectation uses). Set and you get on-policy control: with -greedy behavior the expectation is . Set to pure greedy (probability 1 on the best action) and the sum collapses to : that is exactly Q-learning, with no importance sampling correction needed on the next action.
Worked example: the cliff state
The agent takes action East from , lands in , and gets reward . Settings: , , current . State has three actions:
- (safe path): , the greedy action
- (detour):
- (cliff edge):
Behavior is -greedy with and : , , .
Expected SARSA first averages the next values:
Then the target, the error, and the update:
Compare. If SARSA samples the safe action: , so . If it samples the cliff: , so . Q-learning always takes the max: and . SARSA swings between and on pure dice luck, Q-learning prices the cliff at zero despite a 10 percent fall chance, and Expected SARSA lands once, deterministically, at .
Code
A pure-Python transcription of the worked example, with all three updates side by side.
q_next = [20.0, 10.0, -100.0]probs = [0.8, 0.1, 0.1]reward = -1.0gamma = 0.9alpha = 0.5q_current = 2.0
expected = sum(p * q for p, q in zip(probs, q_next))target = reward + gamma * expectedupdated = q_current + alpha * (target - q_current)
sarsa_safe = q_current + alpha * ((reward + gamma * q_next[0]) - q_current)sarsa_cliff = q_current + alpha * ((reward + gamma * q_next[2]) - q_current)qlearn = q_current + alpha * ((reward + gamma * max(q_next)) - q_current)
print(round(expected, 2)) # -> 7.0print(round(target, 2)) # -> 5.3print(round(updated, 2)) # -> 3.65print(round(sarsa_safe, 2)) # -> 9.5print(round(sarsa_cliff, 2)) # -> -44.5print(round(qlearn, 2)) # -> 9.5Watch Out For
Paying full price for the expectation in huge action spaces
SARSA does one array lookup per step and Q-learning does one max scan, but Expected SARSA evaluates the full dot product over every action on every transition. With 4 to 20 actions that is trivial and the variance win pays immediately. With hundreds of thousands of discrete actions, say a recommender, the dot product becomes the bottleneck. In continuous spaces the integral has no closed form at all.
The fix: under -greedy policies, split the sum into in one vectorized pass instead of building the probability vector. For massive spaces, sample actions to approximate the mean: most of the variance win at a fraction of the cost.
Writing one policy and pricing another
The expectation follows the target policy you wrote, not the behavior you ran. Plug the greedy distribution into the sum while the agent acts -greedy and you are doing Q-learning wearing an Expected SARSA costume, cliff blindness included. Plug the exploratory distribution in while intending to evaluate the greedy policy and you learn a pessimistic value for a policy you never deploy.
The fix: name both policies at the top of your loop and assert which is which. On-policy means the probabilities in the sum match the policy that picked the actions. Any mismatch is off-policy by definition, and then you should say so and check whether the resulting optimism is safe in your environment.
The Quick Version
- Expected SARSA replaces the single sampled next action with the policy-weighted mean .
- Killing action-sampling variance lets it train stably with larger step sizes than standard SARSA.
- The cliff example averages 20, 10 and with weights 0.8, 0.1 and 0.1 to get 7.0, and updates to in one deterministic step.
- Setting the target policy to greedy reproduces Q-learning exactly, with no importance sampling correction.
- The price is a full pass over the action set per step, so huge or continuous action spaces need the split-sum trick or a sampled approximation.