stable-baselines3 2.9.0a3__tar.gz → 2.9.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. {stable_baselines3-2.9.0a3/stable_baselines3.egg-info → stable_baselines3-2.9.2}/PKG-INFO +3 -5
  2. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/README.md +10 -5
  3. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/pyproject.toml +3 -1
  4. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/setup.py +2 -4
  5. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/envs/__init__.py +0 -1
  6. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/monitor.py +3 -3
  7. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/off_policy_algorithm.py +12 -0
  8. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/policies.py +3 -3
  9. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/base_vec_env.py +2 -2
  10. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/subproc_vec_env.py +6 -0
  11. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/ddpg/ddpg.py +3 -0
  12. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/dqn/dqn.py +3 -0
  13. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/ppo/ppo.py +1 -1
  14. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/sac/sac.py +3 -0
  15. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/td3/td3.py +3 -0
  16. stable_baselines3-2.9.2/stable_baselines3/version.txt +1 -0
  17. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2/stable_baselines3.egg-info}/PKG-INFO +3 -5
  18. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3.egg-info/requires.txt +1 -3
  19. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_logger.py +8 -2
  20. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_n_step_replay.py +46 -1
  21. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_save_load.py +31 -0
  22. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_utils.py +56 -0
  23. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_vec_envs.py +1 -1
  24. stable_baselines3-2.9.0a3/stable_baselines3/version.txt +0 -1
  25. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/LICENSE +0 -0
  26. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/NOTICE +0 -0
  27. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/setup.cfg +0 -0
  28. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/__init__.py +0 -0
  29. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/a2c/__init__.py +0 -0
  30. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/a2c/a2c.py +0 -0
  31. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/a2c/policies.py +0 -0
  32. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/__init__.py +0 -0
  33. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/atari_wrappers.py +0 -0
  34. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/base_class.py +0 -0
  35. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/buffers.py +0 -0
  36. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/callbacks.py +0 -0
  37. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/distributions.py +0 -0
  38. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/env_checker.py +0 -0
  39. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/env_util.py +0 -0
  40. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/envs/bit_flipping_env.py +0 -0
  41. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/envs/identity_env.py +0 -0
  42. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/envs/multi_input_envs.py +0 -0
  43. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/evaluation.py +0 -0
  44. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/logger.py +0 -0
  45. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/noise.py +0 -0
  46. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/on_policy_algorithm.py +0 -0
  47. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/preprocessing.py +0 -0
  48. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/results_plotter.py +0 -0
  49. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/running_mean_std.py +0 -0
  50. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/save_util.py +0 -0
  51. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/sb2_compat/__init__.py +0 -0
  52. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/sb2_compat/rmsprop_tf_like.py +0 -0
  53. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/torch_layers.py +0 -0
  54. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/type_aliases.py +0 -0
  55. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/utils.py +0 -0
  56. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/__init__.py +0 -0
  57. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/dummy_vec_env.py +0 -0
  58. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/patch_gym.py +0 -0
  59. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/stacked_observations.py +0 -0
  60. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/util.py +0 -0
  61. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_check_nan.py +0 -0
  62. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_extract_dict_obs.py +0 -0
  63. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_frame_stack.py +0 -0
  64. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_monitor.py +0 -0
  65. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_normalize.py +0 -0
  66. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_transpose.py +0 -0
  67. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/common/vec_env/vec_video_recorder.py +0 -0
  68. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/ddpg/__init__.py +0 -0
  69. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/ddpg/policies.py +0 -0
  70. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/dqn/__init__.py +0 -0
  71. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/dqn/policies.py +0 -0
  72. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/her/__init__.py +0 -0
  73. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/her/goal_selection_strategy.py +0 -0
  74. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/her/her_replay_buffer.py +0 -0
  75. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/ppo/__init__.py +0 -0
  76. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/ppo/policies.py +0 -0
  77. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/py.typed +0 -0
  78. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/sac/__init__.py +0 -0
  79. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/sac/policies.py +0 -0
  80. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/td3/__init__.py +0 -0
  81. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3/td3/policies.py +0 -0
  82. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3.egg-info/SOURCES.txt +0 -0
  83. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3.egg-info/dependency_links.txt +0 -0
  84. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/stable_baselines3.egg-info/top_level.txt +0 -0
  85. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_buffers.py +0 -0
  86. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_callbacks.py +0 -0
  87. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_cnn.py +0 -0
  88. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_custom_policy.py +0 -0
  89. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_deterministic.py +0 -0
  90. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_dict_env.py +0 -0
  91. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_distributions.py +0 -0
  92. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_env_checker.py +0 -0
  93. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_envs.py +0 -0
  94. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_gae.py +0 -0
  95. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_her.py +0 -0
  96. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_identity.py +0 -0
  97. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_monitor.py +0 -0
  98. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_predict.py +0 -0
  99. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_preprocessing.py +0 -0
  100. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_run.py +0 -0
  101. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_sde.py +0 -0
  102. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_spaces.py +0 -0
  103. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_tensorboard.py +0 -0
  104. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_train_eval_mode.py +0 -0
  105. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_vec_check_nan.py +0 -0
  106. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_vec_extract_dict_obs.py +0 -0
  107. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_vec_monitor.py +0 -0
  108. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_vec_normalize.py +0 -0
  109. {stable_baselines3-2.9.0a3 → stable_baselines3-2.9.2}/tests/test_vec_stacked_obs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stable_baselines3
