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
New feature: enable builds to bind "meta" fields #102
Conversation
@jgbos from some of our chatting, it seemed like you are in favor of this feature. Is that right? Do you have any thoughts / concerns? If we do move forward with this, I would like to figure out good names for everything.. |
This use of an |
@Jasha10 thanks for pointing me to that issue. I would be glad to get your input on / impression of this feature; it would be great if it could help address common issues for Hydra users. Regarding facebookresearch/hydra#1827, it seems like the issue the OP is having really comes down to the cumbersome nature of having to construct groups/yamls by hand; they say:
I can see why they would want to be able to delete nodes in their case. That being said, I have to wonder if simply using |
@rsokl yes I am in favor of this based on our conversations! |
Your pitch above is compelling! This The fact that this post-processing is encoded in the config (via the
In theory, one could dump Using this layer of indirection, one gains the power to perform arbitrary per-node post-processing before the
I think you're right that automating the construction of groups would ease the pain-point.
In theory, this is also something that could be achieved automatically via an indirection layer similar to |
@@ -607,6 +611,24 @@ def builds( | |||
_utils.field(default=just(target), init=False), | |||
), | |||
] | |||
elif hydra_meta: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to handle the case where both hydra_partial
is True
and hydra_meta
is not None
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! I definitely do need to handle this case. This is just a crude WIP right now.
I plan to refactor how we handle hydra_partial=True
so that it also looks for _true_target_
instead of _partial_target_
. I want to converge on a common interface for any/all post-processing functions that hydra-zen
ships.
Yep, this is something that we are okay (happy) with, and hopefully others would be as well. Since To me, this seems preferable over being coupled to custom resolvers; not only do those functions need to be made available to users (making the email scenario you laid out much stickier), but the user also has to take care to register them with omegaconf before instantiating the config! This all being said, I realize that we should document that using certain features (
I was starting to think about this.. It would definitely work, but I am not sure that I would like supporting this. It seems to endorse generally-bad practices. Say that I am configuring a class that has a default kwarg, I realize you probably also are wary of this, hence your "in theory" premise, but I just wanted to lay out my thoughts/reservations while they were still fresh.
Indeed, this is really convenient and quite powerful. And this method can also be used for pre-processing (e.g. more-robust type validation) as well. Some thoughts that I have had:
Finally (sorry for the long post), if there are any particular names for fields (e.g. |
@jgbos I added a to-do list to the top of the PR. The main thing I would like input on is for naming things. |
Agreed!
Yup. I think there are some fundamental aspects of OmegaConf's design that would make it very difficult to support arbitrary rich types while also maintaining backward compatibility.
Yes, there seems to be active discussion around
The first 6 of these only have import when used as part of a string in a defaults list, and the last 4 only matter when used with The most robust way I can think of to avoid future conflicts would be to avoid the leading/trailing underscore pattern. |
This is a good point. I plan to change all hydra-zen-specific fields to be patterned as Fortunately, I can change the implementation of
This is very useful. Thank you for this! 😄
This is well-put. I should provide a description along these lines in hydra-zen's docs to try to distinguish these use-cases.
Definitely let us know if you think of any ideas! |
Closing this to break it into to parts: 1: Migrating to the
|
To-Do:
hydra_meta
,_excluded_
, and_true_target_
hydra_partia=True
scenario to leverage the same mechanism ashydra_meta
PartialBuilds
protocolget_target
andhydrated_dataclass
The Pitch
Heh... so this is a little bit of a weird one, but I think it might be pretty useful.
This enables us to bind so-called "meta" fields to a dataclass via
builds
. By "meta field" I mean a field in the resulting dataclass that will not be used during instantiation.For example, let's build a dictionary that has two typical fields,
a
andb
, and a "meta" fieldc
which will be excluded from the actual instantiation process.To peek under the hood here:
>>> print(to_yaml(Conf)) _target_: hydra_zen.funcs.pass_it <-- (note: I plan to change this function's name) _true_target_: builtins.dict _excluded_: - c a: 1 b: 2 c: 3
Why is this useful? The meta field can be used to store a (configurable) default value, and other fields can reference it via relative interpolation.
This means that we can use the above conf at any level of our config, and the interpolated values will always hold relative to its location.
And..uhh...why is this useful? Consider this config of an image augmentation chain:
Normally
size
,mean
, andstd
would either need to be hard-coded into thebuilds
ofRandomCrop
(etc.) and thus be unconfigurable due to the presence of the list. Or they would need to point to values at the top-level of our experiment's config via absolute interpolation, which messes up composability and makes our configuration messier.But now this config is truly portable! You can plug it in at any level of your config, and its default values will resolve via relative interpolation, plus you can configure these values in a natural way:
This also means that these configs are composable via inheritance (this doesn't work on this branch yet, but it will)
@jgbos let me know what you think of this. I am not sure I am doing a good job selling/explaining this, and maybe that is a bad sign that this feature is too complicated.
It definitely would clean up some configs I have in my research. I wonder if this strikes you as a valuable feature for you as well.
If you do think this is worth having, then I will definitely want to brainstorm with you about the right names for everything. Like is
hydra_meta
really what we want to go with, etc.Feel free to pull this branch and play with it to get a feel for the examples I wrote out above.
Some More Thoughts
It actually occurred to me that I could have taken the image augmentation example even further, in terms of exposing configurable interfaces:
Now all configurable components are exposed in a nice, modular (and named) way.
Although it doesn't seem like inheritance would be quite as useful in this case... so there are pros and cons.
Attaching General Metadata
I am not sure if this would be actually useful, but I also realize that this can let people attach metadata to their configs, like maybe a version number?
Its yaml would be