rlmodule 0.0.5__tar.gz → 0.1.0__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 (34) hide show
  1. {rlmodule-0.0.5 → rlmodule-0.1.0}/PKG-INFO +49 -4
  2. rlmodule-0.1.0/README.md +46 -0
  3. {rlmodule-0.0.5 → rlmodule-0.1.0}/pyproject.toml +7 -5
  4. rlmodule-0.1.0/rlmodule/__init__.py +4 -0
  5. rlmodule-0.1.0/rlmodule/skrl/examples/gymnasium/skrl_gymnasium_pendulum.py +276 -0
  6. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule/source/deprecated.py +23 -18
  7. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule/source/model.py +167 -189
  8. rlmodule-0.1.0/rlmodule/source/model_builder.py +33 -0
  9. rlmodule-0.1.0/rlmodule/source/model_cfg.py +33 -0
  10. rlmodule-0.1.0/rlmodule/source/modules.py +696 -0
  11. rlmodule-0.1.0/rlmodule/source/modules_cfg.py +56 -0
  12. rlmodule-0.1.0/rlmodule/source/nvidia_utils/__init__.py +1 -0
  13. rlmodule-0.1.0/rlmodule/source/nvidia_utils/configclass.py +436 -0
  14. rlmodule-0.1.0/rlmodule/source/nvidia_utils/dict.py +121 -0
  15. rlmodule-0.1.0/rlmodule/source/nvidia_utils/string.py +97 -0
  16. rlmodule-0.1.0/rlmodule/source/output_layer.py +150 -0
  17. rlmodule-0.1.0/rlmodule/source/output_layer_cfg.py +38 -0
  18. rlmodule-0.1.0/rlmodule/source/rlmodel.py +373 -0
  19. rlmodule-0.1.0/rlmodule/source/utils.py +121 -0
  20. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule.egg-info/PKG-INFO +49 -4
  21. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule.egg-info/SOURCES.txt +11 -1
  22. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule.egg-info/requires.txt +3 -3
  23. rlmodule-0.0.5/README.md +0 -2
  24. rlmodule-0.0.5/rlmodule/__init__.py +0 -3
  25. rlmodule-0.0.5/rlmodule/skrl/examples/gymnasium/skrl_gymnasium_pendulum.py +0 -120
  26. rlmodule-0.0.5/rlmodule/source/modules.py +0 -1003
  27. rlmodule-0.0.5/rlmodule/source/rlmodel.py +0 -771
  28. {rlmodule-0.0.5 → rlmodule-0.1.0}/LICENSE +0 -0
  29. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule/skrl/__init__.py +0 -0
  30. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule/skrl/examples/gymnasium/skrl_gymnasium_pendulum_no_module.py +0 -0
  31. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule/source/__init__.py +0 -0
  32. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule.egg-info/dependency_links.txt +0 -0
  33. {rlmodule-0.0.5 → rlmodule-0.1.0}/rlmodule.egg-info/top_level.txt +0 -0
  34. {rlmodule-0.0.5 → rlmodule-0.1.0}/setup.cfg +0 -0
@@ -1,8 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rlmodule
3
- Version: 0.0.5
3
+ Version: 0.1.0
4
4
  Summary: Flexible reinforcement learning models instantiators library
5
5
  Author: Lopatovsky
6
+ Author-email: lopatovsky@gmail.com
6
7
  Maintainer: Lopatovsky
7
8
  License: MIT License
8
9
  Project-URL: Homepage, https://github.com/FabricaAI/rlmodule
@@ -24,11 +25,55 @@ License-File: LICENSE
24
25
  Requires-Dist: gym
25
26
  Requires-Dist: gymnasium
26
27
  Requires-Dist: torch>=1.9
27
- Requires-Dist: skrl>=1.2.0
28
+ Requires-Dist: skrl>=1.3.0
28
29
  Provides-Extra: skrl
29
- Requires-Dist: skrl>=1.2.0; extra == "skrl"
30
+ Requires-Dist: skrl>=1.3.0; extra == "skrl"
30
31
  Provides-Extra: all
