drlab 0.2.4__tar.gz → 0.2.6__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 (44) hide show
  1. {drlab-0.2.4/src/drlab.egg-info → drlab-0.2.6}/PKG-INFO +1 -1
  2. {drlab-0.2.4 → drlab-0.2.6}/pyproject.toml +1 -1
  3. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/__init__.py +1 -1
  4. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/off_policy/base.py +29 -6
  5. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/off_policy/dqn.py +1 -1
  6. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/off_policy/sac.py +25 -21
  7. {drlab-0.2.4 → drlab-0.2.6/src/drlab.egg-info}/PKG-INFO +1 -1
  8. {drlab-0.2.4 → drlab-0.2.6}/tests/test_learners.py +42 -4
  9. {drlab-0.2.4 → drlab-0.2.6}/tests/test_public_api.py +1 -1
  10. {drlab-0.2.4 → drlab-0.2.6}/LICENSE +0 -0
  11. {drlab-0.2.4 → drlab-0.2.6}/README.md +0 -0
  12. {drlab-0.2.4 → drlab-0.2.6}/setup.cfg +0 -0
  13. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/__init__.py +0 -0
  14. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/base.py +0 -0
  15. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/e_greedy.py +0 -0
  16. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/gaussian.py +0 -0
  17. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/greedy.py +0 -0
  18. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/stochastic.py +0 -0
  19. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/controllers/warmup.py +0 -0
  20. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/experiments/__init__.py +0 -0
  21. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/experiments/off_policy_experiment.py +0 -0
  22. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/experiments/on_policy_experiment.py +0 -0
  23. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/__init__.py +0 -0
  24. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/off_policy/__init__.py +0 -0
  25. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/off_policy/configs.py +0 -0
  26. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/on_policy/__init__.py +0 -0
  27. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/on_policy/actor_critic.py +0 -0
  28. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/on_policy/base.py +0 -0
  29. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/on_policy/configs.py +0 -0
  30. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/on_policy/ppo.py +0 -0
  31. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/learners/on_policy/reinforce.py +0 -0
  32. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/replay/__init__.py +0 -0
  33. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/replay/replay_buffer.py +0 -0
  34. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/replay/transition_batch.py +0 -0
  35. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/runners/__init__.py +0 -0
  36. {drlab-0.2.4 → drlab-0.2.6}/src/drlab/runners/runner.py +0 -0
  37. {drlab-0.2.4 → drlab-0.2.6}/src/drlab.egg-info/SOURCES.txt +0 -0
  38. {drlab-0.2.4 → drlab-0.2.6}/src/drlab.egg-info/dependency_links.txt +0 -0
  39. {drlab-0.2.4 → drlab-0.2.6}/src/drlab.egg-info/requires.txt +0 -0
  40. {drlab-0.2.4 → drlab-0.2.6}/src/drlab.egg-info/top_level.txt +0 -0
  41. {drlab-0.2.4 → drlab-0.2.6}/tests/test_controllers.py +0 -0
  42. {drlab-0.2.4 → drlab-0.2.6}/tests/test_off_policy_experiment.py +0 -0
  43. {drlab-0.2.4 → drlab-0.2.6}/tests/test_replay.py +0 -0
  44. {drlab-0.2.4 → drlab-0.2.6}/tests/test_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drlab
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Deep Reinforcement Learning kit for research.
5
5
  Author: Tomas Osarte
