I am trying to optimize a mathematical model where I use scipy.optimize.minimize to try a set of different input values x in order for my model to return the output values F as close as possible to the target values F_experimental.
In my program, I observed a strange behavior of the scipy.optimize.minimize callback option. The reproducible tester code (that is partially based here) is:
import numpy as np
from scipy.optimize import minimize,rosen, rosen_der
Nfeval = 1
def rosen(X): #Rosenbrock function
global Nfeval
print('pass rosen',str(Nfeval))
#Nfeval += 1
return (1.0 - X[0])**2 + 100.0 * (X[1] - X[0]**2)**2 + \
(1.0 - X[1])**2 + 100.0 * (X[2] - X[1]**2)**2
def callbackF(Xi):
global Nfeval
print('pass callback',str(Nfeval))
#print(Nfeval, Xi[0], Xi[1], Xi[2], rosen(Xi))
Nfeval += 1
x0 = np.array([1.1, 1.1, 1.1])
optXvalues=minimize(rosen, x0, method='Nelder-Mead',callback=callbackF)
Running this code will return on the screen a very strange result, despite the convergence of the minimizer. A part of it, is:
pass rosen 66
pass rosen 66
pass callback 66
pass rosen 67
pass callback 67
pass rosen 68
pass callback 68
pass rosen 69
pass rosen 69
pass callback 69
pass rosen 70
pass rosen 70
pass callback 70
pass rosen 71
pass rosen 71
pass callback 71
The question is why exactly the minimizer passes 2 times through the objective function rosen? And why is not consistent? In iterations 67 and 68 passed only once.
If I deactivate the callback option and add the counter in the rosen function (just un-comment it), the minimizer passes only once.
If I activate a print function (just un-comment it) inside the callbackF function to obtain the values at each iteration, the program passes once more through the rosen function.
The problem is that I need:
The minimizer to pass only once through the function because in my real problem, I call a simulator to obtain the results (F) of the proposed optimizer values (x).
A way to print/save on each iteration, the iteration number, the x values and the F values.
What do you think is the problem? Can it be a bug in the callback option, a bug in my code or something that I don't understand correctly?
Thanks in advance, Michail