31
- Requires-Dist: skrl>=1.2.0; extra == "all"
32
+ Requires-Dist: skrl>=1.3.0; extra == "all"
32
33
 
33
34
  # rlmodule
34
35
  Flexible reinforcement learning models instantiators library
36
+
37
+
38
+ ## How to run
39
+
40
+ ### Install rlmodule from local code
41
+
42
+ - Make sure you are in base rlmodule dit.
43
+
44
+ - Start virtual env.
45
+ ```
46
+ python3 -m venv venv
47
+ source venv/bin/activate
48
+ ```
49
+ - Install library from local code
50
+ ```
51
+ pip install -e .
52
+ ```
53
+ Note: sometimes installation may fail, if there is a run/ dir present, you may need to remove it (TODO: fix)
54
+ ```
55
+ rm -rf runs
56
+ ```
57
+ ### Run chosen example
58
+ ```
59
+ python3 rlmodule/skrl/examples/gymnasium/skrl_gymnasium_pendulum.py
60
+ ```
61
+
62
+
63
+ ## Update new version to PIP
64
+
65
+ ```
66
+ pip install build twine
67
+ ```
68
+
69
+ ```
70
+ rm -rf runs
71
+ python -m build
72
+ ```
73
+
74
+ ```
75
+ twine upload dist/*
76
+ ```
77
+
78
+
79
+
@@ -0,0 +1,46 @@
1
+ # rlmodule
2
+ Flexible reinforcement learning models instantiators library
3
+
4
+
5
+ ## How to run
6
+
7
+ ### Install rlmodule from local code
8
+
9
+ - Make sure you are in base rlmodule dit.
10
+
11
+ - Start virtual env.
12
+ ```
13
+ python3 -m venv venv
14
+ source venv/bin/activate
15
+ ```
16
+ - Install library from local code
17
+ ```
18
+ pip install -e .
19
+ ```
20
+ Note: sometimes installation may fail, if there is a run/ dir present, you may need to remove it (TODO: fix)
21
+ ```
22
+ rm -rf runs
23
+ ```
24
+ ### Run chosen example
25
+ ```
26
+ python3 rlmodule/skrl/examples/gymnasium/skrl_gymnasium_pendulum.py
27
+ ```
28
+
29
+
30
+ ## Update new version to PIP
31
+
32
+ ```
33
+ pip install build twine
34
+ ```
35
+
36
+ ```
37
+ rm -rf runs
38
+ python -m build
39
+ ```
40
+
41
+ ```
42
+ twine upload dist/*
43
+ ```
44
+
45
+
46
+
@@ -1,16 +1,18 @@
1
1
  [project]
2
2
  name = "rlmodule"
3
- version = "0.0.5"
3
+ version = "0.1.0"
4
4
  description = "Flexible reinforcement learning models instantiators library"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.6"
7
7
  license = {text = "MIT License"}
8
8
  authors = [
9
- {name = "Lopatovsky"},
9
+ {name = "Lopatovsky"},
10
+ {email = "lopatovsky@gmail.com"},
10
11
  ]
11
12
  maintainers = [
12
13
  {name = "Lopatovsky"},
13
14
  ]
15
+
14
16
  keywords = ["reinforcement-learning", "machine-learning", "reinforcement", "machine", "learning", "rl", "rl-models", "rl-modules", "models", "modules"]
