How to pass arguments to callback function in scipy.optimize.differential_evolution

Question:

I am using differential_evolution from scipy.optimize for my optimization problem. My optimizer takes some arguments for the optimization.

Code –

res = optimize.differential_evolution(objective,bounds,args=arguments,disp=True,callback = callback_DE(arguments))

I also have a callback function. I want to send my arguments to my callback function and that is where my issue arises.

If I don’t pass any arguments to my callback function, it works fine –

def callback_DE(x,convergence):        
   '''
   some code
   '''

However, if I give arguments as a parameter in the function definition like –

def callback_DE(x,convergence,arguments):        
   '''
   some code
   '''

It throws an error.

What is the correct way to pass arguments to the callback function?

Asked By: chink

||

Answers:

This is not possible. You can only use the two values that are given to you. The point of the callback is to follow your optimization and stop it early if you choose to do so based on some condition it satisfied, by returning True.

See the description from the reference for more details:

callback : callable, callback(xk, convergence=val), optional

A function to follow the progress of the minimization. xk is the current value of x0. val represents the fractional value of the population convergence. When val is greater than one the function halts. If callback returns True, then the minimization is halted (any polishing is still carried out).

If you really need to use the arguments, you should just access them directly from inside the function.

Answered By: Akaisteph7

Accturally, I found a way to do that. You need to use the functools.partial to achieve that.

Following is a small example:

    from functools import partial
    # the callback function with two 'undesired' arguments
    def print_fun_DE(xk, convergence, name, method):
    print('for {} by {} : x= {} on convergence = {} '.format(name, method, xk,convergence))
    # the way we call this callback function:
    callback=partial(print_fun_DE, name=data_name, method=method),
Answered By: Junzhong Lin

I pass arguments by making the function part of a Python Class. The arguments are put in the class object before starting differential_evolution.

Here is an example using the callback stop_early:

result = differential_evolution(objective_function, 
         self.bounds, self.args, maxiter=self.maxiter,
         disp=self.disp, callback=self.stop_early, workers=n_cpus, updating='deferred')

`

and here is the callback function:

def stop_early(self, xk, convergence):
    error = objective_function(xk, *self.args)
    return error < 0.1
Answered By: Zod