How to Implement On-Policy Algorithms (PPO, A2C, IMPALA) in EvoRL
EvoRL provides a modular architecture where PPO, A2C, and IMPALA share a common OnPolicyWorkflow base class, requiring only algorithm-specific agent factories and loss functions to implement complete training pipelines.
EvoRL is a JAX-based framework designed for scalable evolutionary and reinforcement learning research. When you implement on-policy algorithms like PPO, A2C, and IMPALA in EvoRL, you leverage a unified workflow system that handles distributed rollouts, advantage estimation, and optimization while allowing each algorithm to customize its loss computation and value estimation strategy.
Core Architecture of On-Policy Algorithms in EvoRL
The OnPolicyWorkflow Base Class
The foundation for all on-policy implementations resides in evorl/workflows/rl_workflow.py. The OnPolicyWorkflow class implements the generic training loop shared by PPO, A2C, and IMPALA:
- Rollout collection via
evorl/rollout.py - Observation normalization updates (optional)
- Advantage estimation (GAE for PPO/A2C, V-Trace for IMPALA)
- Loss computation and optimizer steps via
agent_gradient_updateinevorl/distributed/__init__.py
Algorithm-specific workflows (PPOWorkflow, A2CWorkflow, IMPALAWorkflow) inherit from this base and only provide a name() method and a builder that creates the appropriate agent.
Agent Structure and Network Factories
Each algorithm defines an Agent subclass stored in its respective file:
A2CAgentinevorl/algorithms/a2c.pyPPOAgentinevorl/algorithms/ppo.pyIMPALAAgentinevorl/algorithms/impala.py
These agents encapsulate:
- Policy and value networks (built via
make_policy_networkandmake_v_networkinevorl/networks/) - Algorithm-specific hyperparameters (clip epsilon for PPO, V-Trace parameters for IMPALA)
- Loss functions (
lossmethod) and action computation (compute_actions)
Factory functions make_mlp_ppo_agent, make_mlp_a2c_agent, and make_mlp_impala_agent provide convenient construction with configurable hidden layer sizes and optional observation normalization.
Implementing PPO, A2C, and IMPALA
PPO (Proximal Policy Optimization)
PPO implementation in evorl/algorithms/ppo.py uses the clipped surrogate objective. The PPOAgent.loss method computes:
- Policy loss: Clipped importance sampling ratio with epsilon (default 0.2)
- Value loss: MSE between predicted and target values
- Entropy bonus: Encourages exploration
- Optional KL penalty: For early stopping or constraint
The PPOWorkflow class (line 61 in ppo.py) inherits from OnPolicyWorkflow and uses make_mlp_ppo_agent to construct the agent with GAE advantage estimation configured in the workflow base.
A2C (Advantage Actor-Critic)
A2C in evorl/algorithms/a2c.py provides the simplest on-policy implementation. The A2CAgent computes standard actor-critic loss without importance sampling corrections.
Key characteristics:
- Single-step or n-step returns (configurable)
- GAE support via the base workflow
- Synchronous updates (no replay buffer)
The A2CWorkflow (line 29 in a2c.py) is a minimal subclass that instantiates make_mlp_a2c_agent and relies entirely on the base OnPolicyWorkflow for training logic.
IMPALA (Importance Weighted Actor-Learner Architecture)
IMPALA implementation in evorl/algorithms/impala.py introduces V-Trace correction for off-policy actor-critic learning with distributed actors. Unlike PPO and A2C, IMPALA uses:
- V-Trace targets (
compute_vtracefunction) to correct for policy lag between actors and learners - Policy gradient advantages (
compute_pg_advantage) for stable learning - Decoupled actor-learner architecture support via the distributed utilities
The IMPALAAgent loss combines:
- V-Trace corrected policy loss
- Baseline loss (value function)
- Entropy regularization
- KL divergence penalty
The IMPALAWorkflow (line 91 in impala.py) configures the agent using make_mlp_impala_agent and ensures the workflow uses the correct V-Trace advantage computation path in the base class.
Data Flow and Training Loop
Understanding the data flow helps when customizing these algorithms. The OnPolicyWorkflow orchestrates:
- Environment Creation –
evorl.envs.create_envinstantiates vectorized environments - Rollout Phase –
evorl/rollout.pycollects trajectories usingagent.compute_actions - Statistics Update – Optional observation normalization updates
- Advantage Computation –
compute_gaeinevorl/utils/rl_toolkits.pyfor PPO/A2Ccompute_vtraceandcompute_pg_advantageinevorl/algorithms/impala.pyfor IMPALA
- Loss Calculation –
agent.loss()computes gradients - Optimization –
agent_gradient_updateinevorl/distributed/__init__.pyapplies updates - Metrics & Checkpointing –
RLWorkflowhandles logging via recorders and periodic checkpointing
This unified pipeline means switching between PPO, A2C, and IMPALA requires only changing the agent factory and workflow class in your configuration.
Practical Implementation Examples
Training PPO with a Configuration File
The standard entry point scripts/train.py uses Hydra for configuration. Create a YAML config (e.g., configs/ppo_cartpole.yaml):
defaults:
- _self_
- override hydra/launcher: joblib
workflow_cls: evorl.workflows.PPOWorkflow
seed: 42
env:
env_name: CartPole-v1
env_type: gymnax
agent:
actor_hidden_layer_sizes: [256, 256]
critic_hidden_layer_sizes: [256, 256]
clip_epsilon: 0.2
normalize_obs: true
training:
num_iterations: 1000
rollout_length: 128
num_envs: 8
learning_rate: 3e-4
Run with:
python scripts/train.py --config-name=ppo_cartpole
Direct Agent Instantiation for Custom Experiments
For research requiring custom network architectures or loss modifications, instantiate agents directly:
import jax
from evorl.algorithms.ppo import make_mlp_ppo_agent
from evorl.envs import create_env
# Setup environment
env = create_env(
dict(env_name="CartPole-v1", env_type="gymnax"),
episode_length=200,
parallel=8
)
# Build PPO agent with custom architecture
agent = make_mlp_ppo_agent(
action_space=env.action_space,
clip_epsilon=0.2,
actor_hidden_layer_sizes=(256, 256),
critic_hidden_layer_sizes=(256, 256),
normalize_obs=True,
normalize_gae=True,
)
# Access network parameters
key = jax.random.PRNGKey(0)
agent_state = agent.init(key)
print(f"Policy network initialized with parameters: {agent_state.params.keys()}")
Running Distributed IMPALA
IMPALA benefits from distributed training. The workflow automatically handles device parallelism:
from evorl.algorithms.impala import IMPALAWorkflow
import jax
# Configuration should specify IMPALA-specific parameters like:
# - vtrace_rho_bar: 1.0
# - vtrace_c_bar: 1.0
# - baseline_cost: 0.5
cfg = {
"workflow_cls": "evorl.algorithms.impala.IMPALAWorkflow",
"env": {"env_name": "Breakout", "env_type": "gymnax"},
"agent": {
"actor_hidden_layer_sizes": [256, 256],
"vtrace_rho_bar": 1.0,
"vtrace_c_bar": 1.0
},
"training": {
"num_iterations": 10000,
"rollout_length": 20,
"num_envs": 32
}
}
# Build workflow with multi-device support
workflow = IMPALAWorkflow.build_from_config(cfg, enable_multi_devices=True)
# Initialize and train
state = workflow.init(jax.random.PRNGKey(cfg["training"].get("seed", 42)))
final_state = workflow.learn(state)
Summary
- EvoRL provides a unified
OnPolicyWorkflowbase class inevorl/workflows/rl_workflow.pythat handles the complete training loop for PPO, A2C, and IMPALA. - Agent factories (
make_mlp_ppo_agent,make_mlp_a2c_agent,make_mlp_impala_agent) in their respective algorithm files construct policy/value networks with configurable architectures. - Algorithm-specific losses differentiate implementations: PPO uses clipped surrogate loss in
evorl/algorithms/ppo.py, A2C uses standard actor-critic loss inevorl/algorithms/a2c.py, and IMPALA uses V-Trace correction inevorl/algorithms/impala.py. - Distributed training is supported via
agent_gradient_updateinevorl/distributed/__init__.pyand automatic multi-device scaling through the workflow configuration. - Entry point
scripts/train.pyuses Hydra configurations to instantiate workflows, making it easy to switch between algorithms by changing theworkflow_clsparameter.
Frequently Asked Questions
What is the difference between PPO and IMPALA implementations in EvoRL?
The primary difference lies in the advantage estimation and policy correction mechanisms. PPO uses Generalized Advantage Estimation (GAE) via compute_gae in evorl/utils/rl_toolkits.py and a clipped surrogate objective to limit policy updates. IMPALA uses V-Trace correction via compute_vtrace and compute_pg_advantage in evorl/algorithms/impala.py to handle off-policy data from distributed actors, making it suitable for decoupled actor-learner architectures where actors lag behind the learner.
How do I switch from PPO to A2C in my training script?
Switching requires only two configuration changes in your Hydra config or Python script. First, change the workflow_cls parameter from evorl.workflows.PPOWorkflow (or evorl.algorithms.ppo.PPOWorkflow) to evorl.workflows.A2CWorkflow (or evorl.algorithms.a2c.A2CWorkflow). Second, ensure your agent configuration uses the A2C-specific factory by setting the appropriate agent parameters (removing PPO-specific fields like clip_epsilon). The base OnPolicyWorkflow handles the rest of the training loop automatically.
Can I use custom neural network architectures with these algorithms?
Yes, you can replace the default MLP architectures by modifying the network factories or manually constructing agents. Instead of using make_mlp_ppo_agent, you can build custom policy networks using make_policy_network and value networks using make_v_network from evorl/networks/, then pass these directly to the Agent constructor (e.g., PPOAgent). This allows you to use CNNs for visual observations, custom activation functions, or specialized layer configurations while retaining the algorithmic logic of PPO, A2C, or IMPALA.
Where is the distributed training logic handled for IMPALA?
Distributed training logic is centralized in evorl/distributed/__init__.py through the agent_gradient_update function, which handles gradient aggregation across devices using psum for distributed sums and all_reduce for metrics. For IMPALA specifically, the V-Trace correction in evorl/algorithms/impala.py (compute_vtrace and compute_pg_advantage) handles the off-policy corrections necessary when actors and learners operate with different policy parameters. The workflow supports multi-device training via the enable_multi_devices=True flag in build_from_config, which automatically scales the rollout and update steps across available JAX devices.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →