facebookresearch / nevergrad

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

Warning thrown when using register_cheap_constraint with lambda function #1501

Closed SH2282000 closed 1 year ago

SH2282000 commented 1 year ago

Steps to reproduce

When finding the minimum x that fulfill a specific constraint: if this last constraint is defined as a lambda function, the following warning is thrown:

[...].venv/lib/python3.8/site-packages/nevergrad/parametrization/core.py:291: UserWarning: Lambda as constraint is not advised because it may not be picklable.
  warnings.warn("Lambda as constraint is not advised because it may not be picklable.")

Therefore, I replaced my lambda definition:

    constraint = lambda degree: original_pred != max_pred(degree)

...by a function definition...

    def constraint(degree): return original_pred != max_pred(degree)

However, as specified in the documentation, I should be able to use a lambda function for constraining my optimization. I need more information on that, to know if this is a bug or am I misusing NGOpt.

    def constraint(degree): return original_pred != max_pred(degree)

Observed Results

When the lambda definition is replaced by a function definition. No warnings are thrown.

Expected Results

No warnings thrown as in the documentation.

Relevant Code

import nevergrad as ng 

def nevergrad_discrete_search(img, degree_range, perturbation):
    original_pred = np.argmax(certification.predictions_image(img))
    max_pred = lambda degree: np.argmax(certification.predictions_image(img, perturbation, degree))
    constraint = lambda degree: original_pred != max_pred(degree)

    # Discrete, ordered
    param = ng.p.TransitionChoice(degree_range)
    optimizer = ng.optimizers.NGOpt(parametrization=param, budget=100, num_workers=1)
    optimizer.parametrization.register_cheap_constraint(constraint)

    recommendation = optimizer.provide_recommendation()
    for _ in range(optimizer.budget):
        x = optimizer.ask()
        optimizer.tell(x, x.value)

    recommendation = optimizer.provide_recommendation()

    return recommendation.value
teytaud commented 1 year ago

Maybe just

import warnings warnings.filterwarnings("ignore", message=".Lambda as constraint is not advised because it may not be picklable.")

teytaud commented 1 year ago

By the way, note that "register_cheap_constraint" is useful only when the objective function is computationally much more expensive that the constraints. Otherwise the other tool is "constraint_violation". In most applications I use "constraint_violation", but "register_cheap_constraint" is better when the objective function is very expensive and/or does not work when constraints are violated. Reopen the issue or post in https://www.facebook.com/groups/nevergradusers if you need help with constraints, I know that we have not enough doc and users suffer a bit with that.