Population Based Training (PBT)
July 5, 2026 · View on GitHub
rl_games ships the PBT observer lineage of DexPBT
(previously maintained downstream in
IsaacGymEnvs and Isaac Lab's
isaaclab_rl), now available to any rl_games backend from rl_games.common.pbt.
How it works
Each member of the population is an independent training process with a unique
policy_idx. Every interval_steps environment frames, each process:
- saves a scored checkpoint into a shared workspace directory,
- compares its objective against the population
(leaders: score > max(mean +
threshold_std·std, mean +threshold_abs); underperformers: the mirror image below the mean), - if it is an underperformer, re-execs itself from a random leader's checkpoint with the whitelisted hyperparameters mutated multiplicatively.
The objective is read from env infos at a dotted address (objective) — required
when PBT is enabled, since info layouts differ per backend: e.g.
episode.Episode_Reward/success for Isaac Lab-style nested infos, or scores for
flat info dicts. Steps where the address does not resolve keep the previous score.
Prefer a true task metric over raw reward when reward shaping is non-stationary.
Usage
Attach the observer when constructing the runner:
from rl_games.common.pbt import PbtAlgoObserver, MultiObserver
observer = MultiObserver([my_other_observer, PbtAlgoObserver(params, args_cli)])
runner = Runner(algo_observer=observer)
with a pbt section in the params:
pbt:
enabled: True
policy_idx: 0 # unique per process, 0..num_policies-1
num_policies: 8
directory: ./pbt_run
interval_steps: 100000
threshold_std: 0.10
threshold_abs: 0.05
mutation_rate: 0.25
change_range: [1.1, 2.0]
objective: episode.success
mutation:
agent.params.config.learning_rate: mutate_float
agent.params.config.grad_norm: mutate_float
agent.params.config.gamma: mutate_discount
Restart mechanism and launchers
On replacement the process re-execs itself, rebuilding its original command line with
--checkpoint=<leader checkpoint> plus key=value overrides for the mutated
hyperparameters. This requires a train script whose CLI accepts Hydra-style
key=value overrides (as in Isaac Lab / IsaacGymEnvs train.py).
By default the restart uses sys.executable (plain Python). Isaac Sim workflows that
must go through a wrapper set it explicitly:
pbt:
launcher: /path/to/_isaac_sim/python.sh
rl_games/runner.py does not currently accept key=value overrides, so PBT with the
plain runner requires a thin Hydra-style entry point; native runner support is planned
alongside the config-management work.
Mutation functions
mutate_float— multiply or divide by a random factor inchange_range.mutate_discount— mutate(1 - x)conservatively (for gamma-like params near 1.0).
Custom functions can be registered by adding to
rl_games.common.pbt.mutation.MUTATION_FUNCS.