-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Refactoring of TensorSpec and documentation #1818
Comments
Sorry for totally dropping the ball on this. Here's the long term plan:
I expect (1) and (3) to live in a single PR each. (3) should be super easy to come with, (1) requires a bit of digging but if someone wants to give it a shot it'd be awesome. Eventually we could consider a specs.v2 if we see that the current API is really broken, but I'd rather not do it if we can avoid that. Inviting @matteobettini @skandermoalla @albertbou92 @BY571 @btx0424 to the party if you're interested to comment or help (you never know 😝) |
In few days I can start working on point 1 if it's not too late. Shouldn't take too long! |
Renaming specsThe specs name are clunky and even I don't remember them all. OneHotDiscreteTensorSpec -> OneHot(Spec)
CompositeSpec -> Composite(Spec)
UnboundedContinuousTensorSpec -> Continuous(Spec)
UnboundedDiscreteTensorSpec -> Discrete(Spec)
MultiOneHotDiscreteTensorSpec -> MultiOneHot(Spec)
NonTensorSpec -> NonTensor(Spec) or Object(Spec)
MultiDiscreteTensorSpec -> MultiDiscrete(Spec)
LazyStackedTensorSpec -> Stacked(Spec)
LazyStackedCompositeSpec -> StackedComposite(Spec)
DiscreteTensorSpec -> Categorical(Spec)
BoundedTensorSpec -> Bounded(Spec) or Finite(Spec)
BinaryDiscreteTensorSpec -> Binary(Spec) I put the |
Very needed I think and I love it! What I think we need to nail is to keep namings that are simple yet mutually exclusive. Does What is the use of The rest I really like so my proposal is CompositeSpec -> Composite
UnboundedContinuousTensorSpec -> ContinuousUnbounded
BoundedTensorSpec -> ContinuousBounded
UnboundedDiscreteTensorSpec -> DiscreteUnbounded
OneHotDiscreteTensorSpec -> OneHot
MultiOneHotDiscreteTensorSpec -> MultiOneHot
DiscreteTensorSpec -> Categorical
MultiDiscreteTensorSpec -> MultiDiscrete
BinaryDiscreteTensorSpec -> Binary
LazyStackedTensorSpec -> Stacked
LazyStackedCompositeSpec -> StackedComposite
NonTensorSpec -> NonTensor |
UnboundedDiscreteTensorSpec -> DiscreteUnbounded I would ditch that one altogether, it's just an We can keep the old one and just specialize it based on We'll need to keep the old names for a couple of releases (at least) anyway, so the thing we want to do is raise an appropriate warning to tell people how to use the new ones. CompositeSpec -> Composite
UnboundedDiscreteTensorSpec / UnboundedContinuousTensorSpec -> Unbounded
# We can make ContinuousUnbounded and DiscreteUnbounded, both with predefined kwargs
BoundedTensorSpec -> Bounded
BinaryDiscreteTensorSpec -> Binary (specialized version of Bounded?)
OneHotDiscreteTensorSpec -> OneHot
MultiOneHotDiscreteTensorSpec -> MultiOneHot
DiscreteTensorSpec -> Categorical
MultiDiscreteTensorSpec -> MultiDiscrete
LazyStackedTensorSpec -> Stacked
LazyStackedCompositeSpec -> StackedComposite
NonTensorSpec -> NonTensor |
If you check this, you will see that instance checks with all classes are interchangeable, to make sure that people can smoothly switch from one class to the other. For Continuous and Discrete, we refer to the domain/dtype to determine the class. Lines 3623 to 3793 in ba582a7
|
Hi there. Besides the naming, what do you think of adding some metadata for users to populate? This could be useful for, for example, marking which keys are visual observations or temporally stacked low-dimensional observations. People commonly differentiate the type of obs through their dimensions but in this case, they have the same number of dimensions but are expected to be handled differently. It is in general useful for subsequent algorithm implementation to parse the observations and build the network. Like this: visual_obs_spec = Continuous(shape=[N, W, H])
visual_obs_spec.meta["is_pixel"] = True
stacked_obs_spec = Continuous(shape=[N, T, D])
stacked_obs_spec.meta["is_pixel"] = False |
ok good i agree
My only concern now is for Therefore, just having I would let users be able to instantiate only mutually exclusive leaf specs. AKA to get a categorical they need to create a my suggestion then is CompositeSpec -> Composite
UnboundedDiscreteTensorSpec / UnboundedContinuousTensorSpec -> Unbounded
# We can make ContinuousUnbounded and DiscreteUnbounded, both with predefined kwargs
# Bounding in continuous domain
BoundedTensorSpec -> ContinuousBounded (can also call it Interval or smth that is one word and imples both bounds and continiuity)
# Bounding in discrete domain
BinaryDiscreteTensorSpec -> Binary
OneHotDiscreteTensorSpec -> OneHot
MultiOneHotDiscreteTensorSpec -> MultiOneHot
DiscreteTensorSpec -> Categorical
MultiDiscreteTensorSpec -> MultiDiscrete
LazyStackedTensorSpec -> Stacked
LazyStackedCompositeSpec -> StackedComposite
NonTensorSpec -> NonTensor |
What's the added value of having EDIT: |
@matteobettini |
I like the idea but do we want more specific flags? class SpecMetadata(Enum):
PIXELS = 0
STATE = 1
ACTION = 2
...
visual_obs_spec = Unbounded((C, H, W), dtype=torch.uint8)
state_obs_spec = Unbounded((F,), dtype=torch.float32)
visual_obs_spec.metadata.add(SpecMetadata.PIXELS)
state_obs_spec.metadata.add(SpecMetadata.STATE)
visual_obs_spec.check_metadata(SpecMetadata.STATE) # False
visual_obs_spec.check_metadata(SpecMetadata.PIXELS) # True |
Very cool, my main question is still what is the difference between bounded discrete, categorical and discrete? |
Categorical specStuff you will use to index NumericalUnbounded: box is from -inf to inf (or better from iinfo/finfo.min to max) You'd use unbounded for pixels in uint8 for instance: they're not really bounded (only by the dtype range) and they're not used to index even though they are ints. In fact, |
I see, it is more a semantic meaning, because in practice a categorical 10 can still look like a bounded discrete 0 to 10. What is this new What I suggest is run them by someone that is not familiar with torchrl (you can pick a guy from the street) and ask to guess what each class intuitively does. I think it is core that this is as much intuitive and simple as possible to users. so we need as much input as we can get. |
All the previous classes still exist. The overlap between categorical, one-hot and others already existed (a one-hot tensor could pass the test to belong to a bounded / unbounded spec). I don't think anything is changing on that side. At the end of the day, these classes are not only there to specify the dtype and possible values of the tensors (otherwise we'd just need one tensor spec) but also their meaning. In fact, we have a function to generate specs automatically ( There is no |
Motivation
When creating a custom environment, deciding the correct TensorSpec (TS) to use is not straightforward. Some TS are never used, some look very similar to each other and sometimes docstrings are too concise or they miss some parameters.
Solution
After a brief talk with @vmoens and @fedebotu, we propose:
Alternatives
The refactoring might happen as a v2 of the current tensor_specs module, to avoid breaking compatibility with previous versions of the code.
Additional context
This feature is proposed as a mean to improve user experience and as a possible follow up to #1795
Checklist
The text was updated successfully, but these errors were encountered: