ap-gym 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 (42) hide show
  1. ap_gym-0.1.0/LICENSE +21 -0
  2. ap_gym-0.1.0/PKG-INFO +313 -0
  3. ap_gym-0.1.0/README.md +296 -0
  4. ap_gym-0.1.0/ap_gym/__init__.py +34 -0
  5. ap_gym-0.1.0/ap_gym/active_classification_env.py +154 -0
  6. ap_gym-0.1.0/ap_gym/active_perception_env.py +276 -0
  7. ap_gym-0.1.0/ap_gym/active_perception_vector_env.py +333 -0
  8. ap_gym-0.1.0/ap_gym/active_regression_env.py +152 -0
  9. ap_gym-0.1.0/ap_gym/envs/__init__.py +0 -0
  10. ap_gym-0.1.0/ap_gym/envs/dataset/__init__.py +4 -0
  11. ap_gym-0.1.0/ap_gym/envs/dataset/buffered_iterator.py +42 -0
  12. ap_gym-0.1.0/ap_gym/envs/dataset/data_loader.py +31 -0
  13. ap_gym-0.1.0/ap_gym/envs/dataset/dataset.py +45 -0
  14. ap_gym-0.1.0/ap_gym/envs/dataset/dataset_iterator.py +57 -0
  15. ap_gym-0.1.0/ap_gym/envs/floor_map/__init__.py +3 -0
  16. ap_gym-0.1.0/ap_gym/envs/floor_map/floor_map_dataset.py +19 -0
  17. ap_gym-0.1.0/ap_gym/envs/floor_map/floor_map_dataset_maze.py +61 -0
  18. ap_gym-0.1.0/ap_gym/envs/floor_map/floor_map_dataset_rooms.py +95 -0
  19. ap_gym-0.1.0/ap_gym/envs/image/__init__.py +6 -0
  20. ap_gym-0.1.0/ap_gym/envs/image/circle_square_dataset.py +58 -0
  21. ap_gym-0.1.0/ap_gym/envs/image/huggingface_image_classification_dataset.py +51 -0
  22. ap_gym-0.1.0/ap_gym/envs/image/image_classification_dataset.py +85 -0
  23. ap_gym-0.1.0/ap_gym/envs/image/image_perception_module.py +375 -0
  24. ap_gym-0.1.0/ap_gym/envs/image_classification.py +113 -0
  25. ap_gym-0.1.0/ap_gym/envs/image_localization.py +189 -0
  26. ap_gym-0.1.0/ap_gym/envs/lidar_localization2d.py +384 -0
  27. ap_gym-0.1.0/ap_gym/envs/light_dark.py +165 -0
  28. ap_gym-0.1.0/ap_gym/envs/registration.py +210 -0
  29. ap_gym-0.1.0/ap_gym/envs/style.py +17 -0
  30. ap_gym-0.1.0/ap_gym/image_space.py +55 -0
  31. ap_gym-0.1.0/ap_gym/loss_fn.py +161 -0
  32. ap_gym-0.1.0/ap_gym/time_limit.py +156 -0
  33. ap_gym-0.1.0/ap_gym/types.py +16 -0
  34. ap_gym-0.1.0/ap_gym/vector_to_single_wrapper.py +129 -0
  35. ap_gym-0.1.0/ap_gym.egg-info/PKG-INFO +313 -0
  36. ap_gym-0.1.0/ap_gym.egg-info/SOURCES.txt +40 -0
  37. ap_gym-0.1.0/ap_gym.egg-info/dependency_links.txt +1 -0
  38. ap_gym-0.1.0/ap_gym.egg-info/requires.txt +8 -0
  39. ap_gym-0.1.0/ap_gym.egg-info/top_level.txt +1 -0
  40. ap_gym-0.1.0/pyproject.toml +29 -0
  41. ap_gym-0.1.0/setup.cfg +4 -0
  42. ap_gym-0.1.0/test/test_active_classification_env.py +50 -0
ap_gym-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2025 Tim Schneider
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
ap_gym-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.2
2
+ Name: ap_gym
3
+ Version: 0.1.0
4
+ Summary: Active Perception Gym: extension of Gymnasium for active perception tasks.
5
+ Author-email: Tim Schneider <tim@robot-learning.de>
6
+ License: MIT
7
+ Project-URL: homepage, https://git.ias.informatik.tu-darmstadt.de/schneider/active-perception-gym.git
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: gymnasium>=1.0.0
11
+ Requires-Dist: scipy
12
+ Requires-Dist: numpy
13
+ Requires-Dist: datasets
14
+ Requires-Dist: shapely
15
+ Provides-Extra: examples
16
+ Requires-Dist: matplotlib; extra == "examples"
17
+
18
+ # ap_gym: Active Perception Gym
19
+
20
+ Extension of [Gymnasium](https://github.com/Farama-Foundation/Gymnasium/) for active perception tasks.
21
+
22
+ ## Installation
23
+
24
+ This package can be installed using pip:
25
+
26
+ ```bash
27
+ pip install ap_gym[OPTIONS]
28
+ ```
29
+
30
+ where OPTIONS can be empty or `examples`, which installs dependencies for the examples.
31
+
32
+ ## Basic Usage
33
+
34
+ _ap_gym_ adds functionality for active perception tasks to Gymnasium.
35
+ This guide assumes that you are familiar with Gymnasium, otherwise, please check out
36
+ their [documentation](https://gymnasium.farama.org/index.html).
37
+
38
+ ### Active Perception
39
+
40
+ In the active perception domain, an agent's main objective is to gather information and make predictions about a desired
41
+ property of the environment.
42
+ Examples of such properties could be the location of an object in case of a search task or the class of an object the
43
+ agent in case of a classification task.
44
+ To gather information, the agent must interact with the environment, e.g. by moving a glimpse around in case of
45
+ the [CircleSquare](doc/CircleSquare.md) and [MNIST](doc/MNIST.md) tasks.
46
+
47
+ _ap_gym_ models active perception tasks as episodic processes in a way that is fully compatible to Gymnasium.
48
+ Each task is defined as a Gymnasium environment, in which the agent is additionally provided with a differentiable loss
49
+ function.
50
+ The purpose of the loss function is to provide the agent with a generalizable notion of the distance between its current
51
+ property prediction and the ground truth property.
52
+
53
+ In every episode, the agent may take a task-dependent number of steps to gather information.
54
+ Just like in Gymnasium, in every step the environment provides the agent with an observation, typically consisting of
55
+ scalar and/or image data.
56
+ In return, the agent must provide the environment with an action and a property prediction in every step.
57
+ Based on the action and prediction of the agent, the environment computes a reward in every step, which is the sum of a
58
+ regular RL reward (the base reward) and the negative value of the environment's loss function.
59
+ Hence, the agent has to make a prediction in every step, encouraging it to gather information quickly to maximize its
60
+ prediction reward early on.
61
+
62
+ #### Formal Problem Statement
63
+ Active perception problems are a special case of Partially Observable Markov Decision Processes (POMDPs).
64
+ POMDPs are defined by the tuple $(S, A, T, R, \Omega, O, \gamma)$, where
65
+ - $S$ is the set of (hidden) states,
66
+ - $A$ is the set of actions,
67
+ - $T: S \times A \times S \to [0, 1]$ is the transition function,
68
+ - $R: S \times A \to \mathbb{R}$ is the reward function,
69
+ - $\Omega$ is the set of observations,
70
+ - $O: S \times A \times \Omega \to [0, 1]$ is the observation function, and
71
+ - $\gamma \in [0, 1]$ is the discount factor.
72
+
73
+ The objective of the agent in a POMDP is to maximize the expected cumulative reward over time by selecting actions based on its belief about the underlying state.
74
+ Since the agent does not have direct access to the true state, it maintains a belief distribution over states, updating it using observations and the observation function.
75
+ The environment evolves according to the transition function, where taking an action leads to a probabilistic transition to a new state, which in turn generates an observation based on the observation function.
76
+ For further details on POMDPs, refer to the [POMDP Wikipedia page](https://en.wikipedia.org/wiki/Partially_observable_Markov_decision_process).
77
+
78
+ In case of active perception problems, we assume that the hidden state $S$, the action $A$, the reward function $R$, and the transition function $T$ have specific structures.
79
+ First, we assume that the target property the agent is tasked to predict is part of the hidden state.
80
+ Hence, $S$ is defined as $S = S_{\text{base}} \times \overset{\ast}{Y}$, where $S_{\text{base}}$ is the set of base (hidden) states of the environment and $\overset{\ast}{Y}$ is the set of prediction targets.
81
+ E.g., $\overset{\ast}{Y}$ could be the set of classes in a classification task or the set of possible locations in a localization task, while $S_{\text{base}}$ contains all the other hidden state information.
82
+
83
+ To allow the agent to make predictions, the action space $A$ is defined as $A_{\text{base}} \times Y$, where $A_{\text{base}}$ is the base action space and $Y$ is the prediction space.
84
+ The base action space $A_{\text{base}}$ contains all the actions the agent can take to interact with the environment, while $Y$ is the set of possible predictions the agent can make.
85
+ Crucially, environments are defined in a way that agent's prediction never influences the hidden state of the environment.
86
+ Thus, the transition function $T$ is defined as
87
+ $$T(s, a, s') = T(s, (a_\text{base}, y), s') = T_{\text{base}}(s, a_\text{base}, s').$$
88
+ An example for a base action could be the movement of a glimpse in an image classification task, while the prediction could be the logits of the agent's current class prediction.
89
+
90
+ Finally, the reward function is defined as
91
+ $$R(s, a) = R((s_{\text{base}}, \overset{\ast}{y}), (a_{\text{base}}, y)) = R_{\text{base}}(s_{\text{base}}, a_{\text{base}}) - \ell(\overset{\ast}{y}, y),$$
92
+ where $R_{\text{base}}$ is the base reward function and $\ell$ is a differentiable loss function.
93
+ An example for a base reward could be an action regularization term, while the loss function $\ell$ could be a cross-entropy loss in a classification task.
94
+
95
+
96
+ ### Environment Base Classes
97
+
98
+ Every task in _ap_gym_ is modeled as a subclass of `ap_gym.ActivePerceptionEnv` or `ap_gym.ActivePerceptionVectorEnv`.
99
+ `ap_gym.ActivePerceptionEnv` and `ap_gym.ActivePerceptionVectorEnv` subclass `gymnasium.Env` and
100
+ `gymnasium.vector.VectorEnv`, respectively.
101
+ Both subclasses extend their Gymnasium interfaces by four fields:
102
+
103
+ - `loss_fn`: The loss function of the environment. See [Loss Functions](#loss-functions).
104
+ - `prediction_space`: A `gymnasium.spaces.Space` defining the set of valid prediction values.
105
+ - `prediction_target_space`: A `gymnasium.spaces.Space` defining the set of valid prediction target values.
106
+ - `inner_action_space`: A `gymnasium.spaces.Space` defining the set of valid inner action values.
107
+ Additionally, `ap_gym.ActivePerceptionVectorEnv` adds the respective single variants of the latter two fields:
108
+ `single_prediction_space` and `single_inner_action_space`.
109
+
110
+ `ap_gym.ActivePerceptionEnv` and `ap_gym.ActivePerceptionVectorEnv` further enforce the agent's action space to be of
111
+ the following form:
112
+
113
+ ```python
114
+ {
115
+ "action": action,
116
+ "prediction": prediction
117
+ }
118
+ ```
119
+
120
+ where the set of valid `action` values is defined by the `inner_action_space` field of the respective environment, and
121
+ the set of valid `prediction` values is defined by the `prediction_space` field.
122
+
123
+ The info dictionary returned by the reset and step functions always contains the current prediction target in
124
+ `info["prediction"]["target"]`.
125
+ Additionally, the info dictionary returned by the step function contains the base reward (the reward without the
126
+ prediction loss) in `info["base_reward"]` and the prediction loss in `info["prediction"]["loss"]`.
127
+
128
+ To get an understanding of how this class is used, refer to the examples in the _examples_ directory and to
129
+ the [environments](#environments) defined by _ap_gym_.
130
+
131
+ ### Loss Functions
132
+
133
+ The `ap_gym.LossFn` base class provides a differentiable implementation of the loss function for PyTorch and JAX.
134
+ `ap_gym.LossFn` has three functions: `numpy`, `torch`, and `jax`.
135
+ Each of these functions is the respective implementation of the loss function in Numpy, PyTorch, and JAX.
136
+ Note that only the PyTorch and JAX variant provide gradients as Numpy does not support autograd.
137
+
138
+ The signature of each framework-specific function is
139
+
140
+ ```python
141
+ def fn(prediction: ArrayType, target: ArrayType, batch_shape: Tuple[int, ...] = ()) -> ArrayType:
142
+ ...
143
+ ```
144
+
145
+ where ArrayType is one of `np.ndarray`, `torch.Tensor`, or `jax.Array`.
146
+ `batch_shape` is used to specify the batch dimensions in case of a batched evaluation of the loss function, e.g.:
147
+
148
+ ```python
149
+ loss = ap_gym.CrossEntropyLossFn()(np.zeros((3, 7, 10)), np.zeros((3, 7), dtype=np.int_), (3, 7))
150
+ ```
151
+
152
+ ### Representation of Image Observations
153
+
154
+ To help the agent differentiate between scalar and image observations, _ap_gym_ introduces a new type of Gymnasium
155
+ space: `ap_gym.ImageSpace`.
156
+ `ap_gym.ImageSpace` is a subclass of `gymnasium.spaces.Box` with some image specific convenience properties like
157
+ `width`, `height`, and `channels`.
158
+ Its main purpose, though, is to let the agent know that it has to interpret this part of the observation space as an
159
+ image.
160
+
161
+ ### Using Gymnasium Wrappers
162
+
163
+ _ap_gym_ provides a method for using regular Gymnasium wrappers on `ap_gym.ActivePerceptionEnv` and
164
+ `ap_gym.ActivePerceptionVectorEnv` instances.
165
+ The issue with using Gymnasium wrappers naively is that the special fields `loss_fn`, `prediction_space`,
166
+ `prediction_target_space`, and `inner_action_space` do not get mapped through.
167
+ Hence,
168
+
169
+ ```python
170
+ gymnasium.wrappers.TimeLimit(ap_gym.make("CircleSquare-v0"), 8).loss_fn
171
+ ```
172
+
173
+ throws
174
+
175
+ ```
176
+ AttributeError: 'TimeLimit' object has no attribute 'loss_fn'
177
+ ```
178
+
179
+ To address this issue, `ap_gym.ensure_active_perception_env` and `ap_gym.ensure_active_perception_vector_env` can be
180
+ used:
181
+
182
+ ```python
183
+ ap_gym.ActivePerceptionRestoreWrapper(gymnasium.wrappers.TimeLimit(ap_gym.make("CircleSquare-v0"), 8)).loss_fn
184
+ ```
185
+
186
+ `ap_gym.ActivePerceptionRestoreWrapper` and `ap_gym.ActivePerceptionVectorRestoreWrapper` recursively traverse wrappers
187
+ until they find an active perception environment and map the special fields through.
188
+ Additionally, aside of Gymnasium wrappers, `ap_gym.ActivePerceptionVectorRestoreWrapper` also supports
189
+ `gymnasium.vector.SyncVectorEnv` and `gymnasium.vector.AsyncVectorEnv` and will restore proper vector versions of all
190
+ spaces if active perception environments are vectorized this way.
191
+
192
+ ### Environments
193
+
194
+ _ap_gym_ currently comes with a number of image classification environments, which are described in detail in
195
+ the [image classification documentation](doc/ImageClassification.md).
196
+
197
+ #### Image Classification
198
+
199
+ <table align="center" style="border-collapse: collapse; border: none;">
200
+ <tr style="border: none;">
201
+ <td align="center" style="border: none; padding: 10px;">
202
+ <img src="doc/img/CircleSquare-v0.gif" alt="CircleSquare-v0" width="150px"/><br/>
203
+ <a href="doc/CircleSquare.md">
204
+ CircleSquare-v0
205
+ </a>
206
+ </td>
207
+ <td align="center" style="border: none; padding: 10px;">
208
+ <img src="doc/img/MNIST-v0.gif" alt="MNIST-v0" width="150px"/><br/>
209
+ <a href="doc/MNIST.md">
210
+ MNIST-v0
211
+ </a>
212
+ </td>
213
+ <td align="center" style="border: none; padding: 10px;">
214
+ <img src="doc/img/TinyImageNet-v0.gif" alt="TinyImageNet-v0" width="150px"/><br/>
215
+ <a href="doc/TinyImageNet.md">
216
+ TinyImageNet-v0
217
+ </a>
218
+ </td>
219
+ <td align="center" style="border: none; padding: 10px;">
220
+ <img src="doc/img/CIFAR10-v0.gif" alt="CIFAR10-v0" width="150px"/><br/>
221
+ <a href="doc/CIFAR10.md">
222
+ CIFAR10-v0
223
+ </a>
224
+ </td>
225
+ </tr>
226
+ </table>
227
+
228
+ #### 2D Localization
229
+
230
+ <table align="center" style="border-collapse: collapse; border: none;">
231
+ <tr style="border: none;">
232
+ <td align="center" style="border: none; padding: 10px;">
233
+ <img src="doc/img/LightDark-v0.gif" alt="LightDark-v0" width="150px"/> <br/>
234
+ <a href="doc/LightDark.md">
235
+ LightDark-v0
236
+ </a>
237
+ </td>
238
+ <td align="center" style="border: none; padding: 10px;">
239
+ <img src="doc/img/LIDARLocRooms-v0.gif" alt="LIDARLocRooms-v0" width="150px"/><br/>
240
+ <a href="doc/LIDARLocalization.md">
241
+ LIDARLocRooms-v0
242
+ </a>
243
+ </td>
244
+ <td align="center" style="border: none; padding: 10px;">
245
+ <img src="doc/img/LIDARLocMaze-v0.gif" alt="LIDARLocMaze-v0" width="150px"/><br/>
246
+ <a href="doc/LIDARLocMaze.md">
247
+ LIDARLocMaze-v0
248
+ </a>
249
+ </td>
250
+ </tr>
251
+ </table>
252
+
253
+ #### Image Localization
254
+
255
+ <table align="center" style="border-collapse: collapse; border: none;">
256
+ <tr style="border: none;">
257
+ <td align="center" style="border: none; padding: 10px;">
258
+ <img src="doc/img/TinyImageNetLoc-v0.gif" alt="TinyImageNetLoc-v0" width="150px"/><br/>
259
+ <a href="doc/TinyImageNetLoc.md">
260
+ TinyImageNetLoc-v0
261
+ </a>
262
+ </td>
263
+ <td align="center" style="border: none; padding: 10px;">
264
+ <img src="doc/img/CIFAR10Loc-v0.gif" alt="CIFAR10Loc-v0" width="150px"/><br/>
265
+ <a href="doc/CIFAR10Loc.md">
266
+ CIFAR10Loc-v0
267
+ </a>
268
+ </td>
269
+ </tr>
270
+ </table>
271
+
272
+ ### Converting Regular Gymnasium Environments to Active Perception Environments
273
+
274
+ It is possible to convert regular Gymnasium environments into a pseudo active perception environments with the
275
+ `ap_gym.PseudoActivePerceptionWrapper` and `ap_gym.PseudoActivePerceptionVectorWrapper`, respectively:
276
+
277
+ ```python
278
+ env = gymnasium.make("CartPole-v1")
279
+ ap_env = ap_gym.PseudoActivePerceptionWrapper(env)
280
+ ```
281
+
282
+ `ap_gym.PseudoActivePerceptionWrapper` and `ap_gym.PseudoActivePerceptionVectorWrapper` take the environment and add a
283
+ constant zero loss function as well as empty prediction and prediction target spaces.
284
+ The purpose of this conversion is to simplify testing of _ap_gym_ compatible algorithms on regular Gynmasium tasks.
285
+
286
+ If you want to support arbitrary Gymnasium and _ap_gym_ environments, use the `ap_gym.ensure_active_perception_env` and
287
+ `ap_gym.ensure_active_perception_vector_env` functions:
288
+
289
+ ```python
290
+ ap_env_1 = ap_gym.ensure_active_perception_env(gymnasium.make("CartPole-v1"))
291
+ ap_env_2 = ap_gym.ensure_active_perception_env(ap_gym.make("CircleSquare-v0"))
292
+ ap_env_3 = ap_gym.ensure_active_perception_env(gymnasium.wrappers.TimeLimit(ap_gym.make("CircleSquare-v0"), 8))
293
+ ```
294
+
295
+ These functions automatically detect whether to do nothing, apply a restoration wrapper, or perform pseudo active
296
+ perception environment conversion.
297
+
298
+ ## Advanced Usage
299
+
300
+ For more advanced usage, i.e., defining custom environments or wrappers, refer to the [advanced usage documentation](doc/advanced_usage.md).
301
+
302
+ ## License
303
+
304
+ The project is licensed under the MIT license.
305
+
306
+ ## Contributing
307
+
308
+ If you wish to contribute to this project, you are welcome to create a pull request.
309
+ Please run the [pre-commit](https://pre-commit.com/) hooks before submitting your pull request.
310
+ To install the pre-commit hooks, run:
311
+
312
+ 1. [Install pre-commit](https://pre-commit.com/#install)
313
+ 2. Install the Git hooks by running `pre-commit install` or, alternatively, run `pre-commit run --all-files manually.
ap_gym-0.1.0/README.md ADDED
@@ -0,0 +1,296 @@
1
+ # ap_gym: Active Perception Gym
2
+
3
+ Extension of [Gymnasium](https://github.com/Farama-Foundation/Gymnasium/) for active perception tasks.
4
+
5
+ ## Installation
6
+
7
+ This package can be installed using pip:
8
+
9
+ ```bash
10
+ pip install ap_gym[OPTIONS]
11
+ ```
12
+
13
+ where OPTIONS can be empty or `examples`, which installs dependencies for the examples.
14
+
15
+ ## Basic Usage
16
+
17
+ _ap_gym_ adds functionality for active perception tasks to Gymnasium.
18
+ This guide assumes that you are familiar with Gymnasium, otherwise, please check out
19
+ their [documentation](https://gymnasium.farama.org/index.html).
20
+
21
+ ### Active Perception
22
+
23
+ In the active perception domain, an agent's main objective is to gather information and make predictions about a desired
24
+ property of the environment.
25
+ Examples of such properties could be the location of an object in case of a search task or the class of an object the
26
+ agent in case of a classification task.
27
+ To gather information, the agent must interact with the environment, e.g. by moving a glimpse around in case of
28
+ the [CircleSquare](doc/CircleSquare.md) and [MNIST](doc/MNIST.md) tasks.
29
+
30
+ _ap_gym_ models active perception tasks as episodic processes in a way that is fully compatible to Gymnasium.
31
+ Each task is defined as a Gymnasium environment, in which the agent is additionally provided with a differentiable loss
32
+ function.
33
+ The purpose of the loss function is to provide the agent with a generalizable notion of the distance between its current
34
+ property prediction and the ground truth property.
35
+
36
+ In every episode, the agent may take a task-dependent number of steps to gather information.
37
+ Just like in Gymnasium, in every step the environment provides the agent with an observation, typically consisting of
38
+ scalar and/or image data.
39
+ In return, the agent must provide the environment with an action and a property prediction in every step.
40
+ Based on the action and prediction of the agent, the environment computes a reward in every step, which is the sum of a
41
+ regular RL reward (the base reward) and the negative value of the environment's loss function.
42
+ Hence, the agent has to make a prediction in every step, encouraging it to gather information quickly to maximize its
43
+ prediction reward early on.
44
+
45
+ #### Formal Problem Statement
46
+ Active perception problems are a special case of Partially Observable Markov Decision Processes (POMDPs).
47
+ POMDPs are defined by the tuple $(S, A, T, R, \Omega, O, \gamma)$, where
48
+ - $S$ is the set of (hidden) states,
49
+ - $A$ is the set of actions,
50
+ - $T: S \times A \times S \to [0, 1]$ is the transition function,
51
+ - $R: S \times A \to \mathbb{R}$ is the reward function,
52
+ - $\Omega$ is the set of observations,
53
+ - $O: S \times A \times \Omega \to [0, 1]$ is the observation function, and
54
+ - $\gamma \in [0, 1]$ is the discount factor.
55
+
56
+ The objective of the agent in a POMDP is to maximize the expected cumulative reward over time by selecting actions based on its belief about the underlying state.
57
+ Since the agent does not have direct access to the true state, it maintains a belief distribution over states, updating it using observations and the observation function.
58
+ The environment evolves according to the transition function, where taking an action leads to a probabilistic transition to a new state, which in turn generates an observation based on the observation function.
59
+ For further details on POMDPs, refer to the [POMDP Wikipedia page](https://en.wikipedia.org/wiki/Partially_observable_Markov_decision_process).
60
+
61
+ In case of active perception problems, we assume that the hidden state $S$, the action $A$, the reward function $R$, and the transition function $T$ have specific structures.
62
+ First, we assume that the target property the agent is tasked to predict is part of the hidden state.
63
+ Hence, $S$ is defined as $S = S_{\text{base}} \times \overset{\ast}{Y}$, where $S_{\text{base}}$ is the set of base (hidden) states of the environment and $\overset{\ast}{Y}$ is the set of prediction targets.
64
+ E.g., $\overset{\ast}{Y}$ could be the set of classes in a classification task or the set of possible locations in a localization task, while $S_{\text{base}}$ contains all the other hidden state information.
65
+
66
+ To allow the agent to make predictions, the action space $A$ is defined as $A_{\text{base}} \times Y$, where $A_{\text{base}}$ is the base action space and $Y$ is the prediction space.
67
+ The base action space $A_{\text{base}}$ contains all the actions the agent can take to interact with the environment, while $Y$ is the set of possible predictions the agent can make.
68
+ Crucially, environments are defined in a way that agent's prediction never influences the hidden state of the environment.
69
+ Thus, the transition function $T$ is defined as
70
+ $$T(s, a, s') = T(s, (a_\text{base}, y), s') = T_{\text{base}}(s, a_\text{base}, s').$$
71
+ An example for a base action could be the movement of a glimpse in an image classification task, while the prediction could be the logits of the agent's current class prediction.
72
+
73
+ Finally, the reward function is defined as
74
+ $$R(s, a) = R((s_{\text{base}}, \overset{\ast}{y}), (a_{\text{base}}, y)) = R_{\text{base}}(s_{\text{base}}, a_{\text{base}}) - \ell(\overset{\ast}{y}, y),$$
75
+ where $R_{\text{base}}$ is the base reward function and $\ell$ is a differentiable loss function.
76
+ An example for a base reward could be an action regularization term, while the loss function $\ell$ could be a cross-entropy loss in a classification task.
77
+
78
+
79
+ ### Environment Base Classes
80
+
81
+ Every task in _ap_gym_ is modeled as a subclass of `ap_gym.ActivePerceptionEnv` or `ap_gym.ActivePerceptionVectorEnv`.
82
+ `ap_gym.ActivePerceptionEnv` and `ap_gym.ActivePerceptionVectorEnv` subclass `gymnasium.Env` and
83
+ `gymnasium.vector.VectorEnv`, respectively.
84
+ Both subclasses extend their Gymnasium interfaces by four fields:
85
+
86
+ - `loss_fn`: The loss function of the environment. See [Loss Functions](#loss-functions).
87
+ - `prediction_space`: A `gymnasium.spaces.Space` defining the set of valid prediction values.
88
+ - `prediction_target_space`: A `gymnasium.spaces.Space` defining the set of valid prediction target values.
89
+ - `inner_action_space`: A `gymnasium.spaces.Space` defining the set of valid inner action values.
90
+ Additionally, `ap_gym.ActivePerceptionVectorEnv` adds the respective single variants of the latter two fields:
91
+ `single_prediction_space` and `single_inner_action_space`.
92
+
93
+ `ap_gym.ActivePerceptionEnv` and `ap_gym.ActivePerceptionVectorEnv` further enforce the agent's action space to be of
94
+ the following form:
95
+
96
+ ```python
97
+ {
98
+ "action": action,
99
+ "prediction": prediction
100
+ }
101
+ ```
102
+
103
+ where the set of valid `action` values is defined by the `inner_action_space` field of the respective environment, and
104
+ the set of valid `prediction` values is defined by the `prediction_space` field.
105
+
106
+ The info dictionary returned by the reset and step functions always contains the current prediction target in
107
+ `info["prediction"]["target"]`.
108
+ Additionally, the info dictionary returned by the step function contains the base reward (the reward without the
109
+ prediction loss) in `info["base_reward"]` and the prediction loss in `info["prediction"]["loss"]`.
110
+
111
+ To get an understanding of how this class is used, refer to the examples in the _examples_ directory and to
112
+ the [environments](#environments) defined by _ap_gym_.
113
+
114
+ ### Loss Functions
115
+
116
+ The `ap_gym.LossFn` base class provides a differentiable implementation of the loss function for PyTorch and JAX.
117
+ `ap_gym.LossFn` has three functions: `numpy`, `torch`, and `jax`.
118
+ Each of these functions is the respective implementation of the loss function in Numpy, PyTorch, and JAX.
119
+ Note that only the PyTorch and JAX variant provide gradients as Numpy does not support autograd.
120
+
121
+ The signature of each framework-specific function is
122
+
123
+ ```python
124
+ def fn(prediction: ArrayType, target: ArrayType, batch_shape: Tuple[int, ...] = ()) -> ArrayType:
125
+ ...
126
+ ```
127
+
128
+ where ArrayType is one of `np.ndarray`, `torch.Tensor`, or `jax.Array`.
129
+ `batch_shape` is used to specify the batch dimensions in case of a batched evaluation of the loss function, e.g.:
130
+
131
+ ```python
132
+ loss = ap_gym.CrossEntropyLossFn()(np.zeros((3, 7, 10)), np.zeros((3, 7), dtype=np.int_), (3, 7))
133
+ ```
134
+
135
+ ### Representation of Image Observations
136
+
137
+ To help the agent differentiate between scalar and image observations, _ap_gym_ introduces a new type of Gymnasium
138
+ space: `ap_gym.ImageSpace`.
139
+ `ap_gym.ImageSpace` is a subclass of `gymnasium.spaces.Box` with some image specific convenience properties like
140
+ `width`, `height`, and `channels`.
141
+ Its main purpose, though, is to let the agent know that it has to interpret this part of the observation space as an
142
+ image.
143
+
144
+ ### Using Gymnasium Wrappers
145
+
146
+ _ap_gym_ provides a method for using regular Gymnasium wrappers on `ap_gym.ActivePerceptionEnv` and
147
+ `ap_gym.ActivePerceptionVectorEnv` instances.
148
+ The issue with using Gymnasium wrappers naively is that the special fields `loss_fn`, `prediction_space`,
149
+ `prediction_target_space`, and `inner_action_space` do not get mapped through.
150
+ Hence,
151
+
152
+ ```python
153
+ gymnasium.wrappers.TimeLimit(ap_gym.make("CircleSquare-v0"), 8).loss_fn
154
+ ```
155
+
156
+ throws
157
+
158
+ ```
159
+ AttributeError: 'TimeLimit' object has no attribute 'loss_fn'
160
+ ```
161
+
162
+ To address this issue, `ap_gym.ensure_active_perception_env` and `ap_gym.ensure_active_perception_vector_env` can be
163
+ used:
164
+
165
+ ```python
166
+ ap_gym.ActivePerceptionRestoreWrapper(gymnasium.wrappers.TimeLimit(ap_gym.make("CircleSquare-v0"), 8)).loss_fn
167
+ ```
168
+
169
+ `ap_gym.ActivePerceptionRestoreWrapper` and `ap_gym.ActivePerceptionVectorRestoreWrapper` recursively traverse wrappers
170
+ until they find an active perception environment and map the special fields through.
171
+ Additionally, aside of Gymnasium wrappers, `ap_gym.ActivePerceptionVectorRestoreWrapper` also supports
172
+ `gymnasium.vector.SyncVectorEnv` and `gymnasium.vector.AsyncVectorEnv` and will restore proper vector versions of all
173
+ spaces if active perception environments are vectorized this way.
174
+
175
+ ### Environments
176
+
177
+ _ap_gym_ currently comes with a number of image classification environments, which are described in detail in
178
+ the [image classification documentation](doc/ImageClassification.md).
179
+
180
+ #### Image Classification
181
+
182
+ <table align="center" style="border-collapse: collapse; border: none;">
183
+ <tr style="border: none;">
184
+ <td align="center" style="border: none; padding: 10px;">
185
+ <img src="doc/img/CircleSquare-v0.gif" alt="CircleSquare-v0" width="150px"/><br/>
186
+ <a href="doc/CircleSquare.md">
187
+ CircleSquare-v0
188
+ </a>
189
+ </td>
190
+ <td align="center" style="border: none; padding: 10px;">
191
+ <img src="doc/img/MNIST-v0.gif" alt="MNIST-v0" width="150px"/><br/>
192
+ <a href="doc/MNIST.md">
193
+ MNIST-v0
194
+ </a>
195
+ </td>
196
+ <td align="center" style="border: none; padding: 10px;">
197
+ <img src="doc/img/TinyImageNet-v0.gif" alt="TinyImageNet-v0" width="150px"/><br/>
198
+ <a href="doc/TinyImageNet.md">
199
+ TinyImageNet-v0
200
+ </a>
201
+ </td>
202
+ <td align="center" style="border: none; padding: 10px;">
203
+ <img src="doc/img/CIFAR10-v0.gif" alt="CIFAR10-v0" width="150px"/><br/>
204
+ <a href="doc/CIFAR10.md">
205
+ CIFAR10-v0
206
+ </a>
207
+ </td>
208
+ </tr>
209
+ </table>
210
+
211
+ #### 2D Localization
212
+
213
+ <table align="center" style="border-collapse: collapse; border: none;">
214
+ <tr style="border: none;">
215
+ <td align="center" style="border: none; padding: 10px;">
216
+ <img src="doc/img/LightDark-v0.gif" alt="LightDark-v0" width="150px"/> <br/>
217
+ <a href="doc/LightDark.md">
218
+ LightDark-v0
219
+ </a>
220
+ </td>
221
+ <td align="center" style="border: none; padding: 10px;">
222
+ <img src="doc/img/LIDARLocRooms-v0.gif" alt="LIDARLocRooms-v0" width="150px"/><br/>
223
+ <a href="doc/LIDARLocalization.md">
224
+ LIDARLocRooms-v0
225
+ </a>
226
+ </td>
227
+ <td align="center" style="border: none; padding: 10px;">
228
+ <img src="doc/img/LIDARLocMaze-v0.gif" alt="LIDARLocMaze-v0" width="150px"/><br/>
229
+ <a href="doc/LIDARLocMaze.md">
230
+ LIDARLocMaze-v0
231
+ </a>
232
+ </td>
233
+ </tr>
234
+ </table>
235
+
236
+ #### Image Localization
237
+
238
+ <table align="center" style="border-collapse: collapse; border: none;">
239
+ <tr style="border: none;">
240
+ <td align="center" style="border: none; padding: 10px;">
241
+ <img src="doc/img/TinyImageNetLoc-v0.gif" alt="TinyImageNetLoc-v0" width="150px"/><br/>
242
+ <a href="doc/TinyImageNetLoc.md">
243
+ TinyImageNetLoc-v0
244
+ </a>
245
+ </td>
246
+ <td align="center" style="border: none; padding: 10px;">
247
+ <img src="doc/img/CIFAR10Loc-v0.gif" alt="CIFAR10Loc-v0" width="150px"/><br/>
248
+ <a href="doc/CIFAR10Loc.md">
249
+ CIFAR10Loc-v0
250
+ </a>
251
+ </td>
252
+ </tr>
253
+ </table>
254
+
255
+ ### Converting Regular Gymnasium Environments to Active Perception Environments
256
+
257
+ It is possible to convert regular Gymnasium environments into a pseudo active perception environments with the
258
+ `ap_gym.PseudoActivePerceptionWrapper` and `ap_gym.PseudoActivePerceptionVectorWrapper`, respectively:
259
+
260
+ ```python
261
+ env = gymnasium.make("CartPole-v1")
262
+ ap_env = ap_gym.PseudoActivePerceptionWrapper(env)
263
+ ```
264
+
265
+ `ap_gym.PseudoActivePerceptionWrapper` and `ap_gym.PseudoActivePerceptionVectorWrapper` take the environment and add a
266
+ constant zero loss function as well as empty prediction and prediction target spaces.
267
+ The purpose of this conversion is to simplify testing of _ap_gym_ compatible algorithms on regular Gynmasium tasks.
268
+
269
+ If you want to support arbitrary Gymnasium and _ap_gym_ environments, use the `ap_gym.ensure_active_perception_env` and
270
+ `ap_gym.ensure_active_perception_vector_env` functions:
271
+
272
+ ```python
273
+ ap_env_1 = ap_gym.ensure_active_perception_env(gymnasium.make("CartPole-v1"))
274
+ ap_env_2 = ap_gym.ensure_active_perception_env(ap_gym.make("CircleSquare-v0"))
275
+ ap_env_3 = ap_gym.ensure_active_perception_env(gymnasium.wrappers.TimeLimit(ap_gym.make("CircleSquare-v0"), 8))
276
+ ```
277
+
278
+ These functions automatically detect whether to do nothing, apply a restoration wrapper, or perform pseudo active
279
+ perception environment conversion.
280
+
281
+ ## Advanced Usage
282
+
283
+ For more advanced usage, i.e., defining custom environments or wrappers, refer to the [advanced usage documentation](doc/advanced_usage.md).
284
+
285
+ ## License
286
+
287
+ The project is licensed under the MIT license.
288
+
289
+ ## Contributing
290
+
291
+ If you wish to contribute to this project, you are welcome to create a pull request.
292
+ Please run the [pre-commit](https://pre-commit.com/) hooks before submitting your pull request.
293
+ To install the pre-commit hooks, run:
294
+
295
+ 1. [Install pre-commit](https://pre-commit.com/#install)
296
+ 2. Install the Git hooks by running `pre-commit install` or, alternatively, run `pre-commit run --all-files manually.
@@ -0,0 +1,34 @@
1
+ from .active_classification_env import (
2
+ ActiveClassificationEnv,
3
+ ActiveClassificationVectorEnv,
4
+ )
5
+ from .active_perception_env import (
6
+ ActivePerceptionEnv,
7
+ BaseActivePerceptionEnv,
8
+ ActivePerceptionWrapper,
9
+ ActivePerceptionRestoreWrapper,
10
+ ActivePerceptionActionSpace,
11
+ PseudoActivePerceptionWrapper,
12
+ ensure_active_perception_env,
13
+ NoActivePerceptionEnvError,
14
+ )
15
+ from .active_perception_vector_env import (
16
+ ActivePerceptionVectorEnv,
17
+ BaseActivePerceptionVectorEnv,
18
+ ActivePerceptionVectorWrapper,
19
+ ActivePerceptionVectorRestoreWrapper,
20
+ PseudoActivePerceptionVectorWrapper,
21
+ ensure_active_perception_vector_env,
22
+ )
23
+ from .active_regression_env import ActiveRegressionEnv, ActiveRegressionVectorEnv
24
+ from .image_space import ImageSpace
25
+ from .loss_fn import LossFn, LambdaLossFn, ZeroLossFn, CrossEntropyLossFn, MSELossFn
26
+ from .time_limit import TimeLimit
27
+ from .vector_to_single_wrapper import (
28
+ VectorToSingleWrapper,
29
+ ActivePerceptionVectorToSingleWrapper,
30
+ )
31
+
32
+ from .envs.registration import make, make_vec, register_envs
33
+
34
+ register_envs()