Edm is above max

Hello,

I am trying to use TVirtualFitter as in the example fit2dHist.C. According to what I read, minimization should exit if max calls (in my case, 1000000) is reached or a minimum with appropriate edm (<1) is found. Anyway, it seems that my code is exiting after only 11 calls without reaching appropriate edm value. The ouput is as follows.

TFitterMinuit - Minimize with max iterations = 1000000 edmval = 1 errorDef = 1
0 23.8363 723.268
1 58.5014 795.595
2 85.4793 650.941
3 25.6351 759.527
4 42.7115 687.009
5 21.6367 741.409
6 25.6351 759.527
7 23.1268 732.34
8 23.5691 750.473
9 24.8311 736.875
10 21.6367 741.409
TFitterMinuit::Minimization DID not converge !
FVAL  = 21.6367
Edm   = 1.49009
Nfcn  = 11
      Edm is above max

In addition I want to perform minimization with SIMPLEX, MIGRAD and finally MINOS, Using MINOS anyway I get “TFitterMinuit::MINOS failed due to invalid function minimum” even if MIGRAD minimization exited correctly.

Can you help me?

Hi,

I see you are using TFitterMinuit, which is an old interface to Minuit2, which has been removed from ROOT starting from version 6.
I am not sure which version exactly you are using of ROOT, maybe the version of Minuit2 is very old and could contain still some bugs.
Otherwise what you observe could be cause by a failure during the minimisation (if you increase the print level you might see an error message).
This failure is typically caused by bad precision in computing the function to minimise.

Best Regards

Lorenzo

Hi Lorenzo,

thank you for reply. My ROOT version is 5.34/18, not 6, but not so old. I am using TVirtualFItter in the following way

TVirtualFitter::SetDefaultFitter("Minuit2");
TVirtualFitter * minuit = TVirtualFitter::Fitter(NULL, nfitpar);

minuit->SetParameter(0, "f", initfact, 0.1*initfact, initfact-500., initfact+500.);
minuit->SetFCN(myFcn);

minuit->SetPrecision(TMath::Power(10., 0));
minuit->SetMaxIterations(TMath::Power(10., 6));
double arglist[100];
arglist[0] = 3;
minuit->ExecuteCommand("SET PRINT", arglist, 2);
arglist[0] = 1000000.;              // number of function calls
arglist[1] = TMath::Power(10., 0); // tolerance
minuit->ExecuteCommand("MIGRAD", arglist, 2);

Anyway, I am not able to get more information than the one in my first post, even using “3” as print level.

If you think this method is old, could you please link me an example of different way or fitting? Actually, what I want to do is determination of a x scale parameter between two histograms and I am using chi square as myFCN.

Hi,

You should use the ROOT::Fit:Fitter class as described in the Users Guide,
root.cern.ch/root/htmldoc/guide … it-classes

You can use also the method ROOT::Fitter::FitFCN which will allow to fit a function with the same interface as the TVirtualFitter.

If you need help I can migrate your code.

Lorenzo

Thank you for suggestions, I tried to use ROOT::Fit:Fitter, changing my code in the following way

ROOT::Fit::Fitter fitter;
fitter.Config().SetParamsSettings(nfitpar,par0);
//fitter.Config().ParSettings(0).Set("f",initfact);
fitter.Config().ParSettings(0).SetLimits(TMath::Max(0., initfact-500.), initfact+500.);
fitter.Config().ParSettings(0).SetStepSize(5);

ROOT::Math::MinimizerOptions opt;
// print the default minimizer option values
opt.SetMinimizerType("Minuit2");
opt.SetTolerance(1);
opt.SetMaxFunctionCalls(1000000);
opt.SetMaxIterations(1000000);
opt.SetPrintLevel(3);
opt.Print();

opt.SetMinimizerAlgorithm("Simplex");
fitter.SetFCN(myFCN);
fitter.FitFCN();

ROOT::Fit::FitResult result = fitter.Result();
result.Print(std::cout);

but I am still getting same behavior and no more information from “SetPrintLevel(3)”

           Minimizer Type :         Minuit2
      Minimizer Algorithm :          Migrad
                 Strategy :               1
                Tolerance :               1
           Max func calls :         1000000
           Max iterations :         1000000
           Func Precision :              -1
         Error definition :               1
              Print Level :               3

