Skip to content
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] support use case of composing the same config node in multiple places in the config tree #235

Closed
YannDubs opened this issue Oct 16, 2019 · 14 comments · Fixed by #584
Labels
enhancement Enhanvement request
Milestone

Comments

@YannDubs
Copy link
Contributor

YannDubs commented Oct 16, 2019

🚀 Feature Request

Be able to copy all the elements of one config in an other.

Motivation

In my code I have 2 modules which are trained, meaning that I have 2 optimizers. I would like to modify the parameters of one optimizer, but don't want to copy have all default optimizer values written twice. I.e would like to do that python main.py module1.optimizer=adam module1.optimizer.lr=0.01 module2.optimizer.lr=0.01 but not have to define a optimize twice. Something like that:

module1:
  ...
  optimizer: ${optimizer.adam}

module2:
  ...
  optimizer: ${optimizer.adam}

which would use the adam optimizer as default for module 1 and 2 without having to dupicate it.

@YannDubs YannDubs added the enhancement Enhanvement request label Oct 16, 2019
@omry
Copy link
Collaborator

omry commented Oct 16, 2019

The current model in Hydra does not support this kind of thing well.
One thing to try is something with interpolating config nodes, which I mentioned in your other issue:

defaults:
  optimizer: adam

module1:
  ...
  optimizer: ${optimizer}

module2:
  ...
  optimizer: ${optimizer}

I will keep this open as a reminder to improve support for this use case.

@YannDubs
Copy link
Contributor Author

YannDubs commented Oct 16, 2019

In the other thread you say "You can interpolate a node, not just a value" which is what I would like (if I understand what you mean). Can you give an example of how to do that ?

Because in the code above, ${optimizer} is simply the string adam not a dictionary/node right?

@omry
Copy link
Collaborator

omry commented Oct 16, 2019

optimizer is not the string adam, it's the node for adam optimizer that is in optimizer/adam.yaml.

@omry
Copy link
Collaborator

omry commented Oct 16, 2019

I am actually not 100% sure how this would work if you start overriding things, but give it a try and let me know.

@YannDubs
Copy link
Contributor Author

YannDubs commented Oct 16, 2019

I am actually not 100% sure how this would work if you start overriding things, but give it a try and let me know.

I just tried : it overrides the main optimizer (i.e. it does not copy the node), so what I was saying is not possible python main.py module1.optimizer.lr=0.1 module2.optimizer.lr=0.01 sets the lr to 0.01 (the last value used) for the main optimizer => also for both modules

@YannDubs
Copy link
Contributor Author

I don't see any usecases for interpolating the node if it's not copied, right ? if so maybe it would be worth copying instead ?

@omry
Copy link
Collaborator

omry commented Oct 16, 2019

One use case is to make the values of the node accessible in multiple places, much like the use case value interpolation.

Something that can be implemented here is a copy function, but this may be harder than it seems:

module1:
  ...
  optimizer: ${copy:optimizer}

I will keep this open to try this later.
If you would like to try look at custom interpolations in OmegaConf.
As I said, although returning a copy may sound trivial it may actually be quiet tricky and have some weird side effects.
It's easy enough to try.
Don't use the function name copy though to avoid conflict with what I will try to implement later.

maybe copy_node?

@omry
Copy link
Collaborator

omry commented Oct 16, 2019

This should probably be implemented in OmegaConf. there is a good chance that it's not easily possible to do externally at the moment.

@omry
Copy link
Collaborator

omry commented Oct 16, 2019

until this is implemented, a workaround can be implemented as a symlink at the file system level:
optimizer1/{adam,nexterov,sgd>.yaml
optimizer2 -> optimizer1

@omry omry changed the title [Feature Request] Copying configs in other configs [Feature Request] support use case of composing the same config node in multiple places in the config tree Oct 16, 2019
@omry
Copy link
Collaborator

omry commented Oct 21, 2019

another idea I had which might be easier to implement is to use the defaults to do this by adding a few optional fields (source, dest, and group).

for example:

defaults:
   - optimizer: adam
     source: optimizer
     dest: optimizer1
   - optimizer: adam
     source: optimizer
     dest: optimizer2

To make it possible to override from the command line, maybe add another optional field for the group name:

defaults:
   - optimizer1: adam  # identifier optimizer1, with value adam
     group: optimizer  # group optimizer, this means optimizer/adam.yaml will be used
     source: optimizer # this is the source path in the config
     dest: optimizer1  # this is the destination path. when included, the optimizer node will be added ad optimizer1
   - optimizer2: adam
     group: optimizer
     source: optimizer
     dest: optimizer2

This is not as elegant as previous suggestions but it gives quiet a bit of flexibility.
Thoughts?

@omry
Copy link
Collaborator

omry commented Feb 16, 2020

Another idea to play with:

group@path=name

or in defaults:

defaults:
  - db@src_db: mysql
  - db@dst_db: mysql

I kind of like this one.

@isvoboda
Copy link

isvoboda commented May 9, 2020

I am in a similar situation composing my configurations. My use-case include predefined configuration of an experiment based on the suggestion from #386 (comment)

I do not know how to redefine the group model in defaults:

  • conf/config.yaml
defaults:
  model: UNetPix
  • conf/model/UNetPix.yaml
model:
  class: models.UNet.UNetPix
    params:
      kwarg1: ...
      kwarg2: ...
  • conf/model/UNetTC.yaml
model:
  class: models.UNet.UNetTC
    params:
      kwarg1: ...
      kwarg2: ...

I would like to add configuration of an experiment deploying the UNetTC instead of UNetPix in such a way I can just call python train.py experiment=UNetTC.

  • conf/experiment/UNetTC.yaml
model: UNetTC # Here I would like to change UNetPix by UNetTC group defined in model/UNetTC.yaml
... # other experiment related configurations

Is this currently possible?

@omry
Copy link
Collaborator

omry commented May 9, 2020

Your question does not seem related, please ask it in the chat or open a new issue.

@isvoboda
Copy link

isvoboda commented May 9, 2020

I would say it is a particular case related to the "composing the same config node in multiple places". I have opened a new issue #582 (comment)

@omry omry added this to the 1.0.0 milestone May 14, 2020
@omry omry mentioned this issue May 14, 2020
@omry omry closed this as completed in #584 May 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhanvement request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants