Benchmarks¶
Reproduced scores from examples/benchmark_scores.py,
single seed (0), CPU. Return is the mean +/- std of the final deterministic policy over
evaluation episodes; random is a uniform-random policy on the same task for reference.
| Algorithm | Environment | Steps | Return (mean ± std) | Random | Time (s) |
|---|---|---|---|---|---|
| QLearning | GridWorld | 30,000 | 0.95 ± 0.00 | 0.49 | 0 |
| SARSA | GridWorld | 30,000 | 0.95 ± 0.00 | 0.44 | 1 |
| ExpectedSARSA | GridWorld | 30,000 | 0.95 ± 0.00 | 0.35 | 1 |
| DQN | CartPole | 40,000 | 103.20 ± 2.77 | 21.35 | 93 |
| C51 | CartPole | 40,000 | 500.00 ± 0.00 | 21.25 | 131 |
| QRDQN | CartPole | 40,000 | 222.40 ± 183.09 | 20.80 | 159 |
| SACDiscrete | CartPole | 15,000 | 389.40 ± 86.25 | 22.50 | 95 |
| PPO | CartPole | 40,000 | 500.00 ± 0.00 | 21.80 | 39 |
| A2C | CartPole | 40,000 | 500.00 ± 0.00 | 23.75 | 36 |
| REINFORCE | CartPole | 30,000 | 473.00 ± 44.85 | 22.10 | 11 |
| DDPG | Pendulum | 15,000 | -146.88 ± 89.75 | -1318.11 | 113 |
| TD3 | Pendulum | 15,000 | -156.05 ± 100.58 | -1314.10 | 98 |
| SAC | Pendulum | 15,000 | -148.98 ± 97.51 | -1311.03 | 160 |
| TD3BC | PointMass | 10,000 | -2.47 ± 1.24 | -36.92 | 70 |
| IQL | PointMass | 10,000 | -2.74 ± 1.25 | -36.84 | 114 |
Total wall-clock: 1119s. GridWorld optimal ≈ 0.95; CartPole max = 500; Pendulum optimal ≈ -150 (higher is better); PointMass random ≈ -42.
Comparison vs Stable-Baselines3 / CleanRL¶
The scores above are on the built-in environments. To compare decisionrl head-to-head
against established libraries on the same Gymnasium tasks, use
examples/benchmark_vs_baselines.py.
It trains matched algorithms on the same env, over several seeds and an identical step
budget, and reports mean ± std return and wall-clock side by side (results saved to JSON).
pip install stable_baselines3 # the SB3 side is skipped if not installed
python examples/benchmark_vs_baselines.py --algos ppo --env CartPole-v1 \
--seeds 5 --steps 100000
Methodology¶
- Same env, same budget, same seeds. Both libraries train on the identical
Gymnasium id for the identical
total_timesteps, then evaluate the greedy policy over 20 episodes; each library's ownevaluate_policyis used. - Library defaults. Each side uses its own default hyperparameters (this measures the out-of-the-box experience, not a tuned bake-off). For a fair tuned comparison, pass matched hyperparameters to both.
- Multiple seeds. Report the mean and std of the per-seed evaluation returns.
- CleanRL. CleanRL ships single-file reference scripts rather than an installable
package, so compare by running the corresponding script (e.g.
ppo.py) with the same--env-id,--total-timestepsand--seed, and drop its reported return into the table below.
Results¶
Actual head-to-head runs vs Stable-Baselines3 2.9.0 (evaluation return over 20 episodes, mean ± std across 3 seeds, library-default hyperparameters, CPU):
| Algorithm | Environment | Steps | Seeds | decisionrl | SB3 2.9.0 | CleanRL |
|---|---|---|---|---|---|---|
| PPO | CartPole-v1 | 50,000 | 3 | 500.0 ± 0.0 | 500.0 ± 0.0 | ~500 (published¹) |
| DQN | CartPole-v1 | 50,000 | 3 | 327 ± 122 | 96 ± 57 | ~500 (published¹) |
¹ CleanRL ships single-file reference scripts rather than an installable package, so its
column cites the returns reported in CleanRL's own docs
(CartPole-v1 is solved to ~500 by both ppo.py and dqn.py). Re-run its scripts with matched
--env-id/--total-timesteps/--seed to drop measured numbers in. The decisionrl and SB3
columns above were run head-to-head here.
- PPO reaches parity — both solve CartPole to 500/500 in the same wall-clock (~29 s/seed).
- DQN:
decisionrlscores higher at this budget, but the number is honest about two things — it is higher-variance (per-seed 500 / 245 / 238) and slower per seed (~57 s vs SB3's ~22 s; SB3's data pipeline is more optimized). At 50k steps with default hyperparameters SB3's DQN under-performs on CartPole; more steps or tuning close the gap.
Reproduce with python examples/benchmark_vs_baselines.py --algos ppo dqn --env CartPole-v1 --seeds 3 --steps 50000.
Atari and MuJoCo tasks work the same way once their extras are installed
(pip install "gymnasium[atari,accept-rom-license,mujoco]"); decisionrl reaches them
via make_env("gym:ALE/Breakout-v5") and make_atari.