drlab 0.1.1__tar.gz → 0.2.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 (59) hide show
  1. drlab-0.2.2/PKG-INFO +208 -0
  2. drlab-0.2.2/README.md +171 -0
  3. {drlab-0.1.1 → drlab-0.2.2}/pyproject.toml +2 -2
  4. drlab-0.2.2/src/drlab/__init__.py +73 -0
  5. drlab-0.2.2/src/drlab/controllers/__init__.py +17 -0
  6. drlab-0.2.2/src/drlab/controllers/base.py +28 -0
  7. {drlab-0.1.1 → drlab-0.2.2}/src/drlab/controllers/e_greedy.py +16 -6
  8. drlab-0.2.2/src/drlab/controllers/gaussian.py +32 -0
  9. {drlab-0.1.1 → drlab-0.2.2}/src/drlab/controllers/greedy.py +5 -5
  10. drlab-0.1.1/src/drlab/controllers/stochastic_controller.py → drlab-0.2.2/src/drlab/controllers/stochastic.py +5 -5
  11. drlab-0.2.2/src/drlab/controllers/warmup.py +42 -0
  12. drlab-0.2.2/src/drlab/experiments/__init__.py +9 -0
  13. drlab-0.1.1/src/drlab/experiments/dqn_experiment.py → drlab-0.2.2/src/drlab/experiments/off_policy_experiment.py +72 -32
  14. drlab-0.1.1/src/drlab/experiments/ac_experiment.py → drlab-0.2.2/src/drlab/experiments/on_policy_experiment.py +8 -12
  15. drlab-0.2.2/src/drlab/learners/__init__.py +33 -0
  16. drlab-0.2.2/src/drlab/learners/off_policy/__init__.py +9 -0
  17. drlab-0.2.2/src/drlab/learners/off_policy/base.py +147 -0
  18. drlab-0.2.2/src/drlab/learners/off_policy/configs.py +72 -0
  19. drlab-0.2.2/src/drlab/learners/off_policy/dqn.py +101 -0
  20. drlab-0.2.2/src/drlab/learners/off_policy/sac.py +195 -0
  21. drlab-0.2.2/src/drlab/learners/on_policy/__init__.py +23 -0
  22. drlab-0.2.2/src/drlab/learners/on_policy/actor_critic.py +143 -0
  23. drlab-0.2.2/src/drlab/learners/on_policy/base.py +124 -0
  24. drlab-0.2.2/src/drlab/learners/on_policy/configs.py +51 -0
  25. drlab-0.2.2/src/drlab/learners/on_policy/ppo.py +122 -0
  26. drlab-0.2.2/src/drlab/learners/on_policy/reinforce.py +75 -0
  27. {drlab-0.1.1 → drlab-0.2.2}/src/drlab/replay/replay_buffer.py +15 -5
  28. drlab-0.2.2/src/drlab/replay/transition_batch.py +40 -0
  29. {drlab-0.1.1 → drlab-0.2.2}/src/drlab/runners/runner.py +79 -21
  30. drlab-0.2.2/src/drlab.egg-info/PKG-INFO +208 -0
  31. drlab-0.2.2/src/drlab.egg-info/SOURCES.txt +42 -0
  32. {drlab-0.1.1 → drlab-0.2.2}/src/drlab.egg-info/requires.txt +1 -1
  33. drlab-0.2.2/tests/test_controllers.py +163 -0
  34. drlab-0.2.2/tests/test_learners.py +239 -0
  35. drlab-0.2.2/tests/test_off_policy_experiment.py +154 -0
  36. drlab-0.2.2/tests/test_public_api.py +43 -0
  37. {drlab-0.1.1 → drlab-0.2.2}/tests/test_replay.py +17 -0
  38. {drlab-0.1.1 → drlab-0.2.2}/tests/test_runner.py +21 -0
  39. drlab-0.1.1/PKG-INFO +0 -275
  40. drlab-0.1.1/README.md +0 -238
  41. drlab-0.1.1/src/drlab/__init__.py +0 -36
  42. drlab-0.1.1/src/drlab/controllers/__init__.py +0 -6
  43. drlab-0.1.1/src/drlab/controllers/base.py +0 -17
  44. drlab-0.1.1/src/drlab/experiments/__init__.py +0 -9
  45. drlab-0.1.1/src/drlab/learners/__init__.py +0 -4
  46. drlab-0.1.1/src/drlab/learners/actor_critic.py +0 -206
  47. drlab-0.1.1/src/drlab/learners/dqn.py +0 -149
  48. drlab-0.1.1/src/drlab/replay/transition_batch.py +0 -33
  49. drlab-0.1.1/src/drlab.egg-info/PKG-INFO +0 -275
  50. drlab-0.1.1/src/drlab.egg-info/SOURCES.txt +0 -30
  51. drlab-0.1.1/tests/test_controllers.py +0 -80
  52. drlab-0.1.1/tests/test_learners.py +0 -74
  53. drlab-0.1.1/tests/test_public_api.py +0 -29
  54. {drlab-0.1.1 → drlab-0.2.2}/LICENSE +0 -0
  55. {drlab-0.1.1 → drlab-0.2.2}/setup.cfg +0 -0
  56. {drlab-0.1.1 → drlab-0.2.2}/src/drlab/replay/__init__.py +0 -0
  57. {drlab-0.1.1 → drlab-0.2.2}/src/drlab/runners/__init__.py +0 -0
  58. {drlab-0.1.1 → drlab-0.2.2}/src/drlab.egg-info/dependency_links.txt +0 -0
  59. {drlab-0.1.1 → drlab-0.2.2}/src/drlab.egg-info/top_level.txt +0 -0
