omegaconf icon indicating copy to clipboard operation
omegaconf copied to clipboard

negative list indices in variable interpolation

Open Jasha10 opened this issue 3 years ago • 9 comments

This issue is based on https://github.com/facebookresearch/hydra/issues/1674.

Describe the bug Negative list indices do not work in interpolations

To Reproduce

from omegaconf import OmegaConf
cfg = OmegaConf.create(
    {
        "list": [8, 16, 32],
        "interp": "${list[0]}",
        "interp_negative": "${list[-1]}",
    }
)
assert cfg.interp == 8
assert cfg.interp_negative == 32  # raises InterpolationKeyError

Expected behavior Negative list indices work in interpolations.

Additional context

  • OmegaConf version: master
  • Python version: 3.9.5

Jasha10 avatar Jun 17 '21 20:06 Jasha10

This is a feature request, not a bug. Interpolation into a list using negative index never worked (and this is the first time someone asks for it). It only seems appropriate because of the new support for brackets in interpolation syntax.

Using the supported syntax in 2.0 will look like this:

cfg = OmegaConf.create(
    {
        "list": [8, 16, 32],
        "interp": "${list.0}",
        "interp_negative": "${list.-1}",
    }
)

We can consider this for 2.2, but I don't think it's high pri.

omry avatar Jun 17 '21 22:06 omry

Using the supported syntax in 2.0 will look like this:

FYI the "${list.-1}" syntax is not working for me. I tried it on the 2.0 branch (gives ConfigKeyError) and on 2.1/master (gives InterpolationKeyError).

Jasha10 avatar Jun 18 '21 02:06 Jasha10

Using the supported syntax in 2.0 will look like this:

FYI the "${list.-1}" syntax is not working for me. I tried it on the 2.0 branch (gives ConfigKeyError) and on 2.1/master (gives InterpolationKeyError).

This was never supported functionality. The reason I mentioned ${list.-1} is because it's equivalent to ${list[-1]}. The fact that we added support for bracketed access in interpolation does not mean this is a real list. We also do not support slice syntax (and we probably shouldn't support it).

omry avatar Jun 18 '21 23:06 omry

Just my own 2 cents, IMHO This is a very important feature for anything related with ML and Deep Learning model configurations. Many times I would like to be able to access the last element of feature layer lists - It makes everything so much easier.

royvelich avatar Aug 07 '23 08:08 royvelich

Many times I would like to be able to access the last element of feature layer lists - It makes everything so much easier.

You can still do it with something like:

OmegaConf.register_new_resolver("last", lambda lst: lst[-1])
layers:
- input
- hidden
- output
last_layer: ${last:${layers}}

odelalleau avatar Aug 07 '23 11:08 odelalleau

Or even:

OmegaConf.register_new_resolver("getindex", lambda lst, idx: lst[idx])
layers:
- input
- hidden
- output
last_layer: ${getindex:${layers}, -1}

Jasha10 avatar Aug 08 '23 22:08 Jasha10

@Jasha10 @odelalleau Thanks for the suggestions, it works for me. I have an additional question, is somehow possible to incorporate those resolvers inside list literals? something like that:

layers: [${getindex:${layers_previous_model}, -1}, 32, 16, 4]

royvelich avatar Aug 09 '23 11:08 royvelich

is somehow possible to incorporate those resolvers inside list literals? something like that:

layers: [${getindex:${layers_previous_model}, -1}, 32, 16, 4]

Yes, this should work. You might just need to quote the interpolation so that YAML doesn't complain.

odelalleau avatar Aug 09 '23 11:08 odelalleau

Thanks! I was missing the quotes :-)

royvelich avatar Aug 09 '23 13:08 royvelich