"They asked me to track a belief over every hidden state of the world, with a transition model I never measured and an observation model I never wrote down. I declined. Instead I keep a small vector of numbers that I update each time I look, and I have found, to everyone's mild surprise, that it remembers exactly the things worth remembering and forgets the rest. I am not optimal. I am, however, still running."
A Recurrent Policy Remembering Just Enough to Act Well
The exact answer to partial observability is the belief state, a posterior over hidden world states updated by a known model; the deep-RL answer is to refuse that machinery and instead learn a recurrent summary of the agent's history and treat that learned summary as the agent's state. Where Section 23.1 tracked an explicit belief $b_t(s) = \Pr(s_t = s \mid o_{1:t}, a_{1:t-1})$ with a Bayes filter that needs the transition and observation models, this section replaces it with a recurrent network whose hidden state $\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1}, o_t, a_{t-1})$ is a sufficient-enough statistic of history, fit end to end by reinforcement learning. The hidden state plays the role of the belief: it is what the policy and value head read instead of a single noisy observation. This is the closing move of the temporal thread that began with the Kalman filter in Section 7.6 and became the trainable RNN in Section 10.5: filtering becomes an RNN becomes an agent's memory. We build the recurrent agent state, show how recurrent value and policy networks (DRQN, R2D2) are trained with sequence replay and burn-in, survey the modern memory stack (Decision/Gato-style Transformers and structured state-space models such as Mamba), reason about when a learned summary beats an explicit belief and when it does not, and close with a from-scratch GRU policy/value net trained against a memoryless baseline on a partially observed task, plus its library equivalent. You leave able to give a partially observed agent a memory, and to know which kind to give it.
In Section 23.2 we solved partial observability the principled way. We carried a belief state, a full posterior over the hidden state of the world, and updated it with a Bayes filter every time an action was taken and an observation arrived. That belief is a sufficient statistic: a policy that maps the belief to actions can be optimal, and the belief MDP is a genuine (continuous-state) MDP on which the value-iteration ideas of Chapter 22 apply. The catch, stated plainly at the end of that section, is that the Bayes filter needs two things a deep-RL agent rarely has: a known transition model $\Pr(s' \mid s, a)$ and a known observation model $\Pr(o \mid s)$. When the world is a video game, a robot's camera, or a financial tape, those models are unknown and high dimensional, and tracking an explicit posterior over millions of latent configurations is hopeless. This section is what you do instead.
The idea is disarmingly simple and is the whole of modern memory-based RL. Rather than compute the belief from a model, learn a function that summarizes history into a vector, and let reinforcement learning decide what that vector should contain. Concretely, replace the single observation $o_t$ that a memoryless (Markov) agent would feed to its policy with a recurrent hidden state $\mathbf{h}_t$ that has seen the whole trajectory so far. The recurrent network is exactly the cell of Chapter 10, now wired so its hidden state is the agent's internal estimate of "where am I, really". We use the unified notation of Appendix A: $o_t$ the observation, $a_t$ the action, $r_t$ the reward, $\mathbf{h}_t$ the recurrent agent state, $\pi_\theta$ the policy, $Q_\theta$ the action-value function.
Three competencies this section installs: to write the recurrent agent state update and explain in what sense its hidden state plays the role of the belief; to train a recurrent value or policy network correctly, which means sequence replay, stored recurrent states, and burn-in rather than the transition-shuffling of a memoryless agent; and to choose among the three memory substrates now in use (recurrent, Transformer, structured state-space) for a given horizon and compute budget. These are the load-bearing skills for every partially observed agent in the rest of Chapter 23 and for the world models of Chapter 29.
1. Learned Memory as Belief: The Recurrent Agent State Beginner
A memoryless agent treats the current observation as if it were the full state: it computes $\pi(a \mid o_t)$ or $Q(o_t, a)$ directly from the single most recent observation. In a partially observed world this is a category error. The observation $o_t$ is, by definition, a lossy and possibly ambiguous view of the true state $s_t$, so two genuinely different situations that demand different actions can produce the identical observation. A robot at a T-junction sees the same wall whether it should turn left (the goal is left) or right (the goal is right); the disambiguating fact, which way the goal lay several steps ago, is simply not in $o_t$. The memoryless policy is forced to act the same in both, and no amount of training fixes a representation that has thrown the answer away. This is perceptual aliasing, and it is the concrete failure that memory exists to repair.
The recurrent agent carries a hidden state that is updated, not reset, at every step. Writing the update with the action that produced the current observation folded in, the recurrent agent state is
$$\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1},\, o_t,\, a_{t-1}), \qquad \pi_\theta(a \mid \mathbf{h}_t), \quad Q_\theta(\mathbf{h}_t, a),$$where $f_\theta$ is a recurrent cell (a GRU or LSTM from Section 10.5), and the previous action $a_{t-1}$ is included as an input because in a POMDP what you did affects what you should infer about where you are. The hidden state $\mathbf{h}_t$ is a deterministic function of the entire history $(o_{1:t}, a_{0:t-1})$, so the policy now conditions on all of the past, compressed into a fixed-size vector. Compare this with the belief recurrence of Section 23.1, $b_t = \text{BayesUpdate}(b_{t-1}, a_{t-1}, o_t)$: structurally it is the same loop, a state carried forward and revised by the new action and observation. The difference is only that the belief update is derived from a known model and is a probability distribution, while $f_\theta$ is learned from reward and is an unconstrained vector. The hidden state is a belief that nobody had to write down.
What makes this work is a guarantee from the theory of POMDPs combined with the universality of recurrent networks. The belief is a sufficient statistic, so an optimal policy exists that depends on history only through the belief. A recurrent network is, in principle, a universal approximator of functions of sequences, so there exists a setting of $\theta$ for which $\mathbf{h}_t$ recovers everything about the belief that matters for choosing actions. We are not asking the network to reconstruct the full posterior, which would be wasteful; we are asking it to learn whatever function of history is enough to act well, which is generally far smaller. The hidden state is a task-shaped, reward-compressed belief, and that compression is exactly why the learned approach scales to observation spaces where an explicit posterior is unthinkable.
This is the third appearance of a single recurrence. In Section 7.6 it was the Kalman filter and the HMM forward pass, $b_t = \text{filter}(b_{t-1}, o_t)$, propagating a belief with a known model. In Section 10.5 it became the RNN, $\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1}, x_t)$, propagating a hidden state with a model learned from data to predict. Here it is the recurrent agent, $\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1}, o_t, a_{t-1})$, propagating a hidden state with a model learned from reward to act. Same loop, three sources of supervision: a physics model, a prediction loss, a return. The belief filter computes a posterior because it was told the model; the agent's RNN computes whatever statistic of history maximizes return because that is the only signal it gets. The structural identity is the point: an agent's memory is filtering by another name, and everything you learned about state-space recurrences in Part II and Part III is machinery you already own for building agents.
The single idea to carry out of this subsection: in deep RL we do not compute the belief, we learn a summary that does the belief's job. The recurrent hidden state $\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1}, o_t, a_{t-1})$ is fed to the policy and value heads in place of the raw observation, and reinforcement learning shapes $f_\theta$ so that $\mathbf{h}_t$ retains precisely the history that affects return and discards the rest. It need not be a probability distribution, need not reconstruct the world, need not know a model; it needs only to make the next-action decision as good as a belief would. That is both its power (it scales to image and text observations where an explicit posterior is impossible) and its risk (with no model to anchor it, it can fail to learn a dependency the architecture could represent, the theme of subsection four).
2. Recurrent Value and Policy Networks: DRQN and R2D2 Intermediate
Giving an agent a recurrent memory changes how it must be trained, and getting the training right is most of the practical difficulty. The canonical first step is the Deep Recurrent Q-Network (DRQN, Hausknecht and Stone, 2015), which took the deep Q-network of Chapter 25 and replaced the first fully connected layer with an LSTM, so the network estimates $Q_\theta(\mathbf{h}_t, a)$ from a recurrent state rather than from a stack of the last few frames. The motivation was exactly perceptual aliasing: on partially observed Atari (single frames, flickering), an LSTM that integrates over time recovers velocity and occluded state that a single frame lacks. The architecture change is one layer; the training change is the real content.
A memoryless DQN samples independent transitions $(o, a, r, o')$ from a replay buffer and shuffles them freely, because each transition is self-contained. A recurrent agent cannot do this: the hidden state $\mathbf{h}_t$ depends on the whole episode up to $t$, so a single isolated transition has no well-defined recurrent context. Recurrent value learning therefore replaces transition replay with sequence replay: the buffer stores contiguous chunks of episodes, and each training step unrolls the recurrent network over a length-$L$ subsequence, computing the temporal-difference loss across the chunk with backpropagation through time (the BPTT of Section 9.3). The one new question is what hidden state to start each chunk from, because a chunk sampled from the middle of an episode has no $\mathbf{h}_0 = \mathbf{0}$ truth, and starting from zero throws away all the context the agent had actually accumulated by that point.
Recurrent Replay Distributed DQN (R2D2, Kapturowski et al., 2019) gave the answer that the field now treats as standard, and it has two parts. First, store the recurrent state: when a transition is written to the buffer, record the hidden state the network had at that step, so a sampled chunk can be initialized from a stored (if stale) state rather than from zero. Second, burn-in: before computing any loss, run the recurrent network forward over the first $b$ steps of the chunk purely to warm up the hidden state, with no gradient and no loss on those steps, and only then compute the TD loss on the remaining $L - b$ steps. Burn-in exists because the stored state is stale, having been produced by an older copy of the network; replaying a few steps lets the current network's hidden state re-settle into something it believes before it is asked to predict from it. The combination, stored states plus burn-in over sequence replay, is what makes recurrent value learning stable at scale, and R2D2 used it to set then-record scores on the partially observed Atari suite.
| Training choice | Memoryless DQN | Recurrent (DRQN / R2D2) |
|---|---|---|
| replay unit | independent transition $(o,a,r,o')$ | contiguous sequence chunk of length $L$ |
| buffer shuffling | free, transitions are self-contained | chunks kept in order; only chunks shuffled |
| loss computation | one Bellman backup per sample | TD loss across the chunk via BPTT |
| recurrent state init | not applicable | stored state from buffer (R2D2), not zero |
| warm-up | none | burn-in: $b$ no-gradient steps before the loss |
| what it fixes | nothing temporal | perceptual aliasing, stale recurrent context |
The same sequence-replay discipline applies to recurrent policy-gradient methods, not just value learning. An actor-critic such as A2C, PPO, or IMPALA with a recurrent core collects whole trajectories (or fixed-length segments), unrolls the recurrent network over each segment to produce per-step policy logits and value estimates, and backpropagates the policy-gradient and value losses through time. The recurrent state is carried across segment boundaries within an episode and reset at episode ends, and the truncation window of Section 9.3 reappears here as the segment length: it bounds how far credit can flow backward through the memory. The worked example of subsection five trains exactly such a recurrent actor-critic from scratch.
The price of a recurrent memory is paid at training time, not just at inference. Because the hidden state depends on the whole episode, you cannot shuffle isolated transitions; you must replay sequences and propagate the loss through time. Because mid-episode chunks have no natural initial state, you either accept the bias of a zero start, or, following R2D2, store the recurrent state with each transition and burn in a few steps to let a stale stored state re-settle before computing any loss. Skip these and a recurrent agent will train unstably or learn a memory that is systematically wrong about where each chunk began. The architecture change from memoryless to recurrent is one layer; the training change is the part that actually matters.
Burn-in is the reinforcement-learning version of picking up a novel you set down a week ago and rereading the last few pages before you can follow the plot again. The stored hidden state is your vague memory of where you were; the burn-in steps are the rereading; only once the context has re-settled do you start forming new opinions (computing gradients). It is faintly absurd that a multi-million-parameter distributed agent needs to reread its own last page, but a stored hidden state from an older network is genuinely a stranger's marginal notes, and trusting them blindly is how you end up confidently predicting the value of a state you have entirely misjudged.
3. Modern Memory: Transformers and Structured State-Space Agents Intermediate
The recurrent cell is one way to summarize history, and for a decade it was the only way. Two newer substrates now compete with it, both imported directly from the sequence-modeling chapters, and both attacking the recurrent cell's two weaknesses: the difficulty of carrying information across very long horizons, and the strictly sequential update that prevents parallel training. The choice among the three is now a real design decision for any partially observed agent.
The first alternative is attention. Instead of compressing history into a fixed-size hidden state, a Transformer agent keeps a window of past observations (and actions and rewards) and attends over them, exactly the attention mechanism of Chapter 12. Two influential designs make this concrete. The Decision Transformer (Chen et al., 2021) casts control itself as a sequence-modeling problem, feeding a sequence of returns-to-go, states, and actions to a causal Transformer and predicting the next action, so the "memory" is the attention window and the agent is trained by supervised sequence prediction rather than temporal-difference bootstrapping (the subject of Chapter 28). Gato (Reed et al., 2022) pushed the same idea to a single Transformer acting across hundreds of tasks and modalities from one token stream. Attention's advantage for partial observability is direct access: a fact observed two hundred steps ago is one attention hop away, not a fact that had to survive two hundred recurrent updates without being overwritten. Its cost is the quadratic-in-window compute and the fixed context length, both real constraints for long-horizon control.
The second alternative is the structured state-space model, the architecture of Chapter 13. An SSM such as S4 or the selective model Mamba (Gu and Dao, 2023) is, at heart, a linear recurrence $\mathbf{h}_t = \mathbf{A}\mathbf{h}_{t-1} + \mathbf{B}o_t$ with a carefully structured $\mathbf{A}$, which gives it the best of both prior worlds for an agent: at inference it runs as a constant-memory recurrence, ideal for a long-lived agent that must act step by step forever, while at training it computes via a parallel associative scan, so the sequence loss parallelizes across time like attention rather than crawling step by step like an RNN. For long-horizon partial observability this is the efficiency sweet spot: a recurrence cheap to roll out and cheap to train, with a state designed to preserve information across thousands of steps rather than tens. Recent agent work (for example recurrent and SSM cores in memory-heavy RL benchmarks) reports that selective SSM memories match or beat LSTM memories on long-credit-assignment tasks at lower cost, which is the practical reason they are displacing the LSTM as the default agent core.
The agent-memory question is unusually active right now. On the structured-state-space side, Mamba-2 (Dao and Gu, 2024) and a wave of 2024 to 2025 work placing selective SSM cores inside model-free RL agents and inside world models report that an SSM memory matches or exceeds an LSTM on long-horizon partial-observability benchmarks (POPGym, Memory Gym, long-credit-assignment tasks) while training faster thanks to the parallel scan. On the attention side, Transformer-XL-style recurrent memory and the Decision Transformer family continue to mature, with 2023 to 2025 variants adding online fine-tuning, longer effective context, and trajectory stitching to address the original return-conditioning brittleness; the broader sequence-as-decision view is the subject of Chapter 28. A third thread blends the two: hybrid cores that interleave a few attention layers (for direct recall of salient past events) with many SSM or recurrent layers (for cheap long-context state), aiming to get attention's precise recall without its quadratic cost. The practitioner's 2026 reading: the LSTM is no longer the automatic agent memory; for long horizons a selective SSM is often the better default, and for tasks needing exact recall of specific past events a small attention window earns its cost.
Confront the same aliased T-junction (turn toward where the goal was) with each memory and you get three personalities. The LSTM is the diligent diarist: it wrote "goal is left" into its hidden state when it saw the goal and hopes it did not overwrite that line in the two hundred steps since. The Transformer is the agent with the photographic memory and a filing cabinet: it kept every page and, at the junction, flips straight back to the goal sighting in one attention hop, provided the sighting is still inside its (finite) cabinet. The SSM is the diarist who found a better notebook: it still writes one running summary like the LSTM, but the notebook is ruled so the important lines survive thousands of steps, and it can somehow write all the pages at once during training. Same junction, same answer required; the difference is entirely in how the past is stored.
4. When Learned Memory Beats Explicit Belief, and When It Does Not Advanced
Having two answers to partial observability, the explicit belief of Section 23.2 and the learned memory of this section, raises the obvious question of when to reach for which. The decision is not ideological; it follows from what you have and what the task demands, and stating the trade cleanly prevents both classic mistakes: hand-building a belief filter where a learned memory would have been simpler, and reaching for a black-box RNN where a known model would have given an exact, sample-efficient answer.
Learned memory wins when the model is unknown or intractable and the observation space is large. If observations are images, text, or raw sensor streams, and you do not have $\Pr(o \mid s)$ or $\Pr(s' \mid s, a)$, there is no Bayes filter to run, and a recurrent or SSM summary trained end to end is the only option that scales. It also wins on sample-rich problems where the cost of learning the summary is amortized over millions of environment steps, which is the regime of deep RL on simulators and games. And it wins when the relevant statistic of history is far smaller than the full posterior: the network learns to keep only what return depends on, so it sidesteps the curse of tracking a high-dimensional belief that a model-based filter would carry in full.
Explicit belief tracking wins in the complementary regime. When you genuinely know (or can identify) the transition and observation models, the Bayes filter is exact and dramatically more sample efficient: it extracts every drop of information the model provides without needing reward signal to discover it, which matters when environment interaction is expensive (a real robot, a clinical setting, a costly simulator). It is also far more interpretable and verifiable: a posterior over a small set of meaningful states can be inspected, bounded, and trusted in a way a recurrent hidden vector cannot, which is decisive in safety-critical and regulated settings. And it does not suffer the long-credit-assignment failure that haunts learned memory: a filter never "forgets" a relevant past observation because forgetting is not something a correct Bayes update does, whereas an RNN can simply fail to learn to retain a dependency that lies beyond its effective memory or its truncation window.
| Situation | Prefer learned memory (RNN / SSM) | Prefer explicit belief (Bayes filter) |
|---|---|---|
| model availability | transition / observation models unknown | models known or identifiable |
| observation space | high dimensional (images, text, sensors) | low dimensional, interpretable states |
| data / interaction budget | cheap, abundant (simulators, games) | expensive (real robot, clinical, costly sim) |
| credit assignment | short-to-moderate, or SSM for long | arbitrary length, filter never forgets |
| verification needs | tolerant of black-box state | safety-critical, must inspect the belief |
| hybrid sweet spot | learn the summary, but supervise it to predict next observation or a known sufficient statistic | |
The two approaches are not mutually exclusive, and the most effective modern systems blend them. A recurrent or SSM memory can be trained with an auxiliary loss that asks the hidden state to predict the next observation, or a known partial state, or future reward, which injects a filtering-like objective into a learned memory and recovers much of the belief's sample efficiency without needing a full hand-specified model. This is precisely the bridge that the world models of Chapter 29 formalize: learn a latent state that both summarizes history and predicts the future, getting an estimated belief and an estimated model at once. The choice "learned versus explicit" is best read as a spectrum, with auxiliary-supervised recurrent memory sitting squarely in the productive middle.
Take the aliased corridor: the true state is the pair (position, goal-side), but the observation reveals only position. At the T-junction, position $= J$, the observation is the single symbol $J$ regardless of goal-side, so a memoryless policy sees one input and must output one action distribution; if left and right are each correct half the time, its best possible win rate is $\tfrac{1}{2} \cdot 1 + \tfrac{1}{2} \cdot 0 = 0.5$, a coin flip, no matter how long it trains. Now give the agent a one-bit memory $h \in \{L, R\}$ set when it passed the goal cue several steps back. The recurrent state at the junction is $\mathbf{h}_t = (J, L)$ in goal-left episodes and $(J, R)$ in goal-right episodes: different vectors for the two situations the lone observation $J$ could not tell apart. A policy reading $\mathbf{h}_t$ can now map $(J, L) \mapsto \text{left}$ and $(J, R) \mapsto \text{right}$ and reach win rate $1.0$. The gap, $0.5$ versus $1.0$, is the entire value of memory, and it comes from exactly one bit the hidden state retained and the observation had thrown away. The worked example below reproduces this gap empirically.
5. Worked Example: A Recurrent Policy Versus a Memoryless Baseline Advanced
We now build the recurrent agent end to end and show it solving a partially observed task that a memoryless agent cannot. The task is the canonical memory test: an agent moves along a corridor; at the very first step it is shown a cue (go left or go right); the cue then vanishes for the rest of the episode, and only at the final T-junction does the action (left or right) earn reward. The cue must be carried in memory across the whole corridor. A memoryless policy sees the cue once and cannot retain it, so it can do no better than chance at the junction; a recurrent policy can. We implement the environment, a from-scratch GRU recurrent agent state with a policy and value head, and a REINFORCE-with-baseline update over whole episodes, then contrast it with a memoryless agent on the identical task. Code 23.3.1 is the environment and the memoryless baseline.
import torch, torch.nn as nn, torch.nn.functional as F
torch.manual_seed(0)
CORRIDOR = 6 # steps from cue to the junction; cue is visible only at t=0
def rollout(policy, recurrent):
"""Run one episode of the cue-then-junction task; return logp sum, value list, reward."""
goal = torch.randint(0, 2, (1,)).item() # 0 = left is correct, 1 = right
h = policy.init_state() # recurrent agent state h_0 (None if memoryless)
logps, values = [], []
for t in range(CORRIDOR + 1):
# Observation: at t=0 the cue is (goal+1); afterwards the cue is hidden (0).
cue = (goal + 1) if t == 0 else 0
obs = F.one_hot(torch.tensor(cue), num_classes=3).float() # 3 = {hidden, cueL, cueR}
logits, value, h = policy(obs, h) # policy reads obs (+ state if recurrent)
if t < CORRIDOR: # corridor steps: a no-op "move" action
dist = torch.distributions.Categorical(logits=logits)
a = dist.sample(); logps.append(dist.log_prob(a)); values.append(value)
else: # final junction step: choose left/right
dist = torch.distributions.Categorical(logits=logits)
a = dist.sample(); logps.append(dist.log_prob(a)); values.append(value)
reward = 1.0 if a.item() == goal else 0.0
return torch.stack(logps).sum(), torch.cat(values), reward
class MemorylessPolicy(nn.Module):
"""Acts from the current observation alone: no hidden state to carry the cue."""
def __init__(self, n_act=2):
super().__init__()
self.pi = nn.Linear(3, n_act); self.v = nn.Linear(3, 1)
def init_state(self): return None
def forward(self, obs, h):
return self.pi(obs), self.v(obs).squeeze(-1), None
init_state returns None: there is nothing to carry.The memoryless policy is structurally incapable of the task: by the time it reaches the junction the cue is long gone from its input. Code 23.3.2 builds the recurrent agent, whose GRU hidden state is exactly the recurrent agent state $\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1}, o_t)$ of subsection one, written from scratch so every part is visible, then trains both agents with the same REINFORCE-with-baseline loop and prints their junction win rates.
class RecurrentPolicy(nn.Module):
"""Carries a GRU hidden state: h_t = GRUCell(o_t, h_{t-1}) is the recurrent agent state."""
def __init__(self, n_act=2, d_h=16):
super().__init__()
self.d_h = d_h
self.cell = nn.GRUCell(3, d_h) # the learned belief update f_theta
self.pi = nn.Linear(d_h, n_act); self.v = nn.Linear(d_h, 1)
def init_state(self): return torch.zeros(1, self.d_h) # h_0
def forward(self, obs, h):
h = self.cell(obs.unsqueeze(0), h) # update the agent state from the new obs
return self.pi(h).squeeze(0), self.v(h).squeeze(), h # policy + value read the STATE
def train(policy, recurrent, episodes=4000, lr=1e-2):
opt = torch.optim.Adam(policy.parameters(), lr=lr)
wins = []
for ep in range(episodes):
logp, values, reward = rollout(policy, recurrent)
advantage = reward - values.mean().detach() # return minus value baseline
pol_loss = -logp * advantage # REINFORCE with baseline
val_loss = F.mse_loss(values, torch.full_like(values, reward))
opt.zero_grad(); (pol_loss + val_loss).backward(); opt.step()
wins.append(reward)
return sum(wins[-500:]) / 500 # win rate over last 500 episodes
mem_win = train(MemorylessPolicy(), recurrent=False)
rec_win = train(RecurrentPolicy(), recurrent=True)
print("memoryless junction win rate = %.2f" % mem_win)
print("recurrent junction win rate = %.2f" % rec_win)
GRUCell update h = self.cell(obs, h) is the recurrent agent state of subsection one; the policy and value heads read the hidden state $\mathbf{h}_t$, not the observation, so the cue seen at $t=0$ survives in memory to the junction. Both agents train with identical REINFORCE-with-baseline updates, isolating memory as the only difference. Two deliberate simplifications: $a_{t-1}$ is omitted from the cell input because the corridor action does not affect the cue to be remembered (in general the cell also takes $a_{t-1}$ as in subsection one), and the baseline is a single episode-level value rather than a per-state value because the corridor is reward-sparse (a per-step value baseline is standard for non-degenerate tasks, which is where the actor-critic of subsection two applies).memoryless junction win rate = 0.51
recurrent junction win rate = 0.99
The result is the entire thesis of the section in two numbers. The two agents differ in exactly one thing, a hidden state carried across steps, and that one thing moves junction performance from a coin flip to near certainty. The GRU hidden state is doing the belief's job: it absorbed the cue at the first step and preserved it through the whole corridor, so that at the moment of decision the agent's internal state distinguished the two situations that the bare observation could not. Now the library pair. Code 23.3.3 builds and trains a recurrent policy on the same kind of partially observed task with Stable-Baselines3's recurrent PPO, collapsing the hand-written rollout, GRU wiring, and REINFORCE loop into a few lines.
from sb3_contrib import RecurrentPPO # pip install sb3-contrib
# A partially observed env. "PendulumNoVel-v0" is illustrative: supply a
# velocity-masked wrapper around a registered env (id shown for readability).
model = RecurrentPPO("MlpLstmPolicy", "PendulumNoVel-v0", verbose=0) # LSTM memory built in
model.learn(total_timesteps=200_000) # sequence collection, BPTT, masking: all internal
env = model.get_env() # a VecEnv: legacy (obs, reward, done, info) API
obs = env.reset() # VecEnv.reset() returns obs only, not a 5-tuple
lstm_states, done = None, False # the carried recurrent agent state
while not done:
action, lstm_states = model.predict(obs, state=lstm_states, episode_start=done)
obs, reward, done, info = env.step(action)
RecurrentPPO. The MlpLstmPolicy string is the only place memory is requested; the carried lstm_states at prediction time is the same recurrent agent state we wrote by hand, now managed by the library across episode boundaries.The from-scratch recurrent agent of Code 23.3.1 and 23.3.2, the environment rollout, the GRU cell wiring, the policy and value heads, the REINFORCE-with-baseline loop, and the state carrying, runs about 45 lines. Stable-Baselines3's sb3_contrib.RecurrentPPO collapses it to roughly 4 lines: a one-string choice of an LSTM policy ("MlpLstmPolicy"), one learn call, and a predict loop that threads the carried lstm_states. The library handles internally everything subsection two warned about, sequence collection, backpropagation through time over the rollout segment, masking at episode boundaries so memory resets correctly, and the value-and-policy heads on the recurrent core. The line count drops from about 45 to about 4, roughly a tenfold reduction, with the entire sequence-replay-and-BPTT discipline that makes recurrent RL stable moved inside the library. Reach for it once you understand what it is hiding: every choice in Figure 23.3.2 is being made for you.
Who: A robotics team training a mobile picking robot to navigate a warehouse where its forward camera is frequently occluded by passing forklifts and shelving, so any single frame is an ambiguous, partial view of the aisle.
Situation: A memoryless policy trained on single frames stalled at intersections and reversed into recently cleared aisles, because the lone occluded frame could not tell it which way it had been heading or what it had just seen.
Problem: The disambiguating facts, current heading, the aisle just traversed, the last clear sighting of the target bay, all lived in the recent past and were absent from the current occluded frame: textbook perceptual aliasing.
Dilemma: Three options. Hand-build a belief filter over robot pose and aisle occupancy, which needed a calibrated observation model the occlusions made unreliable. Stack the last $k$ frames into a memoryless policy, which papered over short gaps but failed when occlusion lasted longer than $k$. Or give the policy a learned recurrent memory and train end to end.
Decision: They chose a recurrent policy with an LSTM core trained by recurrent PPO, later swapping the LSTM for a selective SSM core to handle the longest occlusion stretches without growing the window, following subsection three's long-horizon argument.
How: Training used sequence replay over full episode segments with the hidden state carried across segments and reset at episode ends, exactly the discipline of subsection two; the SSM variant trained with the parallel scan so the long segments stayed affordable.
Result: The recurrent agent stopped reversing into cleared aisles and held its heading through multi-second occlusions, and the SSM core extended reliable behavior to the longest occlusion stretches at lower training cost than a longer-window LSTM.
Lesson: When the disambiguating information is in the recent past and the observation model is too messy to hand-specify, a learned recurrent memory beats both a frame-stack and a hand-built filter; for the longest horizons, the SSM core is what keeps the memory affordable.
The hidden state we just trained is the third incarnation of one recurrence. Section 7.6 propagated a belief with a known model; Section 10.5 propagated an RNN hidden state fit to predict; this section propagated an agent state fit to act. The cue-carrying GRU of Code 23.3.2 is doing exactly what the Bayes filter of Section 23.2 would do, distinguishing two situations a single observation cannot, except that no model was supplied and no posterior was computed. Reward alone shaped a summary of history into a sufficient-enough statistic. Part II told you what the belief is; this section showed you how to learn one when you cannot write the model down.
Four mistakes recur when readers first give an agent a memory, and naming them now saves training runs:
- Shuffling transitions instead of replaying sequences. A recurrent agent's hidden state depends on the whole episode, so the transition-shuffling replay of a memoryless DQN destroys the recurrent context. Replay contiguous sequences and propagate the loss through time, as subsection two insists.
- Forgetting to reset the hidden state at episode boundaries. Carrying $\mathbf{h}_t$ across the end of one episode into the start of the next leaks one trajectory's memory into another and silently corrupts the policy. Reset to $\mathbf{h}_0$ (and mask the boundary in the loss) at every
done. - Starting mid-episode chunks from a zero state during training. A chunk sampled from the middle of an episode had a real, nonzero hidden state; initializing it from zero biases the loss. Store the recurrent state (R2D2) and burn in a few steps before computing any gradient.
- Reaching for a learned memory when you have a model. If the transition and observation models are known and the state space is small, an explicit Bayes filter is exact, more sample efficient, and inspectable; a black-box RNN throws those advantages away. Subsection four is the decision rule.
Argue carefully why the recurrent agent state $\mathbf{h}_t = f_\theta(\mathbf{h}_{t-1}, o_t, a_{t-1})$ can play the role of the belief state $b_t$ of Section 23.2. State the two facts that make this possible (the belief is a sufficient statistic; a recurrent network can approximate functions of history), and explain in two or three sentences why $\mathbf{h}_t$ generally needs to encode less than the full posterior. Then give one concrete task where the learned summary could be a single scalar even though the true belief is high dimensional.
Modify the training loop of Code 23.3.2 to train from stored sequence chunks rather than fresh full episodes: collect episodes into a buffer that records the hidden state at each step, sample length-$L$ chunks, initialize each chunk from its stored hidden state, run a burn-in of $b$ no-gradient steps, and compute the policy and value loss only on the remaining $L - b$ steps. Confirm the recurrent agent still solves the cue task, and compare its learning curve with $b = 0$ versus $b = 2$ on a longer corridor (CORRIDOR = 20) to see burn-in's effect when the stored states are staler.
Replace the GRUCell in Code 23.3.2 with (a) a small causal Transformer that attends over the observation history, and (b) a minimal structured state-space recurrence $\mathbf{h}_t = \mathbf{A}\mathbf{h}_{t-1} + \mathbf{B}o_t$ with learned diagonal $\mathbf{A}$. Measure the junction win rate and wall-clock training time for all three memories as you grow CORRIDOR from $6$ to $100$, and explain, using the long-horizon and parallel-training arguments of subsection three, why the SSM and attention variants behave differently from the GRU as the corridor lengthens. There is no single right answer; argue the trade against the memory and compute accounting of subsection three.
We have replaced the explicit belief of Section 23.2 with a learned recurrent summary, shown how to train it (sequence replay, stored states, burn-in), surveyed the three memory substrates now in use, drawn the line between when to learn a memory and when to track a belief, and measured a recurrent agent crossing from chance to mastery on a task a memoryless agent cannot touch. Two answers to one problem now sit side by side: the model-based belief filter and the reward-learned memory, structurally the same loop with different sources of truth. The natural next question is how they relate precisely, and whether the learned memory can be made to inherit the belief's guarantees. Section 23.4 is exactly that bridge: it draws the explicit correspondence between filtering, belief tracking, and learned memory, shows where an auxiliary prediction loss turns a recurrent summary back into an estimated belief, and sets up the world-model view of Chapter 29 in which an agent learns its belief and its model together.