****************************************
         Invalid FitResult  (status = 4 )
****************************************
Minimizer is Minuit / Migrad
MinFCN                    =      59.2763
NDf                       =            0
Edm                       =  2.60958e+06
NCalls                    =           53
Par_0                     =      1000.15   +/-   746.941      	 (limited)

I believe I am doing something wrong in FCN because Ndf is 0.

void myFCN(Int_t & /*nPar*/, Double_t * /*grad*/ , Double_t &fval, Double_t *par, Int_t /*iflag */)
{
	double chi2 = 0.;
	npfits = 0;

	// make MC hist
	TH1D *h1 =new TH1D("h1", "h1", nbin, min, max);
	h1->Sumw2();

	for (unsigned int i=0; i<nx; i++)
	{
		h1->Fill(x[i]*par[0]);
	}
	const double currnorm = h1->Integral()/h2->Integral();
	h1>Scale(currnorm);

	for (unsigned int i=0; i<nbin; i++)
	{
		const double cont1 = h1->GetBinContent(i+1);
		const double err1 = TMath::Power(h1->GetBinError(i+1), 2.);
		const double cont2 = h2->GetBinContent(i+1);
		const double err2 = TMath::Power(h2->GetBinError(i+1), 2.);

		if (cont2)
		{
			fval += TMath::Power(cont1-cont2, 2.)/(err1 + err2);
			npfits++;
		}
	}

	chi2 = fval;
}

where h2, x[nx], nx are global variable filled in main program.

HI,

You don;t have a detailed output of all Minuit iterations ?
You should get something like this, when you use PrintLevel=3

Minuit2Minimizer: Minimize with max-calls 1000000 convergence for edm < 0.001 strategy 1
MnSeedGenerator: for initial parameters FCN = 903.4001
MnSeedGenerator: Initial state:   - FCN =         903.4001 Edm =      361.274 NCalls =      7
MnSeedGenerator: Negative G2 found - new state:   - FCN =   84.01703428883 Edm =      157.459 NCalls =     33
VariableMetric: start iterating until Edm is < 2e-06
VariableMetric: Initial state   - FCN =   84.01703428883 Edm =      157.459 NCalls =     33
VariableMetric: Iteration #   0 - FCN =   84.01703428883 Edm =      157.459 NCalls =     33
VariableMetric: Iteration #   1 - FCN =    3.41135157006 Edm =    0.0335156 NCalls =     39
VariableMetric: Iteration #   2 - FCN =   3.389341068459 Edm =     0.005868 NCalls =     45
VariableMetric: Iteration #   3 - FCN =   2.698713690046 Edm =     0.159352 NCalls =     56
VariableMetric: Iteration #   4 - FCN =   2.337685859272 Edm =     0.908401 NCalls =     63
VariableMetric: Iteration #   5 - FCN =   1.876796063821 Edm =       0.2185 NCalls =     69
VariableMetric: Iteration #   6 - FCN =   1.544742346472 Edm =     0.106457 NCalls =     78
VariableMetric: Iteration #   7 - FCN =   1.273465200159 Edm =     0.440474 NCalls =     88
VariableMetric: Iteration #   8 - FCN =  0.4084995477976 Edm =     0.101333 NCalls =    103
VariableMetric: Iteration #   9 - FCN =  0.3960835458631 Edm =    0.0408561 NCalls =    109
VariableMetric: Iteration #  10 - FCN =  0.2825415123901 Edm =    0.0220764 NCalls =    118
VariableMetric: Iteration #  11 - FCN =  0.2358235302355 Edm =    0.0744098 NCalls =    125
VariableMetric: Iteration #  12 - FCN =  0.1173976475646 Edm =    0.0882204 NCalls =    134
VariableMetric: Iteration #  13 - FCN = 0.07135776436404 Edm =    0.0344352 NCalls =    140
VariableMetric: Iteration #  14 - FCN = 0.05783583506484 Edm =    0.0105353 NCalls =    146
VariableMetric: Iteration #  15 - FCN = 0.04919391212636 Edm =   0.00667348 NCalls =    151
VariableMetric: Iteration #  16 - FCN =  0.0269443481119 Edm =     0.010992 NCalls =    158
VariableMetric: Iteration #  17 - FCN = 0.01030152902421 Edm =   0.00269256 NCalls =    164
VariableMetric: Iteration #  18 - FCN = 0.006162211941703 Edm =   0.00334822 NCalls =    171
VariableMetric: Iteration #  19 - FCN = 0.0005328385274753 Edm =  0.000458494 NCalls =    178
VariableMetric: Iteration #  20 - FCN = 6.144542191675e-05 Edm =  4.63186e-05 NCalls =    184
VariableMetric: Iteration #  21 - FCN = 1.016694558288e-06 Edm =  1.10045e-06 NCalls =    190
VariableMetric: After Hessian   - FCN = 1.016694558288e-06 Edm =  1.03263e-06 NCalls =    200
VariableMetric: Iteration #  22 - FCN = 1.016694558288e-06 Edm =  1.03263e-06 NCalls =    200
Number of iterations 23
----------> Iteration 0
            FVAL = 84.0170342888 Edm = 157.459415505 Nfcn = 33
            Error matrix change = 1
            Parameters :  p0 = -1 p1 = 0.105478
