Minimization and SetMaxFunctionCalls - strange behavior

Hello,

I have encoutered a strange behavior when minimizing a function;

If I set a limited max functions calls :

fitter.Config().MinimizerOptions().SetMaxFunctionCalls(2)

and do a minimization; I get FCN value min2 = fitter.Result().MinFcnValue() = 23141916.835.

However, If I print all return values of the FCN function called during the minimization I get the following list:

0 fcn= 23141916.835 # min2
1 fcn= 42766058.2492
2 fcn= 9548078.45118 # min1
3 fcn= 24832967.3401
4 fcn= 21511169.3603
5 fcn= 25553916.835
6 fcn= 20909916.835
7 fcn= 23375016.835
8 fcn= 22910616.835

The minimal value from this list is min1=9548078.45118 which is significantly lower then min2.

Why are the min1 and min2 values different? ](*,)

If I uncomment the line with SetMaxFunctionCalls the problem is gone. A (non)working example reproducing the problem is attached.

Many thanks in advance for your help.

Regards,
Jiri
minimization.py (2.57 KB)

Hi,

You have set a very low values of function calls. The minimiser (Minuit) could not complete the first iteration, because it already reached the maximum number of function calls. For this reason the initial value of the function is returned.

Lorenzo

Hi,

yes, this was also one of my explenation. Is there any reason why not to return a minima corresponding to lowest fcn values in such cases when SetMaxFunctionCalls has been set? It looks like no better minima was found at all with such settings ; but the problem is that even if there were calculateded there are simply not considered by Fitter…

However, in my real case I get a list like that (with option SetMaxIteration(20) instead of SetMaxFunctionCalls):

call, fcn_value
0, 388.7750659099401 # first value

13547, 359.19653482312987 # min1; real min not returned by Fitter

13582, 388.5835398065377 # min2; returned by Fitter (Invalid FitResult (status = 4 ))

13598, 388.76441487015825 # last value

I.e, min2 is returned by Fitter even if lower value min1 has been already calculated before min2. This is quite puzzling as I would expect min1 would be returned by Fitter at least in this case.

What are the conditions to return a fcn value - minima by Fitter (Minuit2)? It looks to me that it is not only the minimal calculated value of FCN (min2 from the list above is invalid anyway so I don’t see any reason why it should be returned instead of min1…).

Maybe I have missed something. I would just like to understend it. :wink:

Many thanks for your help!

Cheers,
Jiri

Hi,

The algorithms performs some internal function evaluation (for example for computing derivatives) within one iteration. These evaluations are not considered and compared with previous ones and then saved as best function minimum for the iteration. It is not by calling randomly the function that we will find a better minimum.
After each iteration, the number used of function call is checked. If it is exceeded the algorithm exits with a function minimum which is the one obtained from the last iteration.
Now, you stop before the real minimization has started so in your case it might exit with the initial function value.
The algorithm is designed to work until the end. If you want to be faster, it is better to increase the tolerance.
I am not sure I understand your use case

Lorenzo

Hello,

[quote]
The algorithms performs some internal function evaluation (for example for computing derivatives) within one iteration. These evaluations are not considered and compared with previous ones and then saved as best function minimum for the iteration.[/quote]

This explain the behavior (from both my first and also the second post) which I did’t understand. I completely forgot that there may be such extra function calls…

[quote]
I am not sure I understand your use case[/quote]

I actually customize a chi^2 and add some extra penalty functions (i.e. not just simple fitting) and the actual final FCN function is therefore rather complicated (depending mainly on a theoretical model which is fitted to data, of course) and it may take some time to calculate it. In that case I want to see some intermediate results from a minimizer, to see whether FCN value is getting lower or not at all (or some other extremaly useful info) after certain “limited” number of the iterations (or function calls). I have often good reasons to change my code accordingly already after the limited number of iterations without need to wait for output from “unlimited” minimization which may take pretty long time.

I have tried to use the functions SetMaxFunctionCalls or SetMaxIterations to somehome obtain the intermediate results but I see, that I should be more carefull with setting too small numbers (especially with the SetMaxFunctionCalls).

Some minimizers I have seen allow to run some user defined code after each iteration (typically to print some info); but this is probably not available in ROOT (I know about fitter.Config().MinimizerOptions().SetPrintLevel method but it prints only some predefined info…). This is also a reason why I sometimes print some info after each FCN function call (and recently discovered the behaviour mentioned in my first and second post…)

Many thanks once more!

Jiri

Hi

I understand now your use case. Thanks for explaining it. What you need is the FCN value after each iteration. I think you are using Minuit2. I think, it does not stop on the number of iterations, which could be desirable and it could be implemented. It considered iterations as function calls, which is not right.
However, if you are using one of the latest version of Minuit2, by doing SetPrintLevel(1), it should print the function value at the end of each iteration.
I have already thought about having such function after each iteration. It could be eventually impelmented in feature versions of the code.

