Target Policy Optimization

Jean Kaddour

TL;DR. GRPO-style RL samples a few answers per prompt, scores them, and nudges the model toward the good ones. TPO does the nudge in two steps. First it writes down where the probability should go: a target distribution qq over the sampled answers. Then it fits the model to qq with cross-entropy. The gradient is p−qp - q, so updates stop once the model hits the target. On dense rewards it matches GRPO; on sparse rewards it wins by a wide margin.

Learning curves: TPO, GRPO and DG on MNIST and on sparse-reward token reversal
Left: MNIST with dense reward, where TPO learns fastest. Right: reward only at the end of the sequence. DG never gets going, GRPO still fails half the time after 2,000 episodes, and TPO ends below 10% error. 20 seeds, mean ± standard error.

One prompt, a handful of answers

Most RL on language models takes a prompt, samples KK answers from the current model, checks each one with a verifier, and updates the model so the right answers become more likely.

GRPO, the current workhorse, standardizes the rewards within the group to get advantages Ai=(Ri−mean R)/std RA_i = (R_i - \text{mean}\,R) / \text{std}\,R, then moves each answer's log-probability up or down in proportion to its advantage:

Δθ∝1K∑i=1KAi ∇θlog⁡πθ(yi∣x)\Delta\theta \propto \frac{1}{K}\sum_{i=1}^{K} A_i\,\nabla_\theta \log \pi_\theta(y_i \mid x)

That one line answers two questions at once:

  1. What should change? Which answers should gain probability, and how much?
  2. How should the weights move to make that change happen?

The advantages give a direction. How far the model travels along it is left to the learning rate, the number of passes over the batch, and the clip. If it moves too little, a rare success gets wasted; if it moves too much, the model overfits one lucky batch.

TPO answers the two questions one at a time: first decide where the probability should go, then move the model there.

Step 1: decide where the probability should go

TPO needs two numbers per answer: how likely the model was to write it, pioldp_i^{\text{old}} (renormalized over the KK sampled answers so they sum to one), and its standardized score AiA_i, the same one GRPO uses. The target reweights the old probabilities by the exponentiated score:

qi=piold eAi/η∑jpjold eAj/ηq_i = \frac{p_i^{\text{old}}\, e^{A_i/\eta}}{\sum_j p_j^{\text{old}}\, e^{A_j/\eta}}

In words: start from what the model already does, scale good answers up and bad ones down, renormalize. η\eta is a temperature; I use η=1\eta = 1 everywhere in the paper.

Build a target
Drag a bar to change p_old · click a reward to flip it
pold (model now)q (target)
y₁
A = −1.00
0.70 → 0.25
y₂
A = +1.00
0.15 → 0.40
y₃
A = +1.00
0.13 → 0.34
y₄
A = −1.00
0.02 → 0.01
q₂ = 0.15 × e+1.00/1.00 ÷ 1.03 = 0.40
Correct answers go from 28% to 74% of the group's mass. In total, 46% of the mass moves.

Some things to try in the widget:

  • Pick All wrong. Every answer has the same reward, so every Ai=0A_i = 0, q=poldq = p^{\text{old}}, and the update is exactly zero.
  • Pick Lone breakthrough. The only correct answer starts at 3% and the target gives it 24%. That's an eightfold boost, but it doesn't take over the group, which I think is the right amount of trust for a single batch.
  • Pick Common vs rare mistake. Both wrong answers get the same score, yet the target takes 45 points of mass from the 70% mistake and barely touches the 2% one. This matters more than it looks (section 2 below).
  • Move η. Smaller η makes the target greedier; larger η keeps it closer to poldp^{\text{old}}.

Why standardize? Scores of (1, 0, −1) and (100, 0, −100) rank the answers the same way, but exponentiating the second gives an essentially one-hot target while the first gives a gentle tilt. After standardizing, the target only depends on how the answers compare with each other, which is why one η\eta works across tasks.

The target is a trade-off

The formula for q comes out of:

q=arg⁡max⁡rEr[A]⏟be good−η KL(r ∥ pold)⏟stay closeq = \arg\max_{r} \underbrace{\mathbb{E}_{r}[A]}_{\text{be good}} - \eta\, \underbrace{\mathrm{KL}(r \,\|\, p^{\text{old}})}_{\text{stay close}}

over distributions rr on the sampled answers: get as much advantage as you can without moving too far from what the model already does. With three answers, every distribution is a point in a triangle, so you can see the trade-off directly.

Where the target sits
Drag the gray dot · flip rewards · slide η
y₁y₂y₃
y₁ ✓y₂ ✗y₃ ✗
pold: the model nowq: TPO's target (★), and where it moves as η changes (dashed)GRPO: a direction, no endpoint
Expected advantage: −0.28 → +0.73
Cost, η·KL(q ‖ pold): 0.53
q = (0.68, 0.20, 0.12)

The dashed curve shows where the target lands for each η\eta. Large η\eta keeps it on top of poldp^{\text{old}}; as η\eta shrinks, it slides toward the correct corner. The orange arrow is GRPO's first step on the same group. It points the same way, but it's only a direction, and where GRPO stops depends on the optimizer settings. TPO's target is a point you can compute before taking a single step.

Step 2: fit the target

Now make the model match qq. TPO uses plain cross-entropy with qq as soft labels:

LTPO=−∑i=1Kqilog⁡piθ\mathcal{L}_{\text{TPO}} = -\sum_{i=1}^{K} q_i \log p_i^{\theta}

where piθp_i^\theta is the current model's probability of answer ii, again renormalized over the group. The gradient with respect to each answer's log-probability is

∂LTPO∂log⁡πθ(yi∣x)=piθ−qi\frac{\partial \mathcal{L}_{\text{TPO}}}{\partial \log \pi_\theta(y_i \mid x)} = p_i^\theta - q_i

which is zero exactly when the model matches the target. This is the part I like most: the update stops on its own. It matters as soon as you reuse a batch for several gradient steps, which PPO and GRPO do routinely.

Reuse one batch for many steps
Press play · change the learning rate
TPOGRPO surrogate, no clip or KLtarget
0%25%50%75%100%0102030gradient steps on the same batchmass on correct answerstarget q: 24%
The group after step 30 (green = correct)
TPO
y₁ 24%
y₂ 39%
y₃ 24%
y₄ 13%
GRPO, no clip
y₁ 100%
Gradient size at step 30: TPO 1.4e-3, GRPO surrogate 2.5e-2

TPO settles on its target at any learning rate; a larger step only gets it there sooner. GRPO's surrogate without the clip and KL penalty has no stopping point, and keeps going until the model is certain about this one batch's winners. That's what the clip and the KL penalty are there to prevent. With TPO, the loss itself stops at the target.

The code is short:

def tpo_target(log_scores, adv, eta=1.0):
    return F.softmax(
        F.log_softmax(log_scores, -1)
        + adv / eta, -1)

q = tpo_target(
    log_scores, adv).detach()
log_p = F.log_softmax(log_scores, -1)
loss = -(q * log_p).sum(-1).mean()

log_scores holds the model's log-probabilities for the KK sampled answers, and adv holds their standardized scores. The one subtlety is detaching qq, because it's a fixed label and gradients shouldn't flow through it. If you reuse a batch for more epochs, keep qq frozen at its rollout-time value.

What the target changes

So why would this beat GRPO? GRPO's one-number-per-answer advantages leave signal on the table in at least three places. The first two are diagnostics from Ian Osband's Delightful Policy Gradient.

1. Hard prompts get their share

Take the simplest setting I can think of: many prompts, each with one correct answer out of ten, and exact updates. Every method then pushes each prompt in the same direction, toward its correct answer. The methods only differ in how hard they push, a weight β(p)\beta(p) that depends on the prompt's current pass rate pp. If the total step size is fixed, β\beta decides how the step gets split between prompts.

How the step is split across prompts
Drag the markers, or use the sliders
GRPO: β = √(p / (1 − p))TPOequal split (supervised learning)
0123450%25%50%75%100%prompt's current pass rate pupdate weight β(p)hard promptGRPO 0.23 · TPO 0.57easy promptGRPO 4.36 · TPO 0.96
Share of one normalized step: hard prompt (dark) vs easy prompt (light)
GRPO
95%
easy gets 19×
TPO
37%
63%
easy gets 1.7×

GRPO's weight goes to zero on hard prompts and blows up on easy ones: a prompt the model solves 95% of the time gets 19× the update of one it solves 5% of the time. That's backwards if the goal is to learn what the model can't do yet. Supervised learning would split the step evenly. TPO gets close, at 1.7×. Its target multiplies the correct answer's odds by the same factor (about 28 here) on every prompt, so hard prompts still get a big update.

2. Common mistakes get pushed harder than rare ones

Back to the four answers from the first widget. GRPO sees two wrong answers with the same reward and gives them the same advantage, so it pushes both logits down equally hard, whether the model makes that mistake 70% of the time or 2% of the time. TPO's push on each answer is qi−pioldq_i - p_i^{\text{old}}, the amount of probability that has to move.

answerpoldrewardGRPO push, A / KTPO push, q − pold
common mistake
0.70
✗ 0
−0.25
−0.45
correct
0.15
✓ 1
+0.25
+0.25
another correct
0.13
✓ 1
+0.25
+0.21
rare mistake
0.02
✗ 0
−0.25
−0.01
Push on each answer's logit at the first step (bars scaled per method). Same numbers as the "Common vs rare mistake" example above.

TPO pushes 35× harder on the habit than on the slip. GRPO spends as much of its update on a 2% slip as on the mistake the model keeps making.

3. Each group gets its own stopping point

PPO and GRPO stop a reused batch with a clip: each answer's probability ratio πθ/πold\pi_\theta / \pi_{\text{old}} may only move within [1−ε, 1+ε][1-\varepsilon,\, 1+\varepsilon], usually with ε=0.2\varepsilon = 0.2. Every answer gets the same band. Once a breakthrough that the model finds 1% of the time reaches 1.2%, the clip stops pushing it, while an easy answer at 90% can coast all the way to 100%. DAPO's "clip-higher" trick was introduced for this reason. TPO has no clip. It stops at qq, which each group sets from its own evidence: a lone success at 1% in a group of eight gets a target of 17%.

Does it work?

The experiments in the paper go from tabular bandits up to 1.7B-parameter LLMs. The short version: with dense reward, TPO is about as good as GRPO, PPO and DG, sometimes a bit better. With sparse reward, it pulls away.

Sparse reward

A small transformer learns to reverse a binary sequence of length HH and only gets a reward if the whole sequence is right. Longer sequences make a correct rollout rarer: at H=10H = 10, a random guess is right one time in 1,024.

Sparse reward: reversing a sequence of length H
Error, lower is better
TPO
7.4%
GRPO
50.4%
GRPO (no KL)
above 95%: no learning
PPO
above 95%: no learning
DG
above 95%: no learning
Exact-match error after 2,000 episodes, with K = 8 rollouts per prompt. "Same prompts" gives every method the same prompts, so the grouped methods use 8× more rollouts. "Same rollouts" gives every method the same number of rollouts. Without its KL penalty GRPO falls apart, so under sparse reward the KL term does most of the work of keeping GRPO stable.

Stale rollouts

Large RL systems often generate rollouts with slightly outdated weights. In an MNIST bandit where the actors use parameters from DD steps ago, TPO's error stays at 2.3% all the way from D=0D = 0 to D=1000D = 1000.

Stale rollouts: actors lag D steps behind
Error, lower is better
TPO
2.3%
DG
2.5%
PPO
5.4%
PG (importance-weighted)
9.8%
REINFORCE
78.1%
Final error on the MNIST contextual bandit, from the talk.

LLMs

I also swapped GRPO's loss for TPO's in verl, on Qwen3-1.7B and DeepSeek-R1-Distill-Qwen-1.5B with 16 rollouts per prompt, and changed nothing else:

Accuracy curves for TPO and GRPO on GSM8K, graph coloring and Knights and Knaves, for two small LLMs
GSM8K ends in a near tie, though TPO gets there faster. On graph coloring with Qwen3-1.7B, GRPO peaks early and then degrades, while TPO keeps climbing to about 0.96.

Independently, a team at Tencent came up with a closely related objective, Listwise Policy Optimization, which also frames group-based RLVR as projecting onto a target on the response simplex.

An old idea, in closed form

Reweight-then-fit is old. It goes back at least to Dayan and Hinton's EM for RL (1997) and runs through REPS, MPO and SPU, each of which had to work around something expensive. Group-based RL makes this much easier: with a finite group of scored answers, the target is just a softmax, so you need neither a critic nor a dual problem.

EM for RL
Dayan & Hinton, 1997
sums over all actions
REPS
Peters et al., 2010
solves a dual problem
MPO
Abdolmaleki et al., 2018
needs a learned Q-function
SPU
Vuong et al., 2019
runs an inner optimization
TPO
2026
finite group, so q is a softmax

Cite

@article{kaddour2026tpo,
  title   = {Target Policy Optimization},
  author  = {Kaddour, Jean},
  journal = {arXiv preprint arXiv:2604.06159},
  year    = {2026}
}