15
17
  classifiers = [
16
18
  "License :: OSI Approved :: MIT License",
@@ -24,18 +26,18 @@ dependencies = [
24
26
  "gym",
25
27
  "gymnasium",
26
28
  "torch>=1.9",
27
- "skrl>=1.2.0",
29
+ "skrl>=1.3.0",
28
30
  ]
29
31
 
30
32
  [project.optional-dependencies]
31
33
 
32
34
  # TODO(ll) only examples should depend on skrl, not the main code.
33
35
  skrl = [
34
- "skrl>=1.2.0",
36
+ "skrl>=1.3.0",
35
37
  ]
36
38
 
37
39
  all = [
38
- "skrl>=1.2.0",
40
+ "skrl>=1.3.0",
39
41
  ]
40
42
 
41
43
  # urls
@@ -0,0 +1,4 @@
1
+ # TODO this is not very good way
2
+ from .source.rlmodel import RLModel, SharedRLModel # noqa: F401, F403
3
+ from .source.output_layer import GaussianLayer, DeterministicLayer # noqa: F401, F403
4
+ from .source.modules import MLP # noqa: F401, F403
@@ -0,0 +1,276 @@
1
+ import gymnasium as gym
2
+
3
+ import torch.nn as nn
4
+
5
+ from rlmodule.source.model_cfg import SharedRLModelCfg
6
+ from rlmodule.source.modules import RnnMlpWithForwardedInput
7
+ from rlmodule.source.modules_cfg import LstmCfg, MlpCfg, RnnMlpCfg
8
+ from rlmodule.source.output_layer_cfg import DeterministicLayerCfg, GaussianLayerCfg
9
+ from rlmodule.source.model_builder import build_model
10
+
11
+ # example how this could be called:
12
+ # from rlmodule.skrl.torch.model import SharedRLModelCfg
13
+ # from rlmodule.skrl.torch.module import LstmCfg
14
+ # from rlmodule.skrl.torch.output_layer import DeterministicLayerCfg, GaussianLayerCfg
15
+ # from rlmodule.skrl.torch import build_model
16
+
17
+ # import the skrl components to build the RL system
18
+ from skrl.agents.torch.ppo import PPO, PPO_RNN, PPO_DEFAULT_CONFIG
19
+
20
+ from skrl.envs.wrappers.torch.gymnasium_envs import GymnasiumWrapper
21
+ #from skrl.envs.wrappers.torch import wrap_env
22
+ from skrl.memories.torch import RandomMemory
23
+ from skrl.resources.preprocessors.torch import RunningStandardScaler
24
+ from skrl.resources.schedulers.torch import KLAdaptiveRL
25
+ from skrl.trainers.torch import SequentialTrainer
26
+ from skrl.utils import set_seed
27
+ from skrl.envs.wrappers.torch.gymnasium_envs import GymnasiumWrapper
28
+
29
+ # todo set seed
30
+ # seed for reproducibility
31
+ set_seed() # e.g. `set_seed(42)` for fixed seed
32
+
33
+ #TODO next
34
+ # (Done) check how to do own @configclass .. or use one from isaac by default (print something to know version)
35
+ # (Done) RNN code modify to use data class
36
+ # (Done) RnnMLP
37
+ # (Done) Custom function Network
38
+ # (Done) Move things logically
39
+ # (Done) Handle input shapes better?
40
+ # (Done except Cnn) Convert all rest modules to use Configclass
41
+ # Rearrange library in the way it can be used for other rllibs and for torch/jax?
42
+ # Create examples - mlp, rnn,gru,lstm, Lstmmlp, shared - separate , custom net by fcion
43
+ # - examples from modules make in class header not function
44
+ # WRITE README tutorial
45
+ # Run & fix pre-commit
46
+ # annotate cfgs in modules - why doesn't work
47
+ # extensive comments
48
+ # Launch new version to pip
49
+ # Import new version in Isaac-lab
50
+
51
+
52
+
53
+ # def example_module(cfg):
54
+ # cfg = RnnMlpCfg(
55
+ # input_size = env.observation_space,
56
+ # rnn = LstmCfg(
57
+ # num_envs = env.num_envs,
58
+ # num_layers = 1,
59
+ # hidden_size = 32,
60
+ # sequence_length = 16,
61
+ # ),
62
+ # mlp = MlpCfg(
63
+ # hidden_units = [64, 64, 64],
64
+ # activations = [nn.ReLU(), nn.ReLU(), nn.ReLU()],
65
+ # ),
66
+ # )
67
+ # return RnnMlp(cfg)
68
+
69
+ def get_shared_model(env):
70
+ # instantiate the agent's models (function approximators).
71
+
72
+ net_cfg = MlpCfg(
73
+ input_size = env.observation_space,
74
+ hidden_units = [64, 64, 64],
75
+ activations = [nn.ReLU(), nn.ReLU(), nn.ReLU()],
76
+ )
77
+
78
+ # 2
79
+ # net_cfg = LstmCfg(
80
+ # input_size = env.observation_space,
81
+ # num_envs = env.num_envs,
82
+ # num_layers = 1,
83
+ # hidden_size = 32,
84
+ # sequence_length = 16,
85
+ # )
86
+
87
+ # 3
88
+ # net_cfg = RnnMlpCfg(
89
+ # input_size = env.observation_space,
90
+ # rnn = LstmCfg(
91
+ # num_envs = env.num_envs,
92
+ # num_layers = 1,
93
+ # hidden_size = 32,
94
+ # sequence_length = 16,
95
+ # ),
96
+ # mlp = MlpCfg(
97
+ # hidden_units = [64, 64, 64],
98
+ # activations = [nn.ReLU(), nn.ReLU(), nn.ReLU()],
99
+ # ),
100
+ # )
101
+
102
+ # 3.5
103
+ # net_cfg = RnnMlpCfg(
104
+ # input_size = env.observation_space,
105
+ # module = RnnMlpWithForwardedInput,
106
+ # rnn = LstmCfg(
107
+ # num_envs = env.num_envs,
108
+ # num_layers = 1,
109
+ # hidden_size = 32,
110
+ # sequence_length = 16,
111
+ # ),
112
+ # mlp = MlpCfg(
113
+ # hidden_units = [64, 64, 64],
114
+ # activations = [nn.ReLU(), nn.ReLU(), nn.ReLU()],
115
+ # ),
116
+ # )
117
+
118
+ # 4
119
+ # net_cfg = NetworkCfg( input_size = env.observation_space,
120
+ # module = example_module)
121
+
122
+ # variant IV - all config
123
+ # net also config (optional)?
124
+ model = build_model(
125
+ SharedRLModelCfg(
126
+ network= net_cfg,
127
+ device= device,
128
+ policy_output_layer= GaussianLayerCfg(
129
+ output_size=env.action_space,
130
+ min_log_std=-1.2,
131
+ max_log_std=2,
132
+ initial_log_std=0.2,
133
+ ),
134
+ value_output_layer= DeterministicLayerCfg(),
135
+ )
136
+ )
137
+ # RLCfg(
138
+ # Model
139
+ # AgentCfg
140
+ # MemoryCfg
141
+ # )
142
+
143
+ # build_model(cfg.model)
144
+
145
+ # cfg.agent.algoclass(
146
+ # cfg.agent.algo_config
147
+ # cfg.memory
148
+ # )
149
+
150
+ # SharedRLModelCfg(RLModelCfg){
151
+ # class = SharedRLModel
152
+
153
+ # }
154
+
155
+ # net
156
+ # output layers.class()
157
+
158
+ # cfg.model.class( net, output_layers )
159
+
160
+ #configclass -> dataclass - easy (Ron said)
161
+
162
+
163
+ # variant V:
164
+ # ideas?
165
+
166
+
167
+ return {'policy': model, 'value': model}
168
+
169
+ # TODO Update separate model to configclass
170
+ # def get_separate_model(env):
171
+ # # instantiate the agent's models (function approximators).
172
+ # params = {'input_size': env.observation_space,
173
+ # 'hidden_units': [64, 64, 64],
174
+ # 'activations': ['relu', 'relu', 'relu']
175
+ # }
176
+ # net = MLP(params)
177
+
178
+ # policy_model = RLModel(
179
+ # network=net,
180
+ # device= device,
181
+ # output_layer = GaussianLayer(
182
+ # input_size=64, # TODO
183
+ # output_size=env.action_space,
184
+ # output_activation=nn.Tanh(),
185
+ # clip_actions=False,
186
+ # clip_log_std=True,
187
+ # min_log_std=-1.2,
188
+ # max_log_std=2,
189
+ # initial_log_std=0.2,
190
+ # ),
191
+ # )
192
+
193
+ # value_model = RLModel(
194
+ # network=net,
195
+ # device= device,
196
+ # output_layer = DeterministicLayer(
197
+ # input_size=64,
198
+ # output_size=1,
199
+ # output_activation=nn.Identity(),
200
+ # ),
201
+ # )
202
+
203
+ # return {'policy': policy_model, 'value': value_model}
204
+
205
+
206
+ # load and wrap the gymnasium environment.
207
+ # note: the environment version may change depending on the gymnasium version
208
+ try:
209
+ env = gym.vector.make("Pendulum-v1", num_envs=4, asynchronous=False)
210
+ except (gym.error.DeprecatedEnv, gym.error.VersionNotFound) as e:
211
+ env_id = [spec for spec in gym.envs.registry if spec.startswith("Pendulum-v")][0]
212
+ print("Pendulum-v1 not found. Trying {}".format(env_id))
213
+ env = gym.vector.make(env_id, num_envs=4, asynchronous=False)
214
+
215
+ env = GymnasiumWrapper(env)
216
+
217
+ device = env.device
218
+
219
+
220
+ # instantiate a memory as rollout buffer (any memory can be used for this)
221
+ memory = RandomMemory(memory_size=1024, num_envs=env.num_envs, device=device)
222
+
223
+ models = get_shared_model(env)
224
+
225
+ print(models)
226
+
227
+
228
+ # configure and instantiate the agent (visit its documentation to see all the options)
229
+ # https://skrl.readthedocs.io/en/latest/api/agents/ppo.html#configuration-and-hyperparameters
230
+ cfg = PPO_DEFAULT_CONFIG.copy()
231
+ cfg["rollouts"] = 1024 # memory_size
232
+ cfg["learning_epochs"] = 10
233
+ cfg["mini_batches"] = 32
234
+ cfg["discount_factor"] = 0.9
235
+ cfg["lambda"] = 0.95
236
+ cfg["learning_rate"] = 1e-3
237
+ cfg["learning_rate_scheduler"] = KLAdaptiveRL
238
+ cfg["learning_rate_scheduler_kwargs"] = {"kl_threshold": 0.008}
239
+ cfg["grad_norm_clip"] = 0.5
240
+ cfg["ratio_clip"] = 0.2
241
+ cfg["value_clip"] = 0.2
242
+ cfg["clip_predicted_values"] = False
243
+ cfg["entropy_loss_scale"] = 0.0
244
+ cfg["value_loss_scale"] = 0.5
245
+ cfg["kl_threshold"] = 0
246
+ cfg["state_preprocessor"] = RunningStandardScaler
247
+ cfg["state_preprocessor_kwargs"] = {"size": env.observation_space, "device": device}
248
+ cfg["value_preprocessor"] = RunningStandardScaler
249
+ cfg["value_preprocessor_kwargs"] = {"size": 1, "device": device}
250
+ # logging to TensorBoard and write checkpoints (in timesteps)
251
+ cfg["experiment"]["write_interval"] = 500
252
+ cfg["experiment"]["checkpoint_interval"] = 5000
253
+ cfg["experiment"]["directory"] = "runs/torch/Pendulum"
254
+
255
+ # TODO(nicer)
256
+ if models['policy']._rnn:
257
+ agent = PPO_RNN(models=models,
258
+ memory=memory,
259
+ cfg=cfg,
260
+ observation_space=env.observation_space,
261
+ action_space=env.action_space,
262
+ device=device)
263
+ else:
264
+ agent = PPO(models=models,
265
+ memory=memory,
266
+ cfg=cfg,
267
+ observation_space=env.observation_space,
268
+ action_space=env.action_space,
269
+ device=device)
270
+
271
+ # configure and instantiate the RL trainer
272
+ cfg_trainer = {"timesteps": 100000, "headless": True}
273
+ trainer = SequentialTrainer(cfg=cfg_trainer, env=env, agents=[agent])
274
+
275
+ # start training
276
+ trainer.train()
@@ -72,13 +72,14 @@ class GaussianMixin:
72
72
  )
73
73
  )
74
74
  """
75
- self._clip_actions = clip_actions and (issubclass(type(self.action_space), gym.Space) or \
76
- issubclass(type(self.action_space), gymnasium.Space))
75
+ # TODO return this functionality
76
+ # self._clip_actions = clip_actions and (issubclass(type(self.action_space), gym.Space) or \
77
+ # issubclass(type(self.action_space), gymnasium.Space))
77
78
 
78
- if self._clip_actions:
79
- # TODO(ll) the code assume it will be inherited ... self.device is not set anywhere.
80
- self._clip_actions_min = torch.tensor(self.action_space.low, device=self.device, dtype=torch.float32)
81
- self._clip_actions_max = torch.tensor(self.action_space.high, device=self.device, dtype=torch.float32)
79
+ # if self._clip_actions:
80
+ # # TODO(ll) the code assume it will be inherited ... self.device is not set anywhere.
81
+ # self._clip_actions_min = torch.tensor(self.action_space.low, device=self.device, dtype=torch.float32)
82
+ # self._clip_actions_max = torch.tensor(self.action_space.high, device=self.device, dtype=torch.float32)
82
83
 
83
84
  self._clip_log_std = clip_log_std
84
85
  self._log_std_min = min_log_std
@@ -194,8 +195,9 @@ class GaussianMixin:
194
195
  actions = self._distribution.rsample()
195
196
 
196
197
  # clip actions
197
- if self._clip_actions:
198
- actions = torch.clamp(actions, min=self._clip_actions_min, max=self._clip_actions_max)
198
+ # TODO enable
199
+ # if self._clip_actions:
200
+ # actions = torch.clamp(actions, min=self._clip_actions_min, max=self._clip_actions_max)
199
201
 
200
202
  if taken_actions is None:
201
203
  taken_actions = actions
@@ -309,12 +311,14 @@ class DeterministicMixin:
309
311
  )
310
312
  )
311
313
  """