----------> Iteration 1
            FVAL = 3.41135157006 Edm = 0.0335156335539 Nfcn = 39
            Error matrix change = 0.628315
            Parameters :  p0 = -0.844697 p1 = 0.704323
----------> Iteration 2
            FVAL = 3.38934106846 Edm = 0.00586800256758 Nfcn = 45
            Error matrix change = 0.501734
            Parameters :  p0 = -0.840157 p1 = 0.711488
----------> Iteration 3
            FVAL = 2.69871369005 Edm = 0.159351992616 Nfcn = 56
            Error matrix change = 0.745356
            Parameters :  p0 = -0.583782 p1 = 0.297172
----------> Iteration 4
            FVAL = 2.33768585927 Edm = 0.908400708087 Nfcn = 63
            Error matrix change = 0.901761
            Parameters :  p0 = -0.407474 p1 = 0.10631
----------> Iteration 5
            FVAL = 1.87679606382 Edm = 0.218499938811 Nfcn = 69
            Error matrix change = 0.565937
            Parameters :  p0 = -0.369065 p1 = 0.141166
----------> Iteration 6
            FVAL = 1.54474234647 Edm = 0.106456832893 Nfcn = 78
            Error matrix change = 0.39705
            Parameters :  p0 = -0.196688 p1 = 0.00511831
----------> Iteration 7
            FVAL = 1.27346520016 Edm = 0.440474231006 Nfcn = 88
            Error matrix change = 0.441763
            Parameters :  p0 = -0.0411024 p1 = -0.0418503
----------> Iteration 8
            FVAL = 0.408499547798 Edm = 0.101332777331 Nfcn = 103
            Error matrix change = 0.430687
            Parameters :  p0 = 0.377925 p1 = 0.128157
----------> Iteration 9
            FVAL = 0.396083545863 Edm = 0.0408560634843 Nfcn = 109
            Error matrix change = 0.99133
            Parameters :  p0 = 0.371374 p1 = 0.134897
----------> Iteration 10
            FVAL = 0.28254151239 Edm = 0.0220763576638 Nfcn = 118
            Error matrix change = 0.895583
            Parameters :  p0 = 0.488595 p1 = 0.224231
----------> Iteration 11
            FVAL = 0.235823530235 Edm = 0.074409785973 Nfcn = 125
            Error matrix change = 0.828991
            Parameters :  p0 = 0.577498 p1 = 0.309563
----------> Iteration 12
            FVAL = 0.117397647565 Edm = 0.0882204463892 Nfcn = 134
            Error matrix change = 0.707354
            Parameters :  p0 = 0.674676 p1 = 0.465941
----------> Iteration 13
            FVAL = 0.071357764364 Edm = 0.0344351842796 Nfcn = 140
            Error matrix change = 0.431734
            Parameters :  p0 = 0.732874 p1 = 0.537221
