SciPy - Optimize: callback(intermediate_result: OptimizeResult) what does it mean?

52 Views Asked by At

I believe it is a trivial question but I was not able to find any example and I am struggling to understand how to use this instruction for creating a callback for scipy.optimize

import scipy.optimize as sp
res = sp.minimize(FUN, 0.25,method='Nelder-Mead',bounds=None,callback=STOP)

where the callback is defined as:

def STOP(intermediate_result: sp.OptimizeResult):
    print('intermediate_results',intermediate_result)
    if intermediate_result.fun < 0.005:
        return StopIteration
    else:
        return 0

The intermediate_resultappears to be only the optimal parameter (so it seems I am implemented the instruction callback(xk) and not callback(intermediate_result: OptimizeResult) )

I would like that my function STOP analyse the value of the returned function value and stop in case the value is smaller than 0.005

But generally I would like to understand what the guidance is saying:

All methods except TNC, SLSQP, and COBYLA support a callable with the signature:

callback(intermediate_result: OptimizeResult)

where intermediate_result is a keyword parameter containing an OptimizeResult with attributes x and fun, the present values of the parameter vector and objective function.

Could you please help me ?

When I tried that I got:

AttributeError: 'numpy.ndarray' object has no attribute 'fun'

I tried different way to change the keyword in the function and inside the optimizer but I have not clue of what I am doing

1

There are 1 best solutions below

3
jlandercy On BEST ANSWER

In previous version of SciPy the callback parameter was the current x value as a nd.array (<= 1.9.3). In newer version it is a partial OptimizeResult with fun and x (1.12.0).

First upgrade to latest version of SciPy, then try this MCVE

from scipy import optimize

def callback(intermediate_result):
    if intermediate_result.fun < 0.5:
        raise StopIteration

optimize.minimize(optimize.rosen, x0=[0, 0, 0, 0], method='Nelder-Mead', tol=1e-6, callback=callback)

Also notice that exception should be raised not returned.

For older versions, you have to compute the solution by yourself and raising StopIetration will stop the script (so you have to catch it):

def callback(intermediate_result):
    if optimize.rosen(intermediate_result) < 0.5:
        raise StopIteration

Where new version will stop the algorithm and return a solution with corresponding message:

#   message: `callback` raised `StopIteration`.
#   success: False
#    status: 99
#       fun: 0.4281196937835328

To update your WSL to the latest scipy, issue the following command:

python -m pip install -U --user scipy