facebookresearch / nevergrad

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

ParaPortfolio throwing budget errors with multiple workers. #1584

Open smestern opened 6 months ago

smestern commented 6 months ago

Steps to reproduce

  1. Create a ParaPortfolio object with num_workers > 4
  2. Run either minimize or ask-tell optimization over a given function
  3. Throws budget error after running for a while

Observed Results

Appears to crashing while generating an ask candidate about 60% of the way thru the budget. The error pops up at line 505 of the optimizers.py

  File "/home/smestern/.local/lib/python3.8/site-packages/nevergrad/optimization/base.py", line 701, in minimize
    args = self.ask()
  File "/home/smestern/.local/lib/python3.8/site-packages/nevergrad/optimization/base.py", line 505, in ask
    assert (
AssertionError: Error: Error: Over the budget (reinitialize if you want to start over)

The optimizer that throws the error appears to be the ScrHammersly, probably because it cares about the budget.

Expected Results

Should expend the full budget provided by budget regardless of the num_workers

Relevant Code

Here is a minimally replicable script.

import numpy as np
import nevergrad as ng

def func_x(x):
    x = list(x.values()) #hack to get the values out of the dict
    return (0.1+x[0])**3 + (0.3+x[1])**2 + x[2]**1 + x[3] 

def main():
    workers = 4
    rounds = 100
    params = ng.p.Dict(x_1=ng.p.Scalar(lower=-3, upper=8), #randomly chosen bounds to test
                       x_2=ng.p.Scalar(lower=-0.4, upper=0.2),
                       x_3=ng.p.Scalar(lower=-5, upper=0.1),
                       x_4=ng.p.Scalar(lower=-20, upper=20))

    optimizer = ng.optimizers.ParaPortfolio(parametrization=params, budget=rounds, num_workers=1)
    #try the minimization interface
    min = optimizer.minimize(func_x, verbosity=2) #this works

    optimizer = ng.optimizers.ParaPortfolio(parametrization=params, budget=rounds, num_workers=workers)
    min = optimizer.minimize(func_x, verbosity=2) #this breaks

    optimizer = ng.optimizers.ParaPortfolio(parametrization=params, budget=int(rounds*workers), num_workers=workers)
    min = optimizer.minimize(func_x, verbosity=2) #this breaks

    #Ask and tell also breaks
    optimizer = ng.optimizers.ParaPortfolio(parametrization=params, budget=rounds, num_workers=workers)
    for _ in range(rounds):
        x_list = []
        for _ in range(workers):
            x_list.append(optimizer.ask())
        y_list = [func_x(list(x.value)) for x in x_list]
        for x, y in zip(x_list, y_list):
            optimizer.tell(x, y)

    print(optimizer.provide_recommendation().value)
if __name__ == '__main__':
    main()
teytaud commented 6 months ago

Thanks for pointing out this. Rubberstamp fix https://github.com/facebookresearch/nevergrad/pull/new/paraportfoliobugfix Still under work, not carefully checked.