6
6
  Keywords: reinforcement-learning,deep-learning,pytorch,gymnasium
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "drlab"
7
- version = "0.2.4"
7
+ version = "0.2.6"
8
8
  description = "Deep Reinforcement Learning kit for research."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -35,7 +35,7 @@ from drlab.learners import (
35
35
  from drlab.replay import ReplayBuffer, TransitionBatch
36
36
  from drlab.runners import Runner
37
37
 
38
- __version__ = "0.2.4"
38
+ __version__ = "0.2.6"
39
39
 
40
40
  __all__ = [
41
41
  "__version__",
@@ -52,6 +52,26 @@ class OffPolicyLearner(ABC):
52
52
 
53
53
  return target
54
54
 
55
+ @staticmethod
56
+ def _validate_optimizer_parameters(
57
+ optimizer: th.optim.Optimizer,
58
+ expected_parameters: Iterable[th.nn.Parameter],
59
+ optimizer_name: str,
60
+ ) -> None:
61
+ expected_parameter_ids = sorted(
62
+ id(parameter) for parameter in expected_parameters
63
+ )
64
+ optimizer_parameter_ids = sorted(
65
+ id(parameter)
66
+ for group in optimizer.param_groups
67
+ for parameter in group["params"]
68
+ )
69
+
70
+ if optimizer_parameter_ids != expected_parameter_ids:
71
+ raise ValueError(
72
+ f"{optimizer_name} must contain exactly its model parameters."
73
+ )
74
+
55
75
  def _hard_update(self, target: th.nn.Module, source: th.nn.Module):
56
76
  target.load_state_dict(source.state_dict())
57
77
  target.eval()
@@ -133,18 +153,21 @@ class OffPolicyLearner(ABC):
133
153
  self,
134
154
  loss: th.Tensor,
135
155
  optimizer: th.optim.Optimizer,
136
- parameters: Iterable[th.nn.Parameter],
156
+ parameters: list[Iterable[th.nn.Parameter]],
137
157
  clipnorm: float | None = None,
138
158
  ) -> None:
139
- parameters = tuple(parameters)
159
+ parameter_groups = [tuple(group) for group in parameters]
160
+ parameters = [
161
+ parameter
162
+ for group in parameter_groups
163
+ for parameter in group
164
+ ]
140
165
  optimizer.zero_grad(set_to_none=True)
141
166
  loss.backward(inputs=parameters)
142
167
 
143
168
  if clipnorm is not None:
144
- th.nn.utils.clip_grad_norm_(
145
- parameters,
146
- clipnorm,
147
- )
169
+ for group in parameter_groups:
170
+ th.nn.utils.clip_grad_norm_(group, clipnorm)
148
171
 
149
172
  optimizer.step()
150
173
 
@@ -88,7 +88,7 @@ class DQNLearner(OffPolicyLearner):
88
88
  self.optimize(
89
89
  loss,
90
90
  optimizer=self.optimizer,
91
- parameters=self.model.parameters(),
91
+ parameters=[self.model.parameters()],
92
92
  clipnorm=self.clipnorm,
93
93
  )
94
94
 
@@ -15,8 +15,7 @@ class SACLearner(OffPolicyLearner):
15
15
  critic1: th.nn.Module,
16
16
  critic2: th.nn.Module,
17
17
  actor_optimizer: th.optim.Optimizer,
18
- critic1_optimizer: th.optim.Optimizer,
19
- critic2_optimizer: th.optim.Optimizer,
18
+ critic_optimizer: th.optim.Optimizer,
20
19
  config: SACConfig,
21
20
  ):
22
21
  super().__init__(config)
@@ -32,8 +31,21 @@ class SACLearner(OffPolicyLearner):
32
31
  self.critic2_target = self.make_target_model(self.critic2)
33
32
 
34
33
  self.actor_optimizer = actor_optimizer
35
- self.critic1_optimizer = critic1_optimizer
36
- self.critic2_optimizer = critic2_optimizer
34
+ self.critic_optimizer = critic_optimizer
35
+
36
+ self._validate_optimizer_parameters(
37
+ self.actor_optimizer,
38
+ self.actor.parameters(),
39
+ "actor_optimizer",
40
+ )
41
+ self._validate_optimizer_parameters(
42
+ self.critic_optimizer,
43
+ [
44
+ *self.critic1.parameters(),
45
+ *self.critic2.parameters(),
46
+ ],
47
+ "critic_optimizer",
48
+ )
37
49
 
38
50
  self.criterion = config.criterion
39
51
 
@@ -127,23 +139,15 @@ class SACLearner(OffPolicyLearner):
127
139
  critic1_loss = self.criterion(current_q1, targets)
128
140
  critic2_loss = self.criterion(current_q2, targets)
129
141
  critic_loss = critic1_loss + critic2_loss
130
- self.critic1_optimizer.zero_grad(set_to_none=True)
131
- self.critic2_optimizer.zero_grad(set_to_none=True)
132
- critic_loss.backward()
133
-
134
- if self.clipnorm is not None:
135
- # Clip each critic independently to preserve the previous behavior.
136
- th.nn.utils.clip_grad_norm_(
142
+ self.optimize(
143
+ critic_loss,
144
+ optimizer=self.critic_optimizer,
145
+ parameters=[
137
146
  self.critic1.parameters(),
138
- self.clipnorm,
139
- )
140
- th.nn.utils.clip_grad_norm_(
141
147
  self.critic2.parameters(),
142
- self.clipnorm,
143
- )
144
-
145
- self.critic1_optimizer.step()
146
- self.critic2_optimizer.step()
148
+ ],
149
+ clipnorm=self.clipnorm,
150
+ )
147
151
 
148
152
  # --------------------------------------------------
149
153
  # 2. Update actor
@@ -167,7 +171,7 @@ class SACLearner(OffPolicyLearner):
167
171
  self.optimize(
168
172
  actor_loss,
169
173
  optimizer=self.actor_optimizer,
170
- parameters=self.actor.parameters(),
174
+ parameters=[self.actor.parameters()],
171
175
  clipnorm=self.clipnorm,
172
176
  )
