Skip to content
AI360Xpert
Beta

Zero-Shot and Few-Shot RL

Zero-shot RL runs on a new task with no practice episodes, while few-shot RL gets K quick tries to figure it out. Both test whether training on many tasks taught a policy that actually generalizes.

Zero-shot runs with an empty context for 42.5 return while five adaptation episodes fill the context and lift return to 78.3.
Zero-shot runs with an empty context for 42.5 return while five adaptation episodes fill the context and lift return to 78.3.

Why Does This Exist?

A standard RL policy is a one-task specialist. Train a cheetah to run at 1.0 m/s for 10 million steps and it looks great. Ask for 2.0 m/s in a new track with slightly different friction and it stumbles. You then pay millions of fresh steps to retrain from zero. That bill repeats for every new goal, friction, or layout.

This page covers the evaluation side of that problem: what happens on a held-out task when you allow zero practice episodes versus K practice episodes. It does not re-teach how to train across tasks. That training story lives in meta-reinforcement learning and the gradient version lives in MAML in RL. Goal wording as a second way to name tasks lives in goal-conditioned RL.

You need one prerequisite idea first. A task is a Markov decision process with states, actions, transition dynamics, and rewards. A policy π(a∣s)\pi(a \mid s) is your rule for picking action aa in state ss. Meta-RL trains one policy across a distribution of such tasks p(T)p(\mathcal{T}) so it can face a new draw. If those terms feel shaky, read the meta-RL page first, then come back.

Think of It Like This

The Cover Chef With Tasting Spoons

You train as a cover chef across forty restaurant branches. Each branch has its own stove heat, salt stock, and regulars. Training builds two things: solid knife habits plus a small tasting-notes card you carry.

A new branch opens across town. Zero-shot means you walk in and cook the lunch rush with a blank card. No tasting, no questions. Your score depends only on how well the habits carry.

Few-shot with K equal to 5 means you get five tasting spoons before the rush. Spoon one tells you the broth runs salty. Spoon two tells you the burner runs hot. You scribble both on the card, adjust salt and flame, and cook. The card is the context. The spoons are the K episodes.

Where the analogy stops: kitchens do not have formal states, rewards, or gradient steps. A chef adjusts by feel. An RL agent adjusts by feeding the K episodes into an encoder that outputs a vector, then conditioning the policy on that vector.

How It Actually Works

Write TT for one task, p(T)p(\mathcal{T}) for the distribution you trained on, and TtestT_{test} for a held-out task you never trained on. Write ss for state, aa for action, GG for episode return, and π\pi for policy. A context cc is a small vector that summarizes what the agent has seen of the new task. DKD_K is the set of KK adaptation episodes on TtestT_{test}. An encoder ff maps that set to a context, so c=f(DK)c = f(D_K).

Zero-shot means empty context and frozen weights

Zero-shot evaluation freezes everything. The agent sees TtestT_{test}, builds an empty context c0c_0, and acts with π(a∣s,c0)\pi(a \mid s, c_0). No gradient step runs. No weight changes. The return J0J_0 is the average GG under that frozen policy.

This works only when training diversity already covered the test variation. Broad training plus steady sensors plus a fixed action meaning can carry a policy surprisingly far. If the test task needs a brand-new skill, zero-shot fails plainly. That failure is honest signal, not a bug.

Few-shot means K episodes become a context

Few-shot evaluation allows exactly KK episodes before scoring. The agent rolls out KK tries, collects DKD_K, computes c=f(DK)c = f(D_K), then acts with π(a∣s,c)\pi(a \mid s, c) on fresh scored episodes. The weights may stay frozen. Only the context changes.

Two common builds do this. A recurrent build carries a hidden state across the K episodes. An encoder build reads the K episodes into cc directly, in the style of probabilistic task embeddings. Either way the policy signature tells the story: the action depends on both the current state and the inferred task summary. MAML-style methods swap the encoder for KK gradient steps, which you will find on the MAML page rather than here.

Generalization benchmarks make the split fair. They fix a train set and a disjoint test set, then report both numbers. Train on slow target speeds, test on a fast one. Train on ten manipulation tasks, test on five new ones. Same agent, same weights, two scores: J0J_0 with no practice and JKJ_K after K tries.

Worked example: 0-shot 42.5 to 5-shot 78.3

Take one held-out task with a small illustrative fixture you can check by hand. The numbers below are a teaching fixture, not a benchmark claim. They trace the same shape real context-conditioned agents show: a big early jump, then shrinking gains.

  • K equal to 0 gives 42.5. Empty context, frozen policy.
  • K equal to 1 gives 58.1, a gain of 15.6. One episode names the task coarsely.
  • K equal to 2 gives 67.4, a gain of 9.3. The context sharpens.
  • K equal to 3 gives 73.0, a gain of 5.6.
  • K equal to 4 gives 76.2, a gain of 3.2.
  • K equal to 5 gives 78.3, a gain of 2.1.

Total adaptation gain is 78.3−42.5=35.878.3 - 42.5 = 35.8. A from-scratch oracle trained only on this task scores 82.0, so five shots reach 78.3/82.078.3 / 82.0, which is 95.5 percent of oracle with a handful of episodes instead of millions of steps. The diagram draws these six bars side by side so you can see the curve flatten.

The trade is simple. Zero-shot costs nothing at test time and tells you what truly transferred. Few-shot costs K episodes plus an encoder, and buys fast calibration when tasks share structure the context can name. When the test task sits far outside p(T)p(\mathcal{T}), neither saves you. Broaden training or retrain instead of adding more shots.

Code

The snippet below recomputes the fixture: per-shot gains, total gap, and oracle coverage.

from typing import Dict

def summarize(returns: Dict[int, float], oracle: float) -> None:    gains = [returns[k] - returns[k - 1] for k in range(1, 6)]    gap = returns[5] - returns[0]    coverage = returns[5] / oracle * 100.0    print(f"gains: {[round(g, 1) for g in gains]}")    print(f"gap: {gap:.1f}")    print(f"oracle coverage: {coverage:.1f}%")

if __name__ == "__main__":    fixture: Dict[int, float] = {        0: 42.5,        1: 58.1,        2: 67.4,        3: 73.0,        4: 76.2,        5: 78.3,    }    summarize(fixture, 82.0)
# -> expected output:gains: [15.6, 9.3, 5.6, 3.2, 2.1]gap: 35.8oracle coverage: 95.5%

Watch Out For

Task-ID leakage makes zero-shot look solved

You add a goal coordinate or task index to the observation during training because it is handy. The encoder learns to read the label instead of the behavior. Train scores look great. On a held-out task where the label is missing or has a new meaning, return collapses from the 70s to the 40s.

Symptom: zero-shot test return drops sharply the moment you hide the label, while train return stays high. Fix: mask every identifier that will not exist at test time, then re-run the zero-shot check with an empty context. If the gap stays, the context now earns its keep.

K-shot variance fools you with one lucky trial

Five episodes are noisy. One lucky rollout can swing the mean by 10 points. Reporting the best seed or the best K out of several tries turns noise into a claim.

Symptom: J5J_5 beats J0J_0 by 30 points on one seed and by 5 on the next. Fix: average over many held-out tasks and several seeds per K, keep K fixed before you run, and report the spread alongside the mean. Plot all six points from 0 to 5 so a shrinking gain reads as a curve, not a single jump.

The Quick Version

  • Zero-shot RL scores a frozen policy on a new task with no practice episodes and an empty context.
  • Few-shot RL allows K episodes, encodes them into a context vector, and conditions the same policy on that context.
  • Context-conditioned policies adapt without weight updates by changing only the task summary they read.
  • In the worked fixture, return climbs from 42.5 at 0-shot to 78.3 at 5-shot, a 35.8 point gain that reaches 95.5 percent of an 82.0 oracle.
  • Generalization benchmarks report both scores on disjoint train and test tasks so transfer reads as two numbers, not a feeling.