Best Regards

Lorenzo

Hello Lorenzo,

[quote]
I think you are using Minuit2. I think, it does not stop on the number of iterations, which could be desirable and it could be implemented.[/quote]

Yes, I’m using Minuit2 right now (ROOT 5.33/02; tags/v5-33-02@43252). If a number of max iterations is set I would expect to stop right after the number is reached. If it could be implemented at some point I would be grateful.

[quote]
I have already thought about having such function after each iteration. It could be eventually impelmented in feature versions of the code. [/quote]

If a user defined function could be run after each iteration it would be also useful. I would be mainly interested if the function could be defined also on python side (I read that ROOT 6 will bring a lot of changes maybe also in that direction so maybe then …).

I have run my optimization with options:

minOpt = fitter.Config().MinimizerOptions() minOpt.SetMinimizerType("Minuit2") minOpt.SetMinimizerAlgorithm("Minimize") minOpt.SetPrintLevel(10) minOpt.SetMaxIterations(20)

The main part of the output is attached. What I do not understand is that at iteration #189 FCN = 359.1970455107 but the final optimized value returned by Fitter is 388.584, i.e. significantly higher. Why is not returned the value 359.1970455107 calculated in last iteration #189 (it looks like it is the minimal value reached out of all the iterations)? Simplex algorithm is run after Migrad and it looks to me like the result from Migrad (which fails) is forgoten and a result from Simplex (just 1 iteration) is returned…

(also in this case I set max iteration to 20 but actually much much more 189 iterations were performed…)

Many thanks.

Regards,
Jiri

Hi,

Yes, this is strange it returns an higher value from Simplex. I would need the code to understand it better, probably Simplex fails immediately. Try running maybe just “Migrad” and then separately “Simplex” and do not use “Minimize”.
I will try to implement your suggestion for ROOT 6

Best Regards

Lorenzo

Hi,

many thanks. I’ve maneged to create a simple example that fails similarly as my program (see attachment). The output is (“python minimization.py”):

Minuit2Minimizer: Minimize with max-calls 20 convergence for edm < 1 strategy 1 MnSeedGenerator: for initial parameters FCN = 5.23111e+40 MnSeedGenerator: Initial state: - FCN = 5.23111094679e+40 Edm = 5.42e+40 NCalls = 13 VariableMetric: start iterating until Edm is < 0.002 VariableMetric: Initial state - FCN = 5.23111094679e+40 Edm = 5.42e+40 NCalls = 13 VariableMetric: Iteration # 1 - FCN = 6.566131070305e+37 Edm = 9.58271e+34 NCalls = 32 Info in <Minuit2>: VariableMetricBuilder: call limit exceeded. Info in <Minuit2>: VariableMetricBuilder: FunctionMinimum is invalid, reached the function call limit Info in <Minuit2>: CombinedMinimumBuilder: migrad method fails, will try with simplex method first. Simplex: Final iteration - FCN = 9.240026671101e+37 Edm = 5.22187e+40 NCalls = 37 Info in <Minuit2>: Simplex did not converge, #fcn calls exhausted. Info in <Minuit2>: CombinedMinimumBuilder: both migrad and simplex method fail. Number of iterations 1 ----------> Iteration 0 FVAL = 9.2400266711e+37 Edm = 5.22187092012e+40 Nfcn = 37 Error matrix change = 1 Parameters : p0 = 9.4 p1 = -9.55 Info in <Minuit2>: Minuit2Minimizer::Minimize : Minimization did NOT converge, Reached call limit Minuit2Minimizer : Invalid Minimum - status = 4 FVAL = 9.24003e+37 Edm = 5.22187e+40 Nfcn = 37

i.e., higher value FCN = 9.240026671101e+37 from Simplex is returned instead of lower value FCN = 6.566131070305e+37 from Migrad. It looks like a bug somewhere which is related to SetMaxFunctionsCalls (Iterations) and “Minimize” algorithm.

Many thanks for your help.

Regards,
Jiri
minimization.py (2.72 KB)

Hi,

Thanks for the example. I will look at it,but again I think the problem is that you stop too early. As I said earlier, it can happen that first iteration gives a function value worst that the initial one.
When you stop earlier, we return the last computed function value and not the minimum value of the function found so far.

Lorenzo

Hello,

This I would understand but my last example is different (as far I understand the output). Initial value of FCN was 5.23111e+40 then migrad after 1 iteration gives lower value FCN = 6.566131070305e+37. However, final FCN value was taken from Simplex FCN = 9.240026671101e+37 even if it is higher then the one from migrad…

Also in my real program thousends of iterations are performed and much lower value of FCN is found but at the end the (wrong) value from Simplex is returned…

Regards,
Jiri