173
177
 
@@ -181,7 +185,7 @@ class SACLearner(OffPolicyLearner):
181
185
  self.optimize(
182
186
  alpha_loss,
183
187
  optimizer=self.alpha_optimizer,
184
- parameters=[self.log_alpha],
188
+ parameters=[[self.log_alpha]],
185
189
  clipnorm=self.clipnorm,
186
190
  )
187
191
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drlab
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Deep Reinforcement Learning kit for research.
5
5
  Author: Tomas Osarte
6
6
  Keywords: reinforcement-learning,deep-learning,pytorch,gymnasium
@@ -143,8 +143,10 @@ class LearnerSmokeTest(unittest.TestCase):
143
143
  critic1=critic1,
144
144
  critic2=critic2,
145
145
  actor_optimizer=th.optim.SGD(actor.parameters(), lr=0.05),
146
- critic1_optimizer=th.optim.SGD(critic1.parameters(), lr=0.05),
147
- critic2_optimizer=th.optim.SGD(critic2.parameters(), lr=0.05),
146
+ critic_optimizer=th.optim.SGD(
147
+ [*critic1.parameters(), *critic2.parameters()],
148
+ lr=0.05,
149
+ ),
148
150
  config=SACConfig(action_shape=(action_dim,), initial_alpha=0.2),
149
151
  )
150
152
  actor_before = [param.detach().clone() for param in actor.parameters()]
@@ -217,6 +219,40 @@ class LearnerSmokeTest(unittest.TestCase):
217
219
  with self.assertRaisesRegex(ValueError, "initial_alpha must be > 0"):
218
220
  SACConfig(initial_alpha=0.0)
219
221
 
222
+ def test_sac_validates_actor_and_critic_optimizer_parameters(self):
223
+ obs_dim = 4
224
+ action_dim = 2
225
+ actor = th.nn.Linear(obs_dim, 2 * action_dim)
226
+ critic1 = th.nn.Linear(obs_dim + action_dim, 1)
227
+ critic2 = th.nn.Linear(obs_dim + action_dim, 1)
228
+ critic_parameters = [*critic1.parameters(), *critic2.parameters()]
229
+
230
+ with self.assertRaisesRegex(
231
+ ValueError,
232
+ "actor_optimizer must contain exactly its model parameters",
233
+ ):
234
+ SACLearner(
235
+ actor=actor,
236
+ critic1=critic1,
237
+ critic2=critic2,
238
+ actor_optimizer=th.optim.SGD(critic1.parameters(), lr=0.05),
239
+ critic_optimizer=th.optim.SGD(critic_parameters, lr=0.05),
240
+ config=SACConfig(action_shape=(action_dim,)),
241
+ )
242
+
243
+ with self.assertRaisesRegex(
244
+ ValueError,
245
+ "critic_optimizer must contain exactly its model parameters",
246
+ ):
247
+ SACLearner(
248
+ actor=actor,
249
+ critic1=critic1,
250
+ critic2=critic2,
251
+ actor_optimizer=th.optim.SGD(actor.parameters(), lr=0.05),
252
+ critic_optimizer=th.optim.SGD(critic1.parameters(), lr=0.05),
253
+ config=SACConfig(action_shape=(action_dim,)),
254
+ )
255
+
220
256
  def test_sac_actor_regularizer_contributes_to_loss(self):
221
257
  th.manual_seed(0)
222
258
  obs_dim = 4
@@ -247,8 +283,10 @@ class LearnerSmokeTest(unittest.TestCase):
247
283
  critic1=critic1,
248
284
  critic2=critic2,
249
285
  actor_optimizer=th.optim.SGD(actor.parameters(), lr=0.05),
250
- critic1_optimizer=th.optim.SGD(critic1.parameters(), lr=0.05),
251
- critic2_optimizer=th.optim.SGD(critic2.parameters(), lr=0.05),
286
+ critic_optimizer=th.optim.SGD(
287
+ [*critic1.parameters(), *critic2.parameters()],
288
+ lr=0.05,
289
+ ),
252
290
  config=SACConfig(
253
291
  action_shape=(action_dim,),
254
292
  regularizers=[actor_l2],
@@ -37,7 +37,7 @@ class PublicAPITest(unittest.TestCase):
37
37
  "WarmupController",
38
38
  }
39
39
 
40
- self.assertEqual(drlab.__version__, "0.2.4")
40
+ self.assertEqual(drlab.__version__, "0.2.5")
41
41
  self.assertTrue(expected.issubset(set(drlab.__all__)))
42
42
  for name in expected:
43
43
  self.assertTrue(hasattr(drlab, name), name)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes