Algorithms
Core training algorithm, rollout logic, configuration, and utilities.
Types
Runtime types for the PPO algorithm.
- class nnx_ppo.algorithms.types.EnvState(*args, **kwargs)[source]
Bases:
ProtocolMinimal environment state interface.
Satisfied by mujoco_playground.State and any compatible environment state. Fields are declared as read-only properties so that frozen dataclasses (which have immutable attributes) satisfy this protocol. Note: replace() is intentionally omitted — playground’s State has it at runtime (via @struct.dataclass) but not in its type stubs.
- property done: Shaped[Array, '...']
- __init__(*args, **kwargs)
- class nnx_ppo.algorithms.types.RLEnv(*args, **kwargs)[source]
Bases:
ProtocolMinimal RL environment interface.
Satisfied by mujoco_playground.MjxEnv and any compatible environment.
- __init__(*args, **kwargs)
- class nnx_ppo.algorithms.types.TrainingState(networks: Any, network_states: Any, env_states: Any, optimizer: Any, rng_key: jaxtyping.Key[Array, ''] | jaxtyping.UInt32[Array, '2'] | jaxtyping.UInt32[Array, '4'], steps_taken: jaxtyping.Float[Array, ''])[source]
Bases:
JaxDataclass- rng_key: Key[Array, ''] | UInt32[Array, '2'] | UInt32[Array, '4']
- steps_taken: Float[Array, '']
- __init__(networks, network_states, env_states, optimizer, rng_key, steps_taken)
- class nnx_ppo.algorithms.types.Transition(obs, network_output, rewards, done, truncated, next_obs, metrics, rollout_extras=None)[source]
Bases:
JaxDataclassEnvironment state for training and inference.
Note: rewards, done, truncated use *time to allow both [batch] (single timestep) and [time, batch] (full rollout) shapes.
- obs: PyTree[jaxtyping.Float[Array, '...']]
- network_output: PPONetworkOutput
- rewards: PyTree[jaxtyping.Float[Array, '*time batch']]
- done: Bool[Array, '*time batch']
- truncated: Bool[Array, '*time batch']
- next_obs: PyTree[jaxtyping.Float[Array, '...']]
- __init__(obs, network_output, rewards, done, truncated, next_obs, metrics, rollout_extras=None)
- class nnx_ppo.algorithms.types.DistillationTransition(obs, student_output, rewards, done, truncated, next_obs, metrics, student_rollout_extras=None, teacher_rollout_extras=None)[source]
Bases:
JaxDataclassRollout transition for distillation training.
Carries both student and teacher network outputs. The student’s actions drive the environment; the teacher’s outputs (pre-computed outside of gradient computation) serve as the distillation target.
- obs: PyTree[jaxtyping.Float[Array, '...']]
- student_output: PPONetworkOutput
- rewards: PyTree[jaxtyping.Float[Array, '*time batch']]
- done: Bool[Array, '*time batch']
- truncated: Bool[Array, '*time batch']
- next_obs: PyTree[jaxtyping.Float[Array, '...']]
- __init__(obs, student_output, rewards, done, truncated, next_obs, metrics, student_rollout_extras=None, teacher_rollout_extras=None)
- class nnx_ppo.algorithms.types.DistillationState(student, student_states, teacher_states, env_states, optimizer, rng_key, steps_taken)[source]
Bases:
JaxDataclassTraining state for distillation.
Mirrors TrainingState but has separate student and teacher states. The teacher is passed as an external argument (like env) and is not stored here. Only the teacher’s per-env carry state is tracked.
- rng_key: Key[Array, ''] | UInt32[Array, '2'] | UInt32[Array, '4']
- steps_taken: Float[Array, '']
- __init__(student, student_states, teacher_states, env_states, optimizer, rng_key, steps_taken)
Configuration
Configuration dataclasses for train_ppo and train_distillation.
- class nnx_ppo.algorithms.config.PPOConfig(n_envs=256, rollout_length=20, total_steps=512000, gae_lambda=0.95, discounting_factor=0.99, clip_range=0.2, learning_rate=0.0001, normalize_advantages=True, combine_advantages=False, n_epochs=4, n_minibatches=4, critic_loss_weight=1.0, gradient_clipping=None, weight_decay=None, logging_level=<LoggingLevel.LOSSES: 1>, logging_percentiles=None)[source]
Bases:
objectCore PPO algorithm parameters.
- logging_level: LoggingLevel = 1
- __init__(n_envs=256, rollout_length=20, total_steps=512000, gae_lambda=0.95, discounting_factor=0.99, clip_range=0.2, learning_rate=0.0001, normalize_advantages=True, combine_advantages=False, n_epochs=4, n_minibatches=4, critic_loss_weight=1.0, gradient_clipping=None, weight_decay=None, logging_level=<LoggingLevel.LOSSES: 1>, logging_percentiles=None)
- class nnx_ppo.algorithms.config.EvalConfig(enabled=True, every_steps=50000, n_envs=64, max_episode_length=1000, logging_level=<LoggingLevel.NONE: 0>, logging_percentiles=(0, 25, 50, 75, 100))[source]
Bases:
objectEvaluation rollout configuration.
- logging_level: LoggingLevel = 0
- __init__(enabled=True, every_steps=50000, n_envs=64, max_episode_length=1000, logging_level=<LoggingLevel.NONE: 0>, logging_percentiles=(0, 25, 50, 75, 100))
- class nnx_ppo.algorithms.config.VideoConfig(enabled=False, every_steps=200000, episode_length=1000, render_kwargs=<factory>)[source]
Bases:
objectVideo recording configuration.
- __init__(enabled=False, every_steps=200000, episode_length=1000, render_kwargs=<factory>)
- class nnx_ppo.algorithms.config.TrainConfig(ppo=<factory>, eval=<factory>, video=<factory>, seed=17, checkpoint_every_steps=500000)[source]
Bases:
objectComplete training configuration.
- eval: EvalConfig
- video: VideoConfig
- __init__(ppo=<factory>, eval=<factory>, video=<factory>, seed=17, checkpoint_every_steps=500000)
- class nnx_ppo.algorithms.config.DistillationConfig(n_envs=256, rollout_length=20, total_steps=512000, learning_rate=0.0001, n_epochs=4, n_minibatches=4, gradient_clipping=None, weight_decay=None, logging_level=<LoggingLevel.LOSSES: 1>, logging_percentiles=None)[source]
Bases:
objectCore distillation algorithm parameters.
- logging_level: LoggingLevel = 1
- __init__(n_envs=256, rollout_length=20, total_steps=512000, learning_rate=0.0001, n_epochs=4, n_minibatches=4, gradient_clipping=None, weight_decay=None, logging_level=<LoggingLevel.LOSSES: 1>, logging_percentiles=None)
- class nnx_ppo.algorithms.config.DistillationTrainConfig(distillation=<factory>, eval=<factory>, video=<factory>, seed=17, checkpoint_every_steps=500000)[source]
Bases:
objectComplete training configuration for distillation.
- distillation: DistillationConfig
- eval: EvalConfig
- video: VideoConfig
- __init__(distillation=<factory>, eval=<factory>, video=<factory>, seed=17, checkpoint_every_steps=500000)
- class nnx_ppo.algorithms.config.VideoData(frames, step, episode_reward, episode_length)[source]
Bases:
objectData passed to video callback.
- frames: ndarray
- __init__(frames, step, episode_reward, episode_length)
- class nnx_ppo.algorithms.config.TrainResult(training_state, final_metrics, eval_history, total_steps, total_iterations)[source]
Bases:
objectResult of train_ppo containing final state and summary.
- training_state: TrainingState
- __init__(training_state, final_metrics, eval_history, total_steps, total_iterations)
- class nnx_ppo.algorithms.config.DistillationTrainResult(training_state, final_metrics, eval_history, total_steps, total_iterations)[source]
Bases:
objectResult of train_distillation containing final state and summary.
- training_state: DistillationState
- __init__(training_state, final_metrics, eval_history, total_steps, total_iterations)
Training
- nnx_ppo.algorithms.ppo.train_ppo(env, networks, config=None, *, total_steps=None, seed=None, log_fn=None, video_fn=None, checkpoint_fn=None, eval_env=None, initial_state=None)[source]
Train a PPO agent.
- Parameters:
env (RLEnv) – Training environment (MjxEnv).
networks (StatefulModule) – PPO network (actor-critic).
config (TrainConfig | None) – Training configuration. If None, uses default_config().
total_steps (int | None) – Override config.ppo.total_steps (convenience parameter).
seed (int | None) – Override config.seed (convenience parameter).
log_fn (Callable[[dict[str, Any], int], None] | None) – Called with (metrics_dict, step) after each PPO step. If None, no logging is performed.
video_fn (Callable[[VideoData], None] | None) – Called with VideoData after rendering eval episodes. If None, no videos are recorded even if config.video.enabled.
checkpoint_fn (Callable[[TrainingState, int], None] | None) – Called with (training_state, step) at config.checkpoint_every_steps intervals. If None, no checkpointing is performed.
eval_env (RLEnv | None) – Environment for evaluation rollouts. If None, uses env.
initial_state (TrainingState | None) – Resume training from an existing TrainingState. If None, creates a new TrainingState.
- Returns:
TrainResult containing final TrainingState, metrics, and eval history.
- Return type:
- nnx_ppo.algorithms.ppo.ppo_step(env, training_state, n_envs, rollout_length, gae_lambda, discounting_factor, clip_range, normalize_advantages, combine_advantages, n_epochs, n_minibatches, critic_loss_weight=1.0, logging_level=<LoggingLevel.LOSSES: 1>, logging_percentiles=None)[source]
- nnx_ppo.algorithms.ppo.gae(rewards, values_excl_last, last_value, done, truncation, lambda_, gamma)[source]
Rollout
- nnx_ppo.algorithms.rollout.unroll_env(env, env_state, networks, network_state, unroll_length, rng_key_for_env_reset)[source]
- nnx_ppo.algorithms.rollout.eval_rollout(env, networks, n_envs, max_episode_length, key, logging_percentiles=None, logging_level=<LoggingLevel.NONE: 0>)[source]
- nnx_ppo.algorithms.rollout.record_activations_rollout(env, networks, n_envs, max_episode_length, key)[source]
Roll out a deterministic episode and return per-step unit activations.
Convenience wrapper for activation analysis.
networksis made recordable withwith_recording()(the original is left untouched) and run in eval mode, so action samplers are deterministic. Each step’s activations are stacked over time via the scan’sysreturn — this is noteval_rollout, which reduces metrics to scalars and so cannot expose per-unit values.Unlike
eval_rollout(), environments are not reset on termination: each env runs a single episode formax_episode_lengthsteps. The returneddonesflag is the pre-step “already terminated” mask (matchingeval_rollout’s accounting); callers should mask out steps where it is set.Memory cost:
max_episode_length × n_envs × Σ unitsis materialised on the device. On a small GPU prefer a modestn_envs(e.g. a handful) and/or a shortermax_episode_length.- Returns:
- A pytree mirroring the network’s container structure, each
leaf an array with leading dims
[max_episode_length, n_envs, ...], keyed by module path (e.g.action/0,value/...); the population graph contributes one entry per population.
dones:
[max_episode_length, n_envs]pre-step termination mask.- Return type:
activations
- class nnx_ppo.algorithms.rollout.SlimData(qpos, qvel, time, mocap_pos, mocap_quat, xfrc_applied)[source]
Bases:
NamedTupleMinimal mjx.Data fields needed for rendering.
- class nnx_ppo.algorithms.rollout.SlimState(data, done, info, metrics)[source]
Bases:
NamedTupleMinimal env state for rendering, avoiding large mjx.Data contact buffers.
- nnx_ppo.algorithms.rollout.eval_rollout_for_render_scan(env, networks, max_episode_length, key)[source]
JIT-compatible scan-based rollout that returns stacked slim states.
Returns stacked SlimState (qpos/qvel/time/info/done/metrics only) rather than the full env state, avoiding large MuJoCo Warp contact buffers.
- Returns:
SlimState pytree with leading dimension of max_episode_length. final_state: The final environment slim state. total_reward: Total reward accumulated during the episode.
- Return type:
stacked_states
Checkpointing
Checkpointing utilities for saving and loading training state.
- class nnx_ppo.algorithms.checkpointing.CheckpointCallback(*args, **kwargs)[source]
Bases:
ProtocolProtocol for checkpoint callbacks with named parameters.
- nnx_ppo.algorithms.checkpointing.make_checkpoint_fn(directory, config=None)[source]
Create a checkpoint callback that saves TrainingState to disk.
Each checkpoint is written to
{directory}/step_{step:010d}/, containing:networks/— orbax checkpoint with all non-PRNG-key network variables (Param, RngCount, NormalizerStatistics, etc.)optimizer/— orbax checkpoint with all optimizer state arraysmetadata.pkl— pickle file with network RngKey variables, all remaining TrainingState fields (network_states,env_states,rng_key,steps_taken), the step count, and the optional TrainConfig.
To resume training from a checkpoint, use
load_checkpoint().- Parameters:
directory (str) – Base directory under which checkpoint subdirectories are created.
config (TrainConfig | None) – Optional TrainConfig to store alongside each checkpoint, useful for reproducing training runs.
- Returns:
A callback compatible with train_ppo’s
checkpoint_fnparameter.- Return type:
Example
>>> result = train_ppo( ... env, networks, config, ... checkpoint_fn=make_checkpoint_fn("/tmp/my_run", config=config), ... )
- nnx_ppo.algorithms.checkpointing.load_checkpoint(path, networks, optimizer)[source]
Load a checkpoint saved by
make_checkpoint_fn().The
networksandoptimizerarguments serve as structural templates: their architecture must match the checkpoint, but their current parameter values are irrelevant and will be overwritten in-place by the checkpoint values.- Parameters:
path (str) – Path to the step checkpoint directory, e.g.
/tmp/my_run/step_0000500000.networks (Any) – Network instance with the same architecture as the checkpoint. Weights are updated in-place.
optimizer (Optimizer) – Optimizer instance with the same structure as the checkpoint. State is updated in-place.
- Returns:
"training_state"— restoredTrainingState"step"— training step at which the checkpoint was saved (int)"config"—TrainConfigif one was stored, elseNone
- Return type:
A dict with the following keys
Example
>>> networks = factories.make_mlp_actor_critic(...) >>> training_state = ppo.new_training_state(env, networks, n_envs, seed) >>> ckpt = load_checkpoint( ... "/tmp/my_run/step_0000500000", ... training_state.networks, ... training_state.optimizer, ... ) >>> result = train_ppo( ... env, networks, ckpt["config"], ... initial_state=ckpt["training_state"], ... )
Callbacks
Callback helpers for training logging.
- nnx_ppo.algorithms.callbacks.wandb_video_fn(key='eval_video', fps=30)[source]
Create a video callback that logs to wandb.
- Parameters:
- Returns:
A callback function compatible with train_ppo’s video_fn parameter.
- Return type:
Example
>>> result = train_ppo( ... env, networks, ... video_fn=wandb_video_fn(fps=50), ... )
Metrics
Metrics computation and logging utilities for PPO training.
- nnx_ppo.algorithms.metrics.compute_metrics(loss_metrics, rollout_data, logging_level, percentile_levels=None)[source]
Compute training metrics from loss metrics and rollout data.
- Parameters:
loss_metrics (dict[str, PyTree]) – Dictionary of loss values from ppo_loss.
rollout_data (Transition) – Transition data from the rollout.
logging_level (LoggingLevel) – Which metrics to include.
percentile_levels (tuple[int, ...] | None) – Percentiles to compute (e.g., (0, 25, 50, 75, 100)). If None, uses mean/std instead.
- Returns:
Dictionary of computed metrics.
- Return type: