Goal-Conditioned Reinforcement Learning
One policy learns many goals at once by taking the target as input. The same network walks to any destination instead of retraining per address.
Why Does This Exist?
A fixed policy bakes in one destination. Move the target and it fails, even when the physics did not change. Training one network per goal ignores shared structure and scales badly.
Goal conditioned RL feeds the goal into policy and value , after Kaelbling and UVFA work by Schaul and coauthors. One net then serves many tasks, failures can be relabeled as wins for the place actually reached in hindsight experience replay, and higher levels in hierarchical RL can command subgoals through the same interface.
The one idea you need first
A goal space lists possible targets, often a subset of states via map . Reward is usually sparse: when close enough to , otherwise. Sparse keeps shortest path incentives clean where dense distance can trap the agent behind walls.
Think of It Like This
A GPS unit, not a fixed commute
A fixed commuter only knows office to home. Ask for the airport and it blanks. A GPS takes current position plus destination and gives turn by turn moves for any pair.
The value is travel time between any two pins. Miss an exit and it recomputes from the new state. Reach the wrong lot and it still learned that route, which hindsight later reuses.
Where it stops: a GPS starts with a surveyed map. The agent starts with none and learns distances by trial.
How It Actually Works
Inputs are state and goal . Two builds exist. Joint concat runs through one MLP for . Factored build encodes and separately and dots them for , which helps lookup across many goals.
Bellman holds per goal:
In words: immediate goal reward plus discounted best future value for the same . Replay stores and minimizes TD error across sampled goals.
Worked example
Stand at , target , , step penalty , terminal . North goes to with steps left; south goes to with steps left.
Optimal remaining value for steps of is . So gives . And gives .
Bellman Q adds one penalty step:
Since beats , the policy picks north toward the goal.
Code
Same choice in code:
import numpy as np
def remaining_value(steps: int, gamma: float = 0.90) -> float: """Discounted sum of -1 for D steps left.""" if steps <= 0: return 0.0 return float(-(1.0 - gamma**steps) / (1.0 - gamma))
def q_value(steps_left: int, gamma: float = 0.90) -> float: """One -1 step plus gamma times remaining value.""" return float(-1.0 + gamma * remaining_value(steps_left, gamma))
print(round(remaining_value(6), 4)) # -> -4.6856print(round(remaining_value(8), 4)) # -> -5.6953print(round(q_value(6), 3)) # -> -5.217print(round(q_value(8), 3)) # -> -6.126Outputs match the hand math, and the larger Q picks north.
Watch Out For
Swapping sparse reward for straight line distance
Dense looks helpful but punishes detours. Behind a U wall the shortest Euclidean step pushes into the barrier while the true path first moves away. The symptom is a policy stuck pressing the wall.
Stay sparse with plus hindsight relabeling. If shaping is needed, learn a reachability distance rather than raw Cartesian gap.
The Quick Version
- Policy and values take , so one net serves many destinations.
- UVFA builds are joint MLP or factored dot product of state and goal codes.
- Sparse versus encodes shortest discounted path without wall traps.
- At gamma 0.9, north gives Q minus 5.22 and south gives minus 6.13, so north wins.
- Failed runs relabel to reached goals, which powers hindsight replay.