facebookresearch / nevergrad

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

Can not pickle the optimizer #1459

Open Ne-oL opened 2 years ago

Ne-oL commented 2 years ago

Steps to reproduce

  1. This is the code:

    optimizer = ng.optimizers.NGOpt(parametrization=parametrization, budget=5000)
    optimizer.enable_pickling
    early_stopping = ng.callbacks.EarlyStopping(lambda opt: opt.current_bests["minimum"].mean < -0.95)
    optimizer.register_callback("ask", early_stopping)
    optimizer.register_callback("tell", ng.callbacks.ProgressBar())
  2. when i try to dump the optimizer using either of these codes:

    optimizer.dump('Opt60p.pkl')
    or
    with open('60P.pkl', 'wb') as file:
    # A new file will be created
    pickle.dump(optimizer, file)
  3. the dumping process happens inside the optimized function as to dump the optimizer after each trial.

Observed Results

Expected Results

Relevant Code

def calcFunct():
    someCalculations
    optimizer.dump('OptPickle.pkl')
    return score
if __name__ == "__main__":
    recommendation = optimizer.minimize(calcFunct)
bottler commented 2 years ago

I'm not sure if this fixes it, but optimizer.enable_pickling should be optimizer.enable_pickling().

bottler commented 2 years ago

Can you replace the callback with a proper function?

So

early_stopping = ng.callbacks.EarlyStopping(lambda opt: opt.current_bests["minimum"].mean < -0.95)

Becomes

def callback(opt):
    return opt.current_bests["minimum"].mean < -0.95
early_stopping = ng.callbacks.EarlyStopping(callback)
Ne-oL commented 2 years ago

I'm not sure if this fixes it, but optimizer.enable_pickling should be optimizer.enable_pickling().

This didn't fix it but i have no idea if it would create any problems in the future so i changed it to the suggested.

Can you replace the callback with a proper function?

So

early_stopping = ng.callbacks.EarlyStopping(lambda opt: opt.current_bests["minimum"].mean < -0.95)

Becomes

def callback(opt):
    return opt.current_bests["minimum"].mean < -0.95
early_stopping = ng.callbacks.EarlyStopping(callback)

This did the Job, now its working fine. i knew that python couldn't pickle lambda functions as there can be many, but i never noticed that lambda was used in the EarlyStopping callback. i thought it was used internally in one of the underlying functions... thank you very much.

I would like to close the issue now, but i wanted to point out a few things that can help alleviate similar future issues and leave it up to you to close it at your own convenience:

  1. I copied the EarlyStopping command verbatim from the examples the docs, and ALL the examples use lambda, so if it wouldn't have a negative effect i think it would be wise to change the lambda to proper function as to make things easier to newbies like me.
  2. Regarding the optimizer pickling, the dumping process isn't very well discussed in the docs, and there is no example that shows the process of enabling the pickling, then dumping the optimizer (within the cost function) and finally loading it in the main to resume. so a proper example that shows the usage of these function would truly be helpful. Finally thank you very much for the awesome library, it's been immensely helpful for my research. i wish i could help contribute but I'm still very new in the field. if that okay, I would be more than happy to help.