312
- self._clip_actions = clip_actions and (issubclass(type(self.action_space), gym.Space) or \
313
- issubclass(type(self.action_space), gymnasium.Space))
314
+ pass
315
+ # TODO return this functionality
316
+ # self._clip_actions = clip_actions and (issubclass(type(self.action_space), gym.Space) or \
317
+ # issubclass(type(self.action_space), gymnasium.Space))
314
318
 
315
- if self._clip_actions:
316
- self._clip_actions_min = torch.tensor(self.action_space.low, device=self.device, dtype=torch.float32)
317
- self._clip_actions_max = torch.tensor(self.action_space.high, device=self.device, dtype=torch.float32)
319
+ # if self._clip_actions:
320
+ # self._clip_actions_min = torch.tensor(self.action_space.low, device=self.device, dtype=torch.float32)
321
+ # self._clip_actions_max = torch.tensor(self.action_space.high, device=self.device, dtype=torch.float32)
318
322
 
319
323
  def act(self,
320
324
  inputs: Mapping[str, Union[torch.Tensor, Any]],
@@ -344,8 +348,9 @@ class DeterministicMixin:
344
348
  actions, outputs = self.compute(inputs, role)
345
349
 
346
350
  # clip actions
347
- if self._clip_actions:
348
- actions = torch.clamp(actions, min=self._clip_actions_min, max=self._clip_actions_max)
351
+ # TODO enable
352
+ # if self._clip_actions:
353
+ # actions = torch.clamp(actions, min=self._clip_actions_min, max=self._clip_actions_max)
349
354
 
350
355
  return actions, None, outputs
351
356
 
@@ -371,8 +376,8 @@ class DeterministicMixin:
371
376
  >>> print(actions.shape, outputs)
372
377
  torch.Size([4096, 1]) {}
373
378
  """
374
- # clip actions
375
- if self._clip_actions:
376
- actions = torch.clamp(actions, min=self._clip_actions_min, max=self._clip_actions_max)
379
+ # clip actions # TODO enable
380
+ # if self._clip_actions:
381
+ # actions = torch.clamp(actions, min=self._clip_actions_min, max=self._clip_actions_max)
377
382
 
378
383
  return actions, None, outputs