3
- Version: 2.9.0a3
3
+ Version: 2.9.2
4
4
  Summary: Pytorch version of Stable Baselines, implementations of reinforcement learning algorithms.
5
5
  Home-page: https://github.com/DLR-RM/stable-baselines3
6
6
  Author: Antonin Raffin
@@ -29,9 +29,7 @@ Requires-Dist: cloudpickle
29
29
  Provides-Extra: tests
30
30
  Requires-Dist: pytest; extra == "tests"
31
31
  Requires-Dist: pytest-cov; extra == "tests"
32
- Requires-Dist: pytest-env; extra == "tests"
33
- Requires-Dist: pytest-xdist; extra == "tests"
34
- Requires-Dist: mypy<2,>=1.9.0; extra == "tests"
32
+ Requires-Dist: mypy<3,>=1.9.0; extra == "tests"
35
33
  Requires-Dist: ruff>=0.5.6; extra == "tests"
36
34
  Requires-Dist: black<27,>=26.1.0; extra == "tests"
37
35
  Provides-Extra: docs
@@ -116,7 +114,7 @@ vec_env = model.get_env()
116
114
  obs = vec_env.reset()
117
115
  for i in range(1000):
118
116
  action, _states = model.predict(obs, deterministic=True)
119
- obs, reward, done, info = vec_env.step(action)
117
+ obs, rewards, dones, info = vec_env.step(action)
120
118
  vec_env.render()
121
119
  # VecEnv resets automatically
122
120
  # if done:
@@ -142,8 +142,8 @@ model.learn(total_timesteps=10_000)
142
142
  vec_env = model.get_env()
143
143
  obs = vec_env.reset()
144
144
  for i in range(1000):
145
- action, _states = model.predict(obs, deterministic=True)
146
- obs, reward, done, info = vec_env.step(action)
145
+ actions, _states = model.predict(obs, deterministic=True)
146
+ obs, rewards, dones, info = vec_env.step(actions)
147
147
  vec_env.render()
148
148
  # VecEnv resets automatically
149
149
  # if done:
@@ -182,23 +182,28 @@ All the following examples can be executed online using Google Colab notebooks:
182
182
 
183
183
  | **Name** | **Recurrent** | `Box` | `Discrete` | `MultiDiscrete` | `MultiBinary` | **Multi Processing** |
184
184
  | ------------------- | ------------------ | ------------------ | ------------------ | ------------------- | ------------------ | --------------------------------- |
