facebookresearch / nevergrad

A Python toolbox for performing gradient-free optimization
https://facebookresearch.github.io/nevergrad/
MIT License
3.9k stars 350 forks source link

Bounds check error in log scalar #1472

Open llucid-97 opened 1 year ago

llucid-97 commented 1 year ago

Hi, I have an instrumentation that contains a log scalar. Some samples that it generates trigger an out of bounds error when trying to spawn a child off its values.

Steps to reproduce

I've contrived this minimum example to highlight the issue: using: python 3.10.4 on linux, nevergrad 0.5.0

import nevergrad as ng

param = ng.p.Log(init=1e-5, lower=1e-5, upper=1e1) # This does not trigger an out-of-bounds error
param.spawn_child(1e-5) # neither does this
print(f"{param.value=}")
param.spawn_child(param.value) # but this does

Observed Results

Here's the output & traceback:

param.value=9.999999999999989e-06 Traceback (most recent call last): File "/home/agimg/projects/fastpbrl/scripts/scratchpads/nevergrad_bounds.py", line 6, in param.spawn_child(param.value) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/core.py", line 348, in spawn_child child.value = new_value File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 190, in set obj._layers[-1]._layered_set_value(value) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 216, in _layered_set_value super()._layered_set_value(np.array([value], dtype=float)) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 96, in _layered_set_value return self._call_deeper("_layered_set_value", value) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 84, in _call_deeper return func(*args, kwargs) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 227, in _layered_set_value super()._layered_set_value(np.asarray(value)) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 96, in _layered_set_value return self._call_deeper("_layered_set_value", value) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 84, in _call_deeper return func(*args, *kwargs) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_datalayers.py", line 172, in _layered_set_value super()._layered_set_value(self.backward(value)) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 96, in _layered_set_value return self._call_deeper("_layered_set_value", value) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_layering.py", line 84, in _call_deeper return func(args, kwargs) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/_datalayers.py", line 279, in _layered_set_value super()._layered_set_value(self._transform.backward(value)) File "/home/agimg/anaconda3/envs/pbrl/lib/python3.10/site-packages/nevergrad/parametrization/transforms.py", line 220, in backward raise ValueError( ValueError: Only data between [-5.] and [1.] can be transformed back. Got: [-5.]

Expected Results

This is a contrived example to highlight the issue. In my real code, the 1e-5 isn't an initial parameter set by me, it's randomly produced by a sample() call to the log dist. While this behavior is technically correct because param.value=9.999999999999989e-06 and is indeed out of bounds, it doesn't make sense that the user should have boiler plate code to check that values we pass to initialize a parameter are valid if they're sampled from the same parameter

Relevant Code

See steps to reproduce