----------> Iteration 14
            FVAL = 0.0578358350648 Edm = 0.0105353011775 Nfcn = 146
            Error matrix change = 0.647355
            Parameters :  p0 = 0.765817 p1 = 0.581003
----------> Iteration 15
            FVAL = 0.0491939121264 Edm = 0.00667347581545 Nfcn = 151
            Error matrix change = 0.399221
            Parameters :  p0 = 0.813441 p1 = 0.649691
----------> Iteration 16
            FVAL = 0.0269443481119 Edm = 0.0109920456542 Nfcn = 158
            Error matrix change = 0.390644
            Parameters :  p0 = 0.837571 p1 = 0.703893
----------> Iteration 17
            FVAL = 0.0103015290242 Edm = 0.00269256437346 Nfcn = 164
            Error matrix change = 0.42405
            Parameters :  p0 = 0.90538 p1 = 0.81604
----------> Iteration 18
            FVAL = 0.0061622119417 Edm = 0.00334821537976 Nfcn = 171
            Error matrix change = 0.404202
            Parameters :  p0 = 0.948334 p1 = 0.893427
----------> Iteration 19
            FVAL = 0.000532838527475 Edm = 0.000458493693636 Nfcn = 178
            Error matrix change = 0.373678
            Parameters :  p0 = 0.977795 p1 = 0.956714
----------> Iteration 20
            FVAL = 6.14454219168e-05 Edm = 4.63186430114e-05 Nfcn = 184
            Error matrix change = 0.22278
            Parameters :  p0 = 0.995725 p1 = 0.990811
----------> Iteration 21
            FVAL = 1.01669455829e-06 Edm = 1.1004464766e-06 Nfcn = 190
            Error matrix change = 0.193359
            Parameters :  p0 = 0.999053 p1 = 0.99814
----------> Iteration 22
            FVAL = 1.01669455829e-06 Edm = 1.03263486009e-06 Nfcn = 200
            Error matrix change = 0
            Parameters :  p0 = 0.999053 p1 = 0.99814
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = 1.01669455828808787e-06
Edm   = 1.03263486008607708e-06
Nfcn  = 200
x	  = 0.999053	 +/-  1.00892
y	  = 0.99814	 +/-  2.01382	(limited)

I checked again inside my code and I did not find anything that can explain why PrintLevel=3 is not working.
Actually my code is not a .C file, but a .cpp file compiled using a makefile. Is it a possible explanation or am I missing something?

Yes, this is very strange. Maybe you are re-directing the output somewhere else ?
Also it is strange you get a failure with status=4, which means that you have reached the call limit, but in reality you had only 55 iterations.
Can you post the code, so I can reproduce the problem ?

Thank you

Lorenzo

I made a very stupid code that reproduces my problem. I still believe I am doing something wrong in Fcn.

Anyway, this is the output I get executing my code inside ROOT

           Minimizer Type :         Minuit2
      Minimizer Algorithm :         Simplex
                 Strategy :               1
                Tolerance :               1
           Max func calls :         1000000
           Max iterations :         1000000
           Func Precision :              -1
         Error definition :               1
              Print Level :               3

****************************************
         Invalid FitResult  (status = 4 )
****************************************
Minimizer is Minuit / Migrad
MinFCN                    =      1461.24
NDf                       =            0
Edm                       =     0.169822
NCalls                    =           35
Par_0                     =      4.99338   +/-   0.000406937  	 (limited)
           Minimizer Type :         Minuit2
      Minimizer Algorithm :          Migrad
                 Strategy :               1
                Tolerance :               1
           Max func calls :         1000000
           Max iterations :         1000000
           Func Precision :              -1
         Error definition :               1
              Print Level :               3

****************************************
         Invalid FitResult  (status = 4 )
****************************************
Minimizer is Minuit / Migrad
MinFCN                    =      1461.24
NDf                       =            0
Edm                       =     0.169822
NCalls                    =           35
Par_0                     =      4.99338   +/-   0.000406937  	 (limited)
           Minimizer Type :         Minuit2
      Minimizer Algorithm :           Minos
                 Strategy :               1
                Tolerance :               1
           Max func calls :         1000000
           Max iterations :         1000000
           Func Precision :              -1
         Error definition :               1
              Print Level :               3