185
- | ARS<sup>[1](#f1)</sup> | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
186
185
  | A2C | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
187
- | CrossQ<sup>[1](#f1)</sup> | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
186
+ | ARS<sup>[1](#f1)</sup> | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
187
+ | CrossQ<sup>[1](#f1)[2](#f2)</sup> | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
188
188
  | DDPG | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
189
189
  | DQN | :x: | :x: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
190
+ | DroQ<sup>[2](#f2)</sup> | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
190
191
  | HER | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
192
+ | Maskable PPO<sup>[1](#f1)</sup> | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
191
193
  | PPO | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
192
194
  | QR-DQN<sup>[1](#f1)</sup> | :x: | :x: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
193
195
  | RecurrentPPO<sup>[1](#f1)</sup> | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
194
196
  | SAC | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
197
+ | SAC-N<sup>[2](#f2)</sup> | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
198
+ | SimBa<sup>[2](#f2)</sup> | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
195
199
  | TD3 | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
196
200
  | TQC<sup>[1](#f1)</sup> | :x: | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
197
201
  | TRPO<sup>[1](#f1)</sup> | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
198
- | Maskable PPO<sup>[1](#f1)</sup> | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
199
202
 
200
203
  <b id="f1">1</b>: Implemented in [SB3 Contrib](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib) GitHub repository.
201
204
 
205
+ <b id="f2">2</b>: Implemented in [SBX (SB3 + Jax)](https://github.com/araffin/sbx)
206
+
202
207
  Actions `gymnasium.spaces`:
203
208
  * `Box`: A N-dimensional box that contains every point in the action space.
204
209
  * `Discrete`: A list of possible actions, where only one action can be used per timestep.
@@ -36,7 +36,7 @@ exclude = """(?x)(
36
36
 
37
37
  [tool.pytest.ini_options]
38
38
  # Deterministic ordering for tests; useful for pytest-xdist.
39
- env = ["PYTHONHASHSEED=0"]
39
+ # env = ["PYTHONHASHSEED=0"]
40
40
 
41
41
  filterwarnings = [
42
42
  # multiprocessing and fork method, use of fork may lead to deadlocks
@@ -45,6 +45,8 @@ filterwarnings = [
45
45
  "ignore:You are trying to run (PPO|A2C) on the GPU",
46
46
  # Tensorboard warnings
47
47
  "ignore::DeprecationWarning:tensorboard",
48
+ # Torch tensorboard numpy newshape deprecation
49
+ "ignore:`newshape` keyword argument is deprecated:DeprecationWarning:torch.utils.tensorboard._utils",
48
50
  # Gymnasium warnings
49
51
  "ignore::UserWarning:gymnasium",
50
52
  # Taxi-v3 and CliffWalking-v0
@@ -55,7 +55,7 @@ vec_env = model.get_env()
55
55
  obs = vec_env.reset()
56
56
  for i in range(1000):
57
57
  action, _states = model.predict(obs, deterministic=True)
58
- obs, reward, done, info = vec_env.step(action)
58
+ obs, rewards, dones, info = vec_env.step(action)
59
59
  vec_env.render()
60
60
  # VecEnv resets automatically
61
61
  # if done:
@@ -90,10 +90,8 @@ setup(
90
90
  # Run tests and coverage
91
91
  "pytest",
92
92
  "pytest-cov",
93
- "pytest-env",
94
- "pytest-xdist",
95
93
  # Type check
96
- "mypy>=1.9.0,<2",
94
+ "mypy>=1.9.0,<3",
97
95
  # Lint code and sort imports (flake8 and isort replacement)
98
96
  "ruff>=0.5.6",
99
97
  # Reformat
@@ -16,5 +16,4 @@ __all__ = [
16
16
  "IdentityEnvMultiBinary",
17
17
  "IdentityEnvMultiDiscrete",
18
18
  "SimpleMultiObsEnv",
19
- "SimpleMultiObsEnv",
20
19
  ]
@@ -262,10 +262,10 @@ def load_results(path: str) -> "pandas.DataFrame":
262
262
  # Only empty monitor files, return empty df
263
263
  empty_df = pandas.DataFrame(columns=["r", "l", "t"])
264
264
  # Create index to have the same columns
265
- empty_df.reset_index(inplace=True)
265
+ empty_df = empty_df.reset_index()
266
266
  return empty_df
267
267
  data_frame = pandas.concat(data_frames)
268
- data_frame.sort_values("t", inplace=True)
269
- data_frame.reset_index(inplace=True)
268
+ data_frame = data_frame.sort_values("t")
269
+ data_frame = data_frame.reset_index()
270
270
  data_frame["t"] -= min(header["t_start"] for header in headers)
271
271
  return data_frame
@@ -52,6 +52,9 @@ class OffPolicyAlgorithm(BaseAlgorithm):
52
52
  at a cost of more complexity.
53
53
  See https://github.com/DLR-RM/stable-baselines3/issues/37#issuecomment-637501195
54
54
  :param n_steps: When n_step > 1, uses n-step return (with the NStepReplayBuffer) when updating the Q-value network.
55
+ Note: it is only used when ``replay_buffer_class`` is ``None``, and is not supported for Dict
56
+ observation spaces yet. When passing a custom ``replay_buffer_class``, configure it directly
57
+ with ``replay_buffer_kwargs={"n_steps": ..., "gamma": ...}`` instead.
55
58
  :param policy_kwargs: Additional arguments to be passed to the policy on creation
56
59
  :param stats_window_size: Window size for the rollout logging, specifying the number of episodes to average
57
60
  the reported success rate, mean episode length, and mean reward over
@@ -175,6 +178,15 @@ class OffPolicyAlgorithm(BaseAlgorithm):
175
178
  self._setup_lr_schedule()
176
179
  self.set_random_seed(self.seed)
177
180
 
181
+ if self.n_steps > 1 and self.replay_buffer_class is not None:
182
+ warnings.warn(
183
+ f"`n_steps={self.n_steps}` is ignored because a custom `replay_buffer_class` "
184
+ f"(`{self.replay_buffer_class.__name__}`) was passed: n-step returns are only set up "
185
+ "automatically when `replay_buffer_class` is `None`. "
186
+ "To use n-step returns with a custom replay buffer, configure it explicitly, e.g. "
187
+ f'`replay_buffer_kwargs={{"n_steps": {self.n_steps}, "gamma": {self.gamma}}}`.'
188
+ )
189
+
178
190
  if self.replay_buffer_class is None:
179
191
  if isinstance(self.observation_space, spaces.Dict):
180
192
  self.replay_buffer_class = DictReplayBuffer
@@ -257,7 +257,7 @@ class BaseModel(nn.Module):
257
257
  obs_ = np.array(obs)
258
258
  vectorized_env = vectorized_env or is_vectorized_observation(obs_, obs_space)
259
259
  # Add batch dimension if needed
260
- observation[key] = obs_.reshape((-1, *self.observation_space[key].shape)) # type: ignore[misc]
260
+ observation[key] = obs_.reshape((-1, *self.observation_space[key].shape)) # type: ignore[misc, arg-type]
261
261
 
262
262
  elif is_image_space(self.observation_space):
263
263
  # Handle the different cases for images
@@ -271,7 +271,7 @@ class BaseModel(nn.Module):
271
271
  # Dict obs need to be handled separately
272
272
  vectorized_env = is_vectorized_observation(observation, self.observation_space)
273
273
  # Add batch dimension if needed
274
- observation = observation.reshape((-1, *self.observation_space.shape)) # type: ignore[misc]
274
+ observation = observation.reshape((-1, *self.observation_space.shape)) # type: ignore[misc, arg-type]
275
275
 
276
276
  obs_tensor = obs_as_tensor(observation, self.device)
277
277
  return obs_tensor, vectorized_env
@@ -367,7 +367,7 @@ class BasePolicy(BaseModel, ABC):
367
367
  with th.no_grad():
368
368
  actions = self._predict(obs_tensor, deterministic=deterministic)
369
369
  # Convert to numpy, and reshape to the original action shape
370
- actions = actions.cpu().numpy().reshape((-1, *self.action_space.shape)) # type: ignore[misc, assignment]
370
+ actions = actions.cpu().numpy().reshape((-1, *self.action_space.shape)) # type: ignore[misc, assignment, arg-type]
371
371
 
372
372
  if isinstance(self.action_space, spaces.Box):
373
373
  if self.squash_output:
@@ -289,7 +289,7 @@ class VecEnv(ABC):
289
289
  self.env_method("render")
290
290
  return None
291
291
 
292
- def seed(self, seed: int | None = None) -> Sequence[None | int]:
292
+ def seed(self, seed: int | None = None) -> Sequence[int | None]:
293
293
  """
294
294
  Sets the random seeds for all environments, based on a given seed.
295
295
  Each individual environment will still get its own seed, by incrementing the given seed.
@@ -392,7 +392,7 @@ class VecEnvWrapper(VecEnv):
392
392
  def step_wait(self) -> VecEnvStepReturn:
393
393
  pass
394
394
 
395
- def seed(self, seed: int | None = None) -> Sequence[None | int]:
395
+ def seed(self, seed: int | None = None) -> Sequence[int | None]:
396
396
  return self.venv.seed(seed)
397
397
 
398
398
  def set_options(self, options: list[dict] | dict | None = None) -> None:
@@ -159,6 +159,12 @@ class SubprocVecEnv(VecEnv):
159
159
  remote.send(("close", None))
160
160
  for process in self.processes:
161
161
  process.join()
162
+ # Close the parent side of the pipes: otherwise the sockets stay open
163
+ # until this instance (and its ``remotes``) is garbage collected,
164
+ # which can exhaust the file-descriptor limit (``Too many open files``)
165
+ # in long-running loops (e.g. hyperparameter optimization).
166
+ for remote in self.remotes:
167
+ remote.close()
162
168
  self.closed = True
163
169
 
164
170
  def get_images(self) -> Sequence[np.ndarray | None]:
@@ -45,6 +45,9 @@ class DDPG(TD3):
45
45
  at a cost of more complexity.
46
46
  See https://github.com/DLR-RM/stable-baselines3/issues/37#issuecomment-637501195
47
47
  :param n_steps: When n_step > 1, uses n-step return (with the NStepReplayBuffer) when updating the Q-value network.
48
+ Note: it is only used when ``replay_buffer_class`` is ``None``, and is not supported for Dict
49
+ observation spaces yet. When passing a custom ``replay_buffer_class``, configure it directly
50
+ with ``replay_buffer_kwargs={"n_steps": ..., "gamma": ...}`` instead.
48
51
  :param policy_kwargs: additional arguments to be passed to the policy on creation. See :ref:`ddpg_policies`
49
52
  :param verbose: Verbosity level: 0 for no output, 1 for info messages (such as device or wrappers used), 2 for
50
53
  debug messages
@@ -45,6 +45,9 @@ class DQN(OffPolicyAlgorithm):
45
45
  at a cost of more complexity.
46
46
  See https://github.com/DLR-RM/stable-baselines3/issues/37#issuecomment-637501195
47
47
  :param n_steps: When n_step > 1, uses n-step return (with the NStepReplayBuffer) when updating the Q-value network.
48
+ Note: it is only used when ``replay_buffer_class`` is ``None``, and is not supported for Dict
49
+ observation spaces yet. When passing a custom ``replay_buffer_class``, configure it directly
50
+ with ``replay_buffer_kwargs={"n_steps": ..., "gamma": ...}`` instead.
48
51
  :param target_update_interval: update the target network every ``target_update_interval``
49
52
  environment steps.
50
53
  :param exploration_fraction: fraction of entire training period over which the exploration rate is reduced
@@ -88,7 +88,7 @@ class PPO(OnPolicyAlgorithm):
88
88
  gamma: float = 0.99,
89
89
  gae_lambda: float = 0.95,
90
90
  clip_range: float | Schedule = 0.2,
91
- clip_range_vf: None | float | Schedule = None,
91
+ clip_range_vf: float | Schedule | None = None,
92
92
  normalize_advantage: bool = True,
93
93
  ent_coef: float = 0.0,
94
94
  vf_coef: float = 0.5,
@@ -54,6 +54,9 @@ class SAC(OffPolicyAlgorithm):
54
54
  at a cost of more complexity.
55
55
  See https://github.com/DLR-RM/stable-baselines3/issues/37#issuecomment-637501195
56
56
  :param n_steps: When n_step > 1, uses n-step return (with the NStepReplayBuffer) when updating the Q-value network.
57
+ Note: it is only used when ``replay_buffer_class`` is ``None``, and is not supported for Dict
58
+ observation spaces yet. When passing a custom ``replay_buffer_class``, configure it directly
59
+ with ``replay_buffer_kwargs={"n_steps": ..., "gamma": ...}`` instead.
57
60
  :param ent_coef: Entropy regularization coefficient. (Equivalent to
58
61
  inverse of reward scale in the original SAC paper.) Controlling exploration/exploitation trade-off.
59
62
  Set it to 'auto' to learn it automatically (and 'auto_0.1' for using 0.1 as initial value)
@@ -49,6 +49,9 @@ class TD3(OffPolicyAlgorithm):
49
49
  at a cost of more complexity.
50
50
  See https://github.com/DLR-RM/stable-baselines3/issues/37#issuecomment-637501195
51
51
  :param n_steps: When n_step > 1, uses n-step return (with the NStepReplayBuffer) when updating the Q-value network.
52
+ Note: it is only used when ``replay_buffer_class`` is ``None``, and is not supported for Dict
53
+ observation spaces yet. When passing a custom ``replay_buffer_class``, configure it directly
54
+ with ``replay_buffer_kwargs={"n_steps": ..., "gamma": ...}`` instead.
52
55
  :param policy_delay: Policy and target networks will only be updated once every policy_delay steps
53
56
  per training steps. The Q values will be updated policy_delay more often (update every training step).
54
57
  :param target_policy_noise: Standard deviation of Gaussian noise added to target policy
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stable_baselines3
3
- Version: 2.9.0a3
3
+ Version: 2.9.2
4
4
  Summary: Pytorch version of Stable Baselines, implementations of reinforcement learning algorithms.
5
5
  Home-page: https://github.com/DLR-RM/stable-baselines3
6
6
  Author: Antonin Raffin
@@ -29,9 +29,7 @@ Requires-Dist: cloudpickle
29
29
  Provides-Extra: tests
30
30
  Requires-Dist: pytest; extra == "tests"
31
31
  Requires-Dist: pytest-cov; extra == "tests"
32
- Requires-Dist: pytest-env; extra == "tests"
33
- Requires-Dist: pytest-xdist; extra == "tests"
34
- Requires-Dist: mypy<2,>=1.9.0; extra == "tests"
32
+ Requires-Dist: mypy<3,>=1.9.0; extra == "tests"
35
33
  Requires-Dist: ruff>=0.5.6; extra == "tests"
36
34
  Requires-Dist: black<27,>=26.1.0; extra == "tests"
37
35
  Provides-Extra: docs
@@ -116,7 +114,7 @@ vec_env = model.get_env()
116
114
  obs = vec_env.reset()
117
115
  for i in range(1000):
118
116
  action, _states = model.predict(obs, deterministic=True)
119
- obs, reward, done, info = vec_env.step(action)
117
+ obs, rewards, dones, info = vec_env.step(action)
120
118
  vec_env.render()
121
119
  # VecEnv resets automatically
122
120
  # if done:
@@ -26,8 +26,6 @@ matplotlib
26
26
  [tests]
27
27
  pytest
28
28
  pytest-cov
29
- pytest-env
30
- pytest-xdist
31
- mypy<2,>=1.9.0
29
+ mypy<3,>=1.9.0
32
30
  ruff>=0.5.6
33
31
  black<27,>=26.1.0
@@ -1,4 +1,3 @@
1
- import importlib.util
2
1
  import json
3
2
  import os
4
3
  import sys
@@ -273,7 +272,14 @@ def test_report_video_to_tensorboard(tmp_path, read_log, capsys):
273
272
 
274
273
 
275
274
  def is_moviepy_installed():
276
- return importlib.util.find_spec("moviepy") is not None
275
+ try:
276
+ import moviepy
277
+
278
+ # PyTorch doesn't support moviepy >= 2.0
279
+ # See: https://github.com/pytorch/pytorch/issues/147317
280
+ return moviepy.__version__ < "2.0"
281
+ except (ImportError, AttributeError):
282
+ return False
277
283
 
278
284
 
279
285
  @pytest.mark.parametrize("unsupported_format", ["stdout", "log", "json", "csv"])
@@ -1,10 +1,14 @@
1
+ import warnings
2
+
1
3
  import gymnasium as gym
2
4
  import numpy as np
3
5
  import pytest
4
6
 
5
7
  from stable_baselines3 import DQN, SAC, TD3
6
- from stable_baselines3.common.buffers import NStepReplayBuffer, ReplayBuffer
8
+ from stable_baselines3.common.buffers import DictReplayBuffer, NStepReplayBuffer, ReplayBuffer
7
9
  from stable_baselines3.common.env_util import make_vec_env
10
+ from stable_baselines3.common.envs import BitFlippingEnv
11
+ from stable_baselines3.her import HerReplayBuffer
8
12
 
9
13
 
10
14
  @pytest.mark.parametrize("model_class", [SAC, DQN, TD3])
@@ -30,6 +34,47 @@ def test_run(model_class):
30
34
  model.learn(total_timesteps=150)
31
35
 
32
36
 
37
+ @pytest.mark.parametrize("replay_buffer_class", [ReplayBuffer, NStepReplayBuffer])
38
+ def test_n_steps_warns_with_custom_replay_buffer_class(replay_buffer_class):
39
+ """`n_steps > 1` is ignored when the buffer class is user-provided, so it must warn."""
40
+ with pytest.warns(UserWarning, match="n_steps=3"):
41
+ model = SAC("MlpPolicy", "Pendulum-v1", n_steps=3, buffer_size=200, replay_buffer_class=replay_buffer_class)
42
+ # The buffer is built from the user-provided class, untouched by `n_steps`
43
+ assert type(model.replay_buffer) is replay_buffer_class
44
+
45
+
46
+ @pytest.mark.parametrize("replay_buffer_class", [None, DictReplayBuffer, HerReplayBuffer])
47
+ def test_n_steps_with_dict_obs(replay_buffer_class):
48
+ """Dict observation spaces do not support n-step returns: assert on the default path, warn otherwise."""
49
+ env = BitFlippingEnv(n_bits=4, continuous=True)
50
+ if replay_buffer_class is None:
51
+ with pytest.raises(AssertionError, match="Dict observation spaces"):
52
+ SAC("MultiInputPolicy", env, n_steps=3, buffer_size=200)
53
+ else:
54
+ with pytest.warns(UserWarning, match="n_steps=3"):
55
+ SAC("MultiInputPolicy", env, n_steps=3, buffer_size=200, replay_buffer_class=replay_buffer_class)
56
+
57
+
58
+ def test_n_steps_custom_class_no_warnings():
59
+ with warnings.catch_warnings():
60
+ warnings.simplefilter("error")
61
+ # Note: values must differ from ``NStepReplayBuffer`` defaults (n_steps=3, gamma=0.99)
62
+ # otherwise the assertions below would pass even if nothing was applied.
63
+ model = SAC(
64
+ "MlpPolicy",
65
+ "Pendulum-v1",
66
+ buffer_size=200,
67
+ replay_buffer_class=NStepReplayBuffer,
68
+ replay_buffer_kwargs={"n_steps": 4, "gamma": 0.95},
69
+ )
70
+ assert isinstance(model.replay_buffer, NStepReplayBuffer)
71
+ assert model.replay_buffer.n_steps == 4
72
+ assert model.replay_buffer.gamma == 0.95
73
+
74
+ # Default n-steps
75
+ SAC("MlpPolicy", "Pendulum-v1", buffer_size=200, replay_buffer_class=ReplayBuffer)
76
+
77
+
33
78
  def create_buffer(buffer_size=10, n_steps=3, gamma=0.99, n_envs=1):
34
79
  obs_space = gym.spaces.Box(low=0, high=1, shape=(4,), dtype=np.float32)
35
80
  act_space = gym.spaces.Box(low=0, high=1, shape=(2,), dtype=np.float32)
@@ -891,3 +891,34 @@ def test_save_load_clip_range_portable(tmp_path, model_class):
891
891
  assert isinstance(model.clip_range, FloatSchedule)
892
892
  assert isinstance(model.clip_range.value_schedule, ConstantSchedule)
893
893
  assert model.clip_range.value_schedule.val == 0.2
894
+
895
+
896
+ def test_load_bad_zip(tmp_path):
897
+ """Test that loading a non-zip file raises a ValueError."""
898
+ # Write a plain text file to the path
899
+ bad_path = tmp_path / "not_a_zip.zip"
900
+ bad_path.write_text("this is not a zip file")
901
+
902
+ with pytest.raises(ValueError, match="wasn't a zip-file"):
903
+ PPO.load(str(bad_path))
904
+
905
+
906
+ @pytest.mark.filterwarnings("error::ResourceWarning")
907
+ def test_open_path_directory_and_missing_parent(tmp_path):
908
+ """Test IsADirectoryError and FileNotFoundError handling in open_path."""
909
+ # Test IsADirectoryError: path already has the suffix and is a folder
910
+ dir_path = tmp_path / "is_a_folder.pkl"
911
+ dir_path.mkdir()
912
+ with warnings.catch_warnings(record=True) as record:
913
+ open_path(dir_path, "w", suffix="pkl").close()
914
+ assert any("is a folder" in str(warning.message) for warning in record)
915
+ # Verify the fallback file was created
916
+ assert (tmp_path / "is_a_folder.pkl_2").exists()
917
+
918
+ # Test FileNotFoundError: parent folder doesn't exist
919
+ missing_parent_path = tmp_path / "nonexistent_parent" / "sub" / "file"
920
+ with warnings.catch_warnings(record=True) as record:
921
+ open_path(missing_parent_path, "w", suffix="pkl").close()
922
+ assert any("does not exist" in str(warning.message) for warning in record)
923
+ # Verify the parent was created and file was written
924
+ assert (tmp_path / "nonexistent_parent" / "sub" / "file.pkl").exists()
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import pickle
2
3
  import shutil
3
4
 
4
5
  import ale_py
@@ -15,6 +16,7 @@ from stable_baselines3.common.env_util import is_wrapped, make_atari_env, make_v
15
16
  from stable_baselines3.common.evaluation import evaluate_policy
16
17
  from stable_baselines3.common.monitor import Monitor
17
18
  from stable_baselines3.common.noise import OrnsteinUhlenbeckActionNoise, VectorizedActionNoise
19
+ from stable_baselines3.common.sb2_compat.rmsprop_tf_like import RMSpropTFLike
18
20
  from stable_baselines3.common.utils import (
19
21
  ConstantSchedule,
20
22
  FloatSchedule,
@@ -628,3 +630,57 @@ def test_deprecated_schedules():
628
630
  assert np.allclose(fn(0.5), schedule(0.5))
629
631
  assert np.allclose(fn(0.5), float_schedule(0.5))
630
632
  assert np.allclose(fn(0.5), float_schedule_2(0.5))
633
+
634
+
635
+ class TestRMSpropTFLike:
636
+ """Tests for the RMSpropTFLike optimizer (sb2_compat)."""
637
+
638
+ def test_invalid_params(self):
639
+ """Test that invalid optimizer parameters raise ValueError."""
640
+ param = th.nn.Parameter(th.zeros(2))
641
+ with pytest.raises(ValueError, match="Invalid learning rate"):
642
+ RMSpropTFLike([param], lr=-1.0)
643
+ with pytest.raises(ValueError, match="Invalid epsilon"):
644
+ RMSpropTFLike([param], eps=-1.0)
645
+ with pytest.raises(ValueError, match="Invalid momentum"):
646
+ RMSpropTFLike([param], momentum=-1.0)
647
+ with pytest.raises(ValueError, match="Invalid weight_decay"):
648
+ RMSpropTFLike([param], weight_decay=-1.0)
649
+ with pytest.raises(ValueError, match="Invalid alpha"):
650
+ RMSpropTFLike([param], alpha=-1.0)
651
+
652
+ def test_centered_momentum_weight_decay(self):
653
+ """Test centered=True, momentum>0, weight_decay>0 branches in step()."""
654
+ param = th.nn.Parameter(th.tensor([1.0, 2.0]))
655
+ opt = RMSpropTFLike(
656
+ [param],
657
+ lr=0.1,
658
+ momentum=0.9,
659
+ alpha=0.99,
660
+ eps=1e-8,
661
+ centered=True,
662
+ weight_decay=0.01,
663
+ )
664
+ # Compute gradient
665
+ loss = (param**2).sum()
666
+ loss.backward()
667
+
668
+ # Run step with closure (covers closure branch)
669
+ def closure():
670
+ param.grad.zero_()
671
+ return float((param**2).sum().detach())
672
+
673
+ opt.step(closure=closure)
674
+ # Check state keys exist (covers centered + momentum init)
675
+ state = opt.state[param]
676
+ assert "grad_avg" in state # centered=True
677
+ assert "momentum_buffer" in state # momentum > 0
678
+
679
+ def test_pickle_roundtrip(self):
680
+ """Test that optimizer survives pickle roundtrip (covers __setstate__)."""
681
+ param = th.nn.Parameter(th.tensor([1.0, 2.0]))
682
+ opt = RMSpropTFLike([param], lr=0.1, momentum=0.5, centered=True)
683
+ opt2 = pickle.loads(pickle.dumps(opt))
684
+ assert opt2.param_groups[0]["lr"] == 0.1
685
+ assert opt2.param_groups[0]["momentum"] == 0.5
686
+ assert opt2.param_groups[0]["centered"] is True
@@ -317,7 +317,7 @@ def check_vecenv_obs(obs, space):
317
317
  assert space.contains(value)
318
318
 
319
319
 
320
- @pytest.mark.parametrize("vec_env_class,space", itertools.product(VEC_ENV_CLASSES, SPACES.values()))
320
+ @pytest.mark.parametrize("vec_env_class,space", list(itertools.product(VEC_ENV_CLASSES, SPACES.values())))
321
321
  def test_vecenv_single_space(vec_env_class, space):
322
322
  def obs_assert(obs):
323
323
  return check_vecenv_obs(obs, space)
@@ -1 +0,0 @@
1
- 2.9.0a3