drlab-0.2.2/PKG-INFO ADDED
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.4
2
+ Name: drlab
3
+ Version: 0.2.2
4
+ Summary: Deep Reinforcement Learning kit for research.
5
+ Author: Tomas Osarte
6
+ Keywords: reinforcement-learning,deep-learning,pytorch,gymnasium
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Science/Research
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Requires-Python: >=3.11
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: torch<3,>=2.0
18
+ Requires-Dist: numpy==2.4.2
19
+ Requires-Dist: gymnasium==1.2.3
20
+ Requires-Dist: tqdm>=4.66
21
+ Requires-Dist: tensorboard>=2.16
22
+ Provides-Extra: experiments
23
+ Requires-Dist: ale-py>=0.11; extra == "experiments"
24
+ Requires-Dist: gymnasium[box2d]==1.2.3; extra == "experiments"
25
+ Requires-Dist: matplotlib>=3.8; extra == "experiments"
26
+ Requires-Dist: minigrid>=3.0; extra == "experiments"
27
+ Requires-Dist: opencv-python>=4.10; extra == "experiments"
28
+ Requires-Dist: scipy>=1.11; extra == "experiments"
29
+ Provides-Extra: dev
30
+ Requires-Dist: build>=1.2; extra == "dev"
31
+ Requires-Dist: ipykernel>=6.29; extra == "dev"
32
+ Requires-Dist: notebook>=7.0; extra == "dev"
33
+ Requires-Dist: pip-tools>=7.4; extra == "dev"
34
+ Requires-Dist: pytest>=8.0; extra == "dev"
35
+ Requires-Dist: ruff>=0.6; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # drlab
39
+
40
+ `drlab` is a small deep reinforcement learning library for training neural
41
+ network agents in Gymnasium environments. Its purpose is to provide simple,
42
+ research-friendly building blocks for reinforcement learning experiments,
43
+ especially when the environment or training setup is still being explored.
44
+
45
+ The library is built around PyTorch models, Gymnasium environments, reusable
46
+ controllers, replay buffers, runners, learners, and lightweight experiment
47
+ loops. It is intended for research code and prototypes, not as a large
48
+ production RL framework.
49
+
50
+ ## Installation
51
+
52
+ The intended development setup uses [`uv`](https://docs.astral.sh/uv/). From the
53
+ repository root:
54
+
55
+ ```bash
56
+ uv sync --extra experiments --extra dev
57
+ ```
58
+
59
+ Run commands through the managed environment:
60
+
61
+ ```bash
62
+ uv run python -m pytest
63
+ uv run python examples/dqn_cartpole.py
64
+ ```
65
+
66
+ You can also activate the local virtual environment created by `uv`:
67
+
68
+ ```bash
69
+ source .venv/bin/activate
70
+ python -m pytest
71
+ ```
72
+
73
+ If you prefer a normal `venv` and `pip` workflow:
74
+
75
+ ```bash
76
+ python -m venv .venv
77
+ source .venv/bin/activate
78
+ python -m pip install --upgrade pip
79
+ python -m pip install -e .
80
+ ```
81
+
82
+ For experiment and development dependencies:
83
+
84
+ ```bash
85
+ python -m pip install -e ".[experiments,dev]"
86
+ ```
87
+
88
+ `drlab` depends on PyTorch, NumPy, Gymnasium, tqdm, and TensorBoard. If you need
89
+ a specific CUDA build of PyTorch, install the matching PyTorch wheel before
90
+ installing the package dependencies.
91
+
92
+ ## Library Overview
93
+
94
+ Most public classes can be imported directly from `drlab`:
95
+
96
+ ```python
97
+ from drlab import DQNConfig, DQNLearner, OffPolicyExperiment
98
+ ```
99
+
100
+ ### Off-Policy Learning
101
+
102
+ Off-policy learners train from transition batches that may come from a replay
103
+ buffer instead of only the most recent rollout. `OffPolicyExperiment` collects
104
+ environment transitions with a `Runner`, stores them in a `ReplayBuffer`, samples
105
+ minibatches, and calls the learner update.
106
+
107
+ Implemented off-policy learners:
108
+
109
+ - `DQNLearner`: value-based learning for discrete action spaces. It supports
110
+ replay-buffer training, target networks, Double DQN, hard or soft target
111
+ updates, gradient clipping, and custom regularizers.
112
+ - `SACLearner`: Soft Actor-Critic style learning for continuous action spaces.
113
+ It uses an actor, two critics, target critics, entropy tuning, and replay
114
+ buffer training.
115
+
116
+ ### On-Policy Learning
117
+
118
+ On-policy learners train from the data collected by the current policy.
119
+ `OnPolicyExperiment` collects rollouts, computes returns when needed, and trains
120
+ the learner directly on the fresh batch.
121
+
122
+ Implemented on-policy learners:
123
+
124
+ - `ReinforceLearner`: policy-gradient learning from discounted returns.
125
+ - `ActorCriticLearner`: policy and value learning from shared model outputs.
126
+ - `PPOLearner`: clipped policy optimization over rollout batches.
127
+
128
+ ### Supporting Components
129
+
130
+ Controllers turn model outputs into environment actions:
131
+
132
+ - `GreedyController`, `EpsilonGreedyController`, and `StochasticController`
133
+ support discrete action spaces.
134
+ - `GaussianController` supports continuous action spaces by sampling bounded
135
+ actions from model-predicted Gaussian parameters.
136
+
137
+ `Runner` interacts with Gymnasium environments and returns transition batches,
138
+ episode returns, episode lengths, and optionally the last completed episode.
139
+
140
+ `ReplayBuffer` stores transitions for off-policy learning. It supports both
141
+ discrete and continuous action spaces through the configured action shape and
142
+ action type.
143
+
144
+ `TransitionBatch` is the tensor container passed between runners, replay
145
+ buffers, experiments, and learners.
146
+
147
+ ## Simple Usage
148
+
149
+ This example trains a DQN agent on `CartPole-v1`:
150
+
151
+ ```python
152
+ import gymnasium as gym
153
+ import torch as th
154
+
155
+ from drlab import (
156
+ DQNConfig,
157
+ DQNLearner,
158
+ EpsilonGreedyController,
159
+ GreedyController,
160
+ OffPolicyExperiment,
161
+ OffPolicyExperimentConfig,
162
+ )
163
+
164
+ env = gym.make("CartPole-v1")
165
+
166
+ obs_dim = env.observation_space.shape[0]
167
+ num_actions = env.action_space.n
168
+
169
+ model = th.nn.Sequential(
170
+ th.nn.Linear(obs_dim, 64),
171
+ th.nn.ReLU(),
172
+ th.nn.Linear(64, num_actions),
173
+ )
174
+ optimizer = th.optim.Adam(model.parameters(), lr=1e-3)
175
+
176
+ learner = DQNLearner(
177
+ model,
178
+ optimizer,
179
+ DQNConfig(num_actions=num_actions),
180
+ )
181
+
182
+ controller = EpsilonGreedyController(
183
+ GreedyController(model, num_actions=num_actions),
184
+ num_actions=num_actions,
185
+ max_eps=1.0,
186
+ min_eps=0.05,
187
+ anneal_steps=10_000,
188
+ )
189
+
190
+ experiment = OffPolicyExperiment(
191
+ env,
192
+ controller,
193
+ learner,
194
+ OffPolicyExperimentConfig(
195
+ max_steps=10_000,
196
+ run_steps=1,
197
+ batch_size=64,
198
+ log_dir="runs/examples/dqn_cartpole",
199
+ ),
200
+ )
201
+
202
+ experiment.run()
203
+ env.close()
204
+ ```
205
+
206
+ More complete scripts are available in the [`examples/`](examples/) folder,
207
+ including DQN, REINFORCE, actor-critic, PPO, SAC, and a comparison with
208
+ Stable-Baselines3.
drlab-0.2.2/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # drlab
2
+
3
+ `drlab` is a small deep reinforcement learning library for training neural
4
+ network agents in Gymnasium environments. Its purpose is to provide simple,
5
+ research-friendly building blocks for reinforcement learning experiments,
6
+ especially when the environment or training setup is still being explored.
7
+
8
+ The library is built around PyTorch models, Gymnasium environments, reusable
9
+ controllers, replay buffers, runners, learners, and lightweight experiment
10
+ loops. It is intended for research code and prototypes, not as a large
11
+ production RL framework.
12
+
13
+ ## Installation
14
+
15
+ The intended development setup uses [`uv`](https://docs.astral.sh/uv/). From the
16
+ repository root:
17
+
18
+ ```bash
19
+ uv sync --extra experiments --extra dev
20
+ ```
21
+
22
+ Run commands through the managed environment:
23
+
24
+ ```bash
25
+ uv run python -m pytest
26
+ uv run python examples/dqn_cartpole.py
27
+ ```
28
+
29
+ You can also activate the local virtual environment created by `uv`:
30
+
31
+ ```bash
32
+ source .venv/bin/activate
33
+ python -m pytest
34
+ ```
35
+
36
+ If you prefer a normal `venv` and `pip` workflow:
37
+
38
+ ```bash
39
+ python -m venv .venv
40
+ source .venv/bin/activate
41
+ python -m pip install --upgrade pip
42
+ python -m pip install -e .
43
+ ```
44
+
45
+ For experiment and development dependencies:
46
+
47
+ ```bash
48
+ python -m pip install -e ".[experiments,dev]"
49
+ ```
50
+
51
+ `drlab` depends on PyTorch, NumPy, Gymnasium, tqdm, and TensorBoard. If you need
52
+ a specific CUDA build of PyTorch, install the matching PyTorch wheel before
53
+ installing the package dependencies.
54
+
55
+ ## Library Overview
56
+
57
+ Most public classes can be imported directly from `drlab`:
58
+
59
+ ```python
60
+ from drlab import DQNConfig, DQNLearner, OffPolicyExperiment
61
+ ```
62
+
63
+ ### Off-Policy Learning
64
+
65
+ Off-policy learners train from transition batches that may come from a replay
66
+ buffer instead of only the most recent rollout. `OffPolicyExperiment` collects
67
+ environment transitions with a `Runner`, stores them in a `ReplayBuffer`, samples
68
+ minibatches, and calls the learner update.
69
+
70
+ Implemented off-policy learners:
71
+
72
+ - `DQNLearner`: value-based learning for discrete action spaces. It supports
73
+ replay-buffer training, target networks, Double DQN, hard or soft target
74
+ updates, gradient clipping, and custom regularizers.
75
+ - `SACLearner`: Soft Actor-Critic style learning for continuous action spaces.
76
+ It uses an actor, two critics, target critics, entropy tuning, and replay
77
+ buffer training.
78
+
79
+ ### On-Policy Learning
80
+
81
+ On-policy learners train from the data collected by the current policy.
82
+ `OnPolicyExperiment` collects rollouts, computes returns when needed, and trains
83
+ the learner directly on the fresh batch.
84
+
85
+ Implemented on-policy learners:
86
+
87
+ - `ReinforceLearner`: policy-gradient learning from discounted returns.
88
+ - `ActorCriticLearner`: policy and value learning from shared model outputs.
89
+ - `PPOLearner`: clipped policy optimization over rollout batches.
90
+
91
+ ### Supporting Components
92
+
93
+ Controllers turn model outputs into environment actions:
94
+
95
+ - `GreedyController`, `EpsilonGreedyController`, and `StochasticController`
96
+ support discrete action spaces.
97
+ - `GaussianController` supports continuous action spaces by sampling bounded
98
+ actions from model-predicted Gaussian parameters.
99
+
100
+ `Runner` interacts with Gymnasium environments and returns transition batches,
101
+ episode returns, episode lengths, and optionally the last completed episode.
102
+
103
+ `ReplayBuffer` stores transitions for off-policy learning. It supports both
104
+ discrete and continuous action spaces through the configured action shape and
105
+ action type.
106
+
107
+ `TransitionBatch` is the tensor container passed between runners, replay
108
+ buffers, experiments, and learners.
109
+
110
+ ## Simple Usage
111
+
112
+ This example trains a DQN agent on `CartPole-v1`:
113
+
114
+ ```python
115
+ import gymnasium as gym
116
+ import torch as th
117
+
118
+ from drlab import (
119
+ DQNConfig,
120
+ DQNLearner,
121
+ EpsilonGreedyController,
122
+ GreedyController,
123
+ OffPolicyExperiment,
124
+ OffPolicyExperimentConfig,
125
+ )
126
+
127
+ env = gym.make("CartPole-v1")
128
+
129
+ obs_dim = env.observation_space.shape[0]
130
+ num_actions = env.action_space.n
131
+
132
+ model = th.nn.Sequential(
133
+ th.nn.Linear(obs_dim, 64),
134
+ th.nn.ReLU(),
135
+ th.nn.Linear(64, num_actions),
136
+ )
137
+ optimizer = th.optim.Adam(model.parameters(), lr=1e-3)
138
+
139
+ learner = DQNLearner(
140
+ model,
141
+ optimizer,
142
+ DQNConfig(num_actions=num_actions),
143
+ )
144
+
145
+ controller = EpsilonGreedyController(
146
+ GreedyController(model, num_actions=num_actions),
147
+ num_actions=num_actions,
148
+ max_eps=1.0,
149
+ min_eps=0.05,
150
+ anneal_steps=10_000,
151
+ )
152
+
153
+ experiment = OffPolicyExperiment(
154
+ env,
155
+ controller,
156
+ learner,
157
+ OffPolicyExperimentConfig(
158
+ max_steps=10_000,
159
+ run_steps=1,
160
+ batch_size=64,
161
+ log_dir="runs/examples/dqn_cartpole",
162
+ ),
163
+ )
164
+
165
+ experiment.run()
166
+ env.close()
167
+ ```
168
+
169
+ More complete scripts are available in the [`examples/`](examples/) folder,
170
+ including DQN, REINFORCE, actor-critic, PPO, SAC, and a comparison with
171
+ Stable-Baselines3.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "drlab"
7
- version = "0.1.1"
7
+ version = "0.2.2"
8
8
  description = "Deep Reinforcement Learning kit for research."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -20,7 +20,7 @@ classifiers = [
20
20
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
21
21
  ]
22
22
  dependencies = [
23
- "torch==2.10.0+cu128",
23
+ "torch>=2.0,<3",
24
24
  "numpy==2.4.2",
25
25
  "gymnasium==1.2.3",
26
26
  "tqdm>=4.66",
@@ -0,0 +1,73 @@
1
+ from drlab.controllers import (
2
+ ContinuousActionController,
3
+ Controller,
4
+ DiscreteActionController,
5
+ EpsilonGreedyController,
6
+ GaussianController,
7
+ GreedyController,
8
+ StochasticController,
9
+ WarmupController,
10
+ )
11
+ from drlab.experiments import (
12
+ OnPolicyExperiment,
13
+ OnPolicyExperimentConfig,
14
+ OffPolicyExperiment,
15
+ OffPolicyExperimentConfig,
16
+ )
17
+ from drlab.learners import (
18
+ ActorCriticConfig,
19
+ ActorCriticLearner,
20
+ DQNConfig,
21
+ DQNLearner,
22
+ SACConfig,
23
+ SACLearner,
24
+ OnPolicyConfig,
25
+ OnPolicyLearner,
26
+ OffPolicyConfig,
27
+ OffPolicyLearner,
28
+ PPOConfig,
29
+ PPOLearner,
30
+ ReinforceConfig,
31
+ ReinforceLearner,
32
+ TargetUpdate,
33
+ ValueTargets,
34
+ )
35
+ from drlab.replay import ReplayBuffer, TransitionBatch
36
+ from drlab.runners import Runner
37
+
38
+ __version__ = "0.2.2"
39
+
40
+ __all__ = [
41
+ "__version__",
42
+ "ActorCriticConfig",
43
+ "ActorCriticLearner",
44
+ "OnPolicyExperiment",
45
+ "OnPolicyExperimentConfig",
46
+ "ContinuousActionController",
47
+ "Controller",
48
+ "DiscreteActionController",
49
+ "DQNConfig",
50
+ "DQNLearner",
51
+ "SACConfig",
52
+ "SACLearner",
53
+ "OnPolicyConfig",
54
+ "OnPolicyLearner",
55
+ "OffPolicyConfig",
56
+ "OffPolicyLearner",
57
+ "OffPolicyExperiment",
58
+ "OffPolicyExperimentConfig",
59
+ "PPOConfig",
60
+ "PPOLearner",
61
+ "ReinforceConfig",
62
+ "ReinforceLearner",
63
+ "TargetUpdate",
64
+ "EpsilonGreedyController",
65
+ "GaussianController",
66
+ "GreedyController",
67
+ "ReplayBuffer",
68
+ "Runner",
69
+ "StochasticController",
70
+ "TransitionBatch",
71
+ "ValueTargets",
72
+ "WarmupController",
73
+ ]
@@ -0,0 +1,17 @@
1
+ from .base import ContinuousActionController, Controller, DiscreteActionController
2
+ from .greedy import GreedyController
3
+ from .e_greedy import EpsilonGreedyController
4
+ from .stochastic import StochasticController
5
+ from .gaussian import GaussianController
6
+ from .warmup import WarmupController
7
+
8
+ __all__ = [
9
+ "ContinuousActionController",
10
+ "Controller",
11
+ "DiscreteActionController",
12
+ "EpsilonGreedyController",
13
+ "GaussianController",
14
+ "GreedyController",
15
+ "StochasticController",
16
+ "WarmupController",
17
+ ]
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ import torch as th
4
+ from abc import ABC, abstractmethod
5
+
6
+
7
+ class Controller(ABC):
8
+ """Base controller interface for all action spaces."""
9
+
10
+ model: th.nn.Module
11
+
12
+ @abstractmethod
13
+ def choose(self, obs: th.Tensor, **kwargs) -> th.Tensor: ...
14
+
15
+
16
+ class DiscreteActionController(Controller):
17
+ """Controller interface for discrete action spaces."""
18
+
19
+ num_actions: int
20
+
21
+ @abstractmethod
22
+ def probabilities(self, obs: th.Tensor, **kwargs) -> th.Tensor: ...
23
+
24
+
25
+ class ContinuousActionController(Controller):
26
+ """Controller interface for continuous action spaces."""
27
+
28
+ action_dim: int
@@ -1,12 +1,13 @@
1
1
  import numpy as np
2
2
  import torch as th
3
- from .base import Controller
3
+ from .base import DiscreteActionController
4
4
 
5
- class EpsilonGreedyController(Controller):
5
+
6
+ class EpsilonGreedyController(DiscreteActionController):
6
7
 
7
8
  def __init__(
8
9
  self,
9
- controller: Controller,
10
+ controller: DiscreteActionController,
10
11
  num_actions: int,
11
12
  max_eps: float = 1.0,
12
13
  min_eps: float = 0.1,
@@ -27,7 +28,12 @@ class EpsilonGreedyController(Controller):
27
28
  frac = max(1 - self.num_decisions / (self.anneal_steps - 1), 0.0)
28
29
  return frac * (self.max_eps - self.min_eps) + self.min_eps
29
30
 
30
- def choose(self, obs: th.Tensor, increase_counter: bool = True, **kwargs) -> th.Tensor:
31
+ def choose(
32
+ self,
33
+ obs: th.Tensor,
34
+ increase_counter: bool = True,
35
+ **kwargs,
36
+ ) -> th.Tensor:
31
37
  eps = self.epsilon()
32
38
  if increase_counter:
33
39
  self.num_decisions += 1
@@ -40,7 +46,11 @@ class EpsilonGreedyController(Controller):
40
46
 
41
47
  def probabilities(self, obs: th.Tensor, **kwargs) -> th.Tensor:
42
48
  eps = self.epsilon()
43
- greedy = self.controller.probabilities(obs, **kwargs) # one-hot on argmax, shape [B,A]
49
+ greedy = self.controller.probabilities(obs, **kwargs)
44
50
  B = greedy.shape[0]
45
- uniform = th.full((B, self.num_actions), eps / self.num_actions, device=greedy.device)
51
+ uniform = th.full(
52
+ (B, self.num_actions),
53
+ eps / self.num_actions,
54
+ device=greedy.device,
55
+ )
46
56
  return uniform + (1 - eps) * greedy
@@ -0,0 +1,32 @@
1
+ import torch as th
2
+ from .base import ContinuousActionController
3
+
4
+
5
+ class GaussianController(ContinuousActionController):
6
+
7
+ def __init__(
8
+ self,
9
+ model: th.nn.Module,
10
+ action_dim: int,
11
+ deterministic: bool = False,
12
+ ):
13
+ self.model = model
14
+ self.action_dim = action_dim
15
+ self.num_actions = action_dim
16
+ self.deterministic = deterministic
17
+
18
+ def choose(self, obs: th.Tensor, **kwargs) -> th.Tensor:
19
+ output = self.model(obs)
20
+
21
+ mean = output[:, :self.action_dim]
22
+ log_std = output[:, self.action_dim: 2 * self.action_dim]
23
+ log_std = th.clamp(log_std, -20, 2)
24
+
25
+ if self.deterministic:
26
+ u = mean
27
+ else:
28
+ std = log_std.exp()
29
+ eps = th.randn_like(mean)
30
+ u = mean + std * eps
31
+
32
+ return th.tanh(u)
@@ -1,20 +1,20 @@
1
1
  import torch as th
2
- from .base import Controller
2
+ from .base import DiscreteActionController
3
3
 
4
- class GreedyController(Controller):
4
+
5
+ class GreedyController(DiscreteActionController):
5
6
 
6
7
  def __init__(self, model: th.nn.Module, num_actions: int):
7
-
8
8
  self.num_actions = num_actions
9
9
  self.model = model
10
10
 
11
11
  def choose(self, obs: th.Tensor):
12
12
  output: th.Tensor = self.model(obs)[:, :self.num_actions]
13
13
  return th.argmax(output, dim=-1)
14
-
14
+
15
15
  def probabilities(self, obs: th.Tensor):
16
16
  output: th.Tensor = self.model(obs)[:, :self.num_actions]
17
- idx = output.argmax(dim=-1, keepdim=True) # [B,1]
17
+ idx = output.argmax(dim=-1, keepdim=True)
18
18
  probs = th.zeros(output.shape[0], self.num_actions, device=output.device)
19
19
  probs.scatter_(dim=-1, index=idx, value=1.0)
20
20
  return probs
@@ -1,17 +1,17 @@
1
1
  import torch as th
2
- from .base import Controller
2
+ from .base import DiscreteActionController
3
3
 
4
- class StochasticController(Controller):
4
+
5
+ class StochasticController(DiscreteActionController):
5
6
 
6
7
  def __init__(self, model: th.nn.Module, num_actions: int):
7
-
8
8
  self.num_actions = num_actions
9
9
  self.model = model
10
10
 
11
11
  def choose(self, obs: th.Tensor) -> th.Tensor:
12
12
  probs = self.probabilities(obs)
13
13
  return th.distributions.Categorical(probs=probs).sample()
14
-
14
+
15
15
  def probabilities(self, obs: th.Tensor) -> th.Tensor:
16
16
  output = self.model(obs)[:, :self.num_actions]
17
- return th.nn.functional.softmax(output, dim=-1)
17
+ return th.nn.functional.softmax(output, dim=-1)
@@ -0,0 +1,42 @@
1
+ from typing import Any
2
+
3
+ import numpy as np
4
+ import torch as th
5
+
6
+ from .base import ContinuousActionController, Controller, DiscreteActionController
7
+
8
+
9
+ class WarmupController(ContinuousActionController, DiscreteActionController):
10
+ def __init__(self, controller: Controller, action_space: Any, warmup_steps: int):
11
+ self.controller = controller
12
+ self.action_space = action_space
13
+ self.warmup_steps = warmup_steps
14
+ self.steps = 0
15
+ self.model = controller.model
16
+
17
+ if hasattr(controller, "num_actions"):
18
+ self.num_actions = controller.num_actions
19
+ if hasattr(controller, "action_dim"):
20
+ self.action_dim = controller.action_dim
21
+
22
+ if warmup_steps < 0:
23
+ raise ValueError("warmup_steps must be >= 0.")
24
+
25
+ def choose(
26
+ self,
27
+ obs: th.Tensor,
28
+ **kwargs,
29
+ ) -> th.Tensor:
30
+ if self.steps >= self.warmup_steps:
31
+ return self.controller.choose(obs, **kwargs)
32
+
33
+ batch_size = obs.shape[0]
34
+ self.steps += batch_size
35
+ actions = [self.action_space.sample() for _ in range(batch_size)]
36
+ return th.as_tensor(np.asarray(actions), device=obs.device)
37
+
38
+ def probabilities(self, obs: th.Tensor, **kwargs) -> th.Tensor:
39
+ if self.steps >= self.warmup_steps:
40
+ return self.controller.probabilities(obs, **kwargs)
41
+
42
+ return th.ones((obs.shape[0], self.num_actions), device=obs.device) / self.num_actions
@@ -0,0 +1,9 @@
1
+ from .off_policy_experiment import OffPolicyExperiment, OffPolicyExperimentConfig
2
+ from .on_policy_experiment import OnPolicyExperiment, OnPolicyExperimentConfig
3
+
4
+ __all__ = [
5
+ "OffPolicyExperiment",
6
+ "OnPolicyExperiment",
7
+ "OffPolicyExperimentConfig",
8
+ "OnPolicyExperimentConfig",
9
+ ]