****************************************
         Invalid FitResult  (status = 4 )
****************************************
Minimizer is Minuit / Migrad
MinFCN                    =      1461.24
NDf                       =            0
Edm                       =     0.169822
NCalls                    =           35
Par_0                     =      4.99338   +/-   0.000406937  	 (limited)
Fit converged toward value 4.99338 ± 0.000406937 with probability 0
-1 -1 1

I am also wondering why I always get “Minimizer is Minuit / Migrad”… Thank you for help.
x_scale_fit.cpp (4.01 KB)

Hi,

You are missing to set the minimiser option to the fitter (to the FitConfig object).
You need to add this line, before calling the Fit method:

fitter.Config().SetMinimizerOptions(opt);

After doing this I see the correct output. The fit does not converge for some precision problems, due in the FCN calculation. I can try to understand later the reason for this

Best Regards

Lorenzo

Thank you for your suggestion. I attached the modified code. As you said there is still problem with conversion.

I guess this is a very basic question but… why I obtain a different result each time I run it? If you run it 10 times, you will get the correct value (0.5) at least once. Despite this, also in this case fit status is invalid (3).

I am really wondering how to solve my problem. Changing parameter like tolerance or step size did not clearly improve situations (of course, if we use 0.5 as initial value or a very narrow range, fit converges but in real situation I do not know this value). Do you have some other general suggestions that I can try? Thank you in advance.
x_scale_fit.cpp (5.25 KB)

I am sorry to ask again about this problem, but yet I was not able to find some constraints on the fit in order to obtain convergence. Could you give me some more hints?

Hi,

The problem is your function. Looking at how is defined the function can have discontinuities because a parameter is making a horizontal shifts in the bin. This can cause discontinuities in the function evaluations, which are not good for Minuit.
You should find a way to avoid this.

Best Regards

Lorenzo

Thank you for your reply.

I am not completely sure of having understood your suggestion. I tried to use TGraph in the following way:

  • convert TH1 in TGraph
  • scale x of TGraph for the fitting parameter
  • normalize TGraph to the reference TH1
  • evaluate chi2 using TGraph::Eval
    I expected to overcome discontinuities in this way. I am checking results of each calls. Distributions seem reasonable, but in the end I can not get convergence. Should I put some kind of constraints on derivatives?

I attach my code.
x_scale_fit.cpp (6.29 KB)

Hi,

It looks better with the Graph than before, but probably there are still some precision or discontinuities in the FCN function. You can try to plot the FCN as function of the parameter around the sound best minimum value to see how it behaves.

Lorenzo

Hi,

I checked function vs call and function vs parameter. I see some kind of quadratic relation, despite sometimes the function value is very high, but finally the minimization get stacked far away from correct value (0.5).
x_scale_fit.cpp (6.88 KB)

Hi,
Can you attach a plot of the CHi2 function vs the parameter values, in particular close to the minimum ?
Or better adapt the macro to make this plot. At the moment your code is not working for me

Cheers

Lorenzo

I am sorry, I swapped x-y in the plot so even my conclusion was wrong. I don’t know if this was the problem (of course it is not a beautiful code…), anyway I updated it.
You can find the image your requested. The zoom is in [0,2] region (right value should be 0.5). The algorithm finds a very high chi2 just below 1. Maybe this is the reason why it is not moving to the right direction (the left one).
x_scale_fit.cpp (7.18 KB)
img.eps (54.2 KB)

Hi,
I see big jumps in chi2 vs par0, however this is not exactly the plot I meant. What I meant is chi vs par0 for grid values of par0 around the minimum, to see how it behaves, in particular using a very fine grid, Th plot you have is for the par0 values occurred during the minimisation.
If the function is not smooth for small changes of par0 then Minuit will not be able to work

Lorenzo

Ok, finally I got what you were saying! This is the picture. As you said, it seems that the minimum around 0.5 is very narrow, so maybe that, if the fit does not try a value very near to it, it will exclude that region. Am I right?
chi2vspar0_zoom.eps (17.2 KB)
chi2vspar0.eps (14.4 KB)
chi2vspar0.cpp (3.07 KB)