The REINFORCE Algorithm
REINFORCE waits for full episodes, then raises the probability of actions that led to high returns and lowers the probability of actions that led to low returns.
Why Does This Exist?
Value methods pick actions by maximizing over the action set. That works for a few discrete buttons and breaks for a robot arm, where the action is a continuous torque vector and the maximum has no closed form. They also struggle to represent stochastic policies, which you need when one observation demands a mix of actions.
REINFORCE, introduced by Williams in 1992, skips values and tunes the policy directly. The policy is a parameterized distribution, such as a Gaussian mean and variance for continuous joints or logits for discrete moves. The puzzle it solved: how do you differentiate expected return when the environment dynamics behind it are unknown? The log derivative trick turns the gradient of an expectation into an expectation of gradients, which single episode rollouts can estimate. For the general family this belongs to, read policy gradient. For the lower variance successor, read actor critic architecture.
The one idea you need first
An expected return is the average total reward your policy collects, where the average runs over all the randomness in trajectories. REINFORCE climbs this average with gradient ascent: it estimates which way in weight space raises the average, then steps that way. Everything below is how to get that direction from one played episode.
Think of It Like This
A coach who only reviews full game tape
A basketball coach is not allowed to shout instructions during the game. She watches the whole 48 minutes, lets the players try things, and waits for the final buzzer. Then she rewinds the tape. Every possession that fed a scoring run gets a note saying do that dribble move more often. Every possession that fed turnovers gets a note saying cut that risky pass down.
Credit is noisy, because one brilliant first quarter pass sits inside a game lost on fourth quarter defense. But across hundreds of games, the moves that systematically precede wins get reinforced and the rest fade. That is Monte Carlo learning: judge each decision by the full return that followed it, and average over many completions.
Where the analogy stops: the coach understands why a play worked, while REINFORCE only knows the score that followed. It assigns credit by timing, weighting early actions by everything that came after, which is exactly why its estimates wobble so much.
How It Actually Works
The likelihood ratio trick
Write a trajectory as . Here is the state, the action taken, and the rewards collected. The objective is the expected trajectory return:
A trajectory's probability splits into the start distribution, your policy, and the unknown environment transitions :
Differentiating looks hopeless because is unknown. The trick is the identity , which moves the gradient onto the log. Since turns the product into a sum and does not depend on , every environment term differentiates to zero:
That leaves the policy gradient estimator:
Here is the return to go from step , meaning rewards from onward discounted back: with discount factor . Using instead of the whole episode return respects causality, since your action at cannot affect rewards already banked before .
Baselines cut variance without bias
Full episode returns swing wildly, and that swing passes straight into the gradient. The standard fix subtracts a baseline , a number that may depend on the state but not on the sampled action:
Here is the learning rate. The baseline adds no bias because its expected contribution is zero: averaging over the policy's own action distribution always gives zero, so scaling it by still gives zero. A constant average return works, and a learned state value works better. The diagram below walks the numbers once through this update.
Worked example
Two steps, two actions, one weight . The policy is a sigmoid: action gets logit and gets logit , so and . Start at , so both actions have probability . Set , , baseline . The episode plays for reward , then for reward .
Returns to go, computed backward: and . Minus the baseline, the advantages are and .
Log probability gradients at : for the taken , . For the taken , . Total gradient: . Update: . The new . The good first move gets reinforced more than the second move gets suppressed, so its probability rises.
Code
This snippet runs the worked update with plain arithmetic. Check each printed number against the hand computation above.
import numpy as np
def reinforce_update(theta: float, actions: list[int], rewards: list[float], gamma: float = 1.0, alpha: float = 0.1, baseline: float = 5.0) -> tuple[float, list[float]]: """One Monte Carlo REINFORCE update over a single episode.""" returns: list[float] = [0.0] * len(rewards) g = 0.0 for t in reversed(range(len(rewards))): g = rewards[t] + gamma * g returns[t] = g prob_a1 = 1.0 / (1.0 + np.exp(-theta)) total_grad = 0.0 for t, action in enumerate(actions): advantage = returns[t] - baseline grad_log = (1.0 - prob_a1) if action == 0 else (-prob_a1) total_grad += grad_log * advantage return theta + alpha * total_grad, returns
if __name__ == "__main__": new_theta, rets = reinforce_update(0.0, [0, 1], [2.0, 8.0]) print(f"returns: {rets}") print(f"theta: {new_theta:.2f}") print(f"P(a1): {1.0 / (1.0 + np.exp(-new_theta)):.4f}")# -> expected output:returns: [10.0, 8.0]theta: 0.10P(a1): 0.5250Watch Out For
Full episode variance stalls long horizon training
The symptom: updates thrash, the policy jitters, and longer episodes train worse than short ones at the same learning rate. The cause is Monte Carlo credit: one noisy late transition alters for every earlier step, so the whole episode's gradient inherits the noise of its worst moment.
The fix: always use returns to go rather than whole episode return, subtract a baseline (constant at minimum, learned state value when episodes run long), and normalize advantages within each batch. Past a few hundred steps per episode, move to an actor critic that bootstraps after steps instead of waiting for termination.
Forgetting the baseline must ignore the sampled action
The symptom: adding a baseline shifts the final policy instead of just calming training. The cause is a baseline that peeks at the action just taken, such as an advantage estimate built from the same sample. The zero expectation proof breaks, and the update turns biased.
The fix: let the baseline depend on state (and time) only. Audit any learned baseline to confirm it never receives the current action as input, and keep the gradient term as the only place the sampled action appears.
The Quick Version
- REINFORCE tunes the policy directly with the log derivative trick, so unknown environment dynamics drop out of the gradient.
- Updates wait for full episodes and weight each step's log probability gradient by its return to go .
- A state dependent baseline subtracts from with zero bias and much lower variance.
- The worked episode gives returns 10.0 and 8.0, gradient +1.0, new theta 0.1, and rising from 0.5000 to 0.5250.
- Past a few hundred steps per episode, bootstrap with an actor critic instead of pure Monte Carlo returns.