Minimizer issue: inconsistent results across ROOT versions

Dear experts,

I have a simple code that fits two mass peaks simultaneously. The setup is pretty simple, RooGaussian + RooChebychev, where the mean and sigma of the gaussian are shared between the two mass regions (RooCategory). I have experienced issues in reproducing the fit results with different ROOT versions.

  • The fit result looks good in ROOT 6.30/02 (I also tested it in 6.26/11)
  • The fit result is totally off in ROOT 6.34/02 (I also tested it in 6.32/10 with the same outcome)

Since ROOT 6.30/02 and 6.34/02 are the versions provided in the LCG environments 105 and 107 respectively, I believe this issue is related to the one recently reported by @nicolo.trevisani.

These plots show the result in ROOT 6.30/02 and older versions. The two plots correspond to the two mass regions in the simultaneous fit:

While here is what I get with ROOT 6.34/02:

RooFit log in ROOT 6.30/02:

[#1] INFO:Eval -- RooRealVar::setRange(dimu_OS1) new range named 'fit_nll_signal_mumu_data' created with bounds [0.98,1.08]
[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(nll_signal_mumu_data) constructing test statistic for sub-range named fit_range_signal
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
Minuit2Minimizer: Minimize with max-calls 1000 convergence for edm < 1 strategy 1
Info in <Minuit2>: MnSeedGenerator Computing seed using NumericalGradient calculator
Info in <Minuit2>: MnSeedGenerator Initial state: FCN =      -6540.139974 Edm =      -336.8412911 NCalls =      9
Info in <Minuit2>: NegativeG2LineSearch Doing a NegativeG2LineSearch since one of the G2 component is negative
Info in <Minuit2>: MnSeedGenerator Negative G2 found - new state: 
  Minimum value : -6759.661969
  Edm           : 1.708732621
  Internal parameters:	[                0    -0.3905360998]	
  Internal gradient  :	[     -9.246451549     -18.78991127]	
  Internal covariance matrix:
[[    0.078044331              0]
 [              0  0.00045993433]]]
Info in <Minuit2>: MnSeedGenerator Initial state  
  Minimum value : -6759.661969
  Edm           : 1.708732621
  Internal parameters:	[                0    -0.3905360998]	
  Internal gradient  :	[     -9.246451549     -18.78991127]	
  Internal covariance matrix:
[[    0.078044331              0]
 [              0  0.00045993433]]]
Info in <Minuit2>: VariableMetricBuilder Start iterating until Edm is < 0.001 with call limit = 1000
Info in <Minuit2>: VariableMetricBuilder    0 - FCN =      -6759.661969 Edm =       1.708732621 NCalls =     26
Info in <Minuit2>: VariableMetricBuilder    1 - FCN =      -6761.250973 Edm =     0.07328111069 NCalls =     32
Info in <Minuit2>: VariableMetricBuilder    2 - FCN =      -6761.337042 Edm =   1.380802967e-05 NCalls =     38
Info in <Minuit2>: VariableMetricBuilder After Hessian
Info in <Minuit2>: VariableMetricBuilder    3 - FCN =      -6761.337042 Edm =   1.619328576e-05 NCalls =     48
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = -6761.33704188590127
Edm   = 1.61932857624699604e-05
Nfcn  = 48
M_mumu	  = 1.01973	 +/-  0.000397116	(limited)
width	  = 0.0188872	 +/-  0.00032099	(limited)
Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 1000
Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization
[#1] INFO:Eval -- RooRealVar::setRange(dimu_OS1) new range named 'fit_nll_simul_model_datatofit' created with bounds [0.9,1.16]
RooAbsTestStatistic::initSimMode: creating slave calculator #0 for state looseBDT (7828 dataset entries)
[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(looseBDT) constructing test statistic for sub-range named fit_range
RooAbsTestStatistic::initSimMode: creating slave calculator #1 for state tightBDT (3530 dataset entries)
[#1] INFO:Fitting -- RooAbsOptTestStatistic::ctor(tightBDT) constructing test statistic for sub-range named fit_range
[#1] INFO:Fitting -- RooAbsTestStatistic::initSimMode: created 2 slave calculators.
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
[#1] INFO:Minimization --  The following expressions will be evaluated in cache-and-track mode: (signal_mumu,bmodel_ctrl)
[#1] INFO:Minimization --  The following expressions will be evaluated in cache-and-track mode: (signal_mumu,bmodel)
Minuit2Minimizer: Minimize with max-calls 4000 convergence for edm < 1 strategy 1
Info in <Minuit2>: MnSeedGenerator Computing seed using NumericalGradient calculator
Info in <Minuit2>: MnSeedGenerator Initial state: FCN =      -95360.13639 Edm =      -1154.076539 NCalls =     33
Info in <Minuit2>: NegativeG2LineSearch Doing a NegativeG2LineSearch since one of the G2 component is negative
Info in <Minuit2>: MnSeedGenerator Negative G2 found - new state: 
  Minimum value : -97081.5748
  Edm           : 758.9011992
  Internal parameters:	[      0.375208442                0     0.6435011088     0.6435011088    -0.6376432924                0                0    -0.3928146854]	
  Internal gradient  :	[      25.31044218      417.4800536      9.957564737      320.6898948     -3.140052728        162.39212       588.010494      794.3649351]	
  Internal covariance matrix:
[[     0.18647605              0              0              0              0              0              0              0]
 [              0   0.0019809103              0              0              0              0              0              0]
 [              0              0   0.0014842965              0              0              0              0              0]
 [              0              0              0   0.0090653991              0              0              0              0]
 [              0              0              0              0  0.00066566041              0              0              0]
 [              0              0              0              0              0   0.0041729091              0              0]
 [              0              0              0              0              0              0  0.00095230311              0]
 [              0              0              0              0              0              0              0   0.0019003106]]]
Info in <Minuit2>: MnSeedGenerator Initial state  
  Minimum value : -97081.5748
  Edm           : 758.9011992
  Internal parameters:	[      0.375208442                0     0.6435011088     0.6435011088    -0.6376432924                0                0    -0.3928146854]	
  Internal gradient  :	[      25.31044218      417.4800536      9.957564737      320.6898948     -3.140052728        162.39212       588.010494      794.3649351]	
  Internal covariance matrix:
[[     0.18647605              0              0              0              0              0              0              0]
 [              0   0.0019809103              0              0              0              0              0              0]
 [              0              0   0.0014842965              0              0              0              0              0]
 [              0              0              0   0.0090653991              0              0              0              0]
 [              0              0              0              0  0.00066566041              0              0              0]
 [              0              0              0              0              0   0.0041729091              0              0]
 [              0              0              0              0              0              0  0.00095230311              0]
 [              0              0              0              0              0              0              0   0.0019003106]]]
Info in <Minuit2>: VariableMetricBuilder Start iterating until Edm is < 0.001 with call limit = 4000
Info in <Minuit2>: VariableMetricBuilder    0 - FCN =       -97081.5748 Edm =       758.9011992 NCalls =     62
Info in <Minuit2>: VariableMetricBuilder    1 - FCN =      -97425.06857 Edm =       141.2002291 NCalls =     86
Info in <Minuit2>: VariableMetricBuilder    2 - FCN =      -97490.89187 Edm =       64.54300277 NCalls =    104
Info in <Minuit2>: VariableMetricBuilder    3 - FCN =      -97518.81138 Edm =       11.94799931 NCalls =    122
Info in <Minuit2>: VariableMetricBuilder    4 - FCN =      -97523.53194 Edm =       3.395830549 NCalls =    140
Info in <Minuit2>: VariableMetricBuilder    5 - FCN =       -97525.0164 Edm =      0.4153871578 NCalls =    158
Info in <Minuit2>: VariableMetricBuilder    6 - FCN =       -97525.4484 Edm =     0.02006770115 NCalls =    176
Info in <Minuit2>: VariableMetricBuilder    7 - FCN =       -97525.4665 Edm =   0.0002343436795 NCalls =    194
Info in <Minuit2>: VariableMetricBuilder After Hessian
Info in <Minuit2>: VariableMetricBuilder    8 - FCN =       -97525.4665 Edm =   0.0001879779896 NCalls =    261
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = -97525.4665035848157
Edm   = 0.000187977989554814859
Nfcn  = 261
M_mumu	  = 1.01878	 +/-  0.000282703	(limited)
Nb	  = 1570.53	 +/-  46.7777	(limited)
Nb_ctrl	  = 6548.31	 +/-  90.2702	(limited)
Ns	  = 1958.77	 +/-  50.7567	(limited)
Ns_ctrl	  = 1278.53	 +/-  53.8043	(limited)
a0	  = -0.362474	 +/-  0.0423579	(limited)
b0	  = -0.286239	 +/-  0.0210441	(limited)
width	  = 0.0117274	 +/-  0.000270008	(limited)
Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 4000
Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate
[#1] INFO:Fitting -- RooAbsPdf::fitTo(simul_model) Calculating sum-of-weights-squared correction matrix for covariance matrix
Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 4000
Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization

  RooFitResult: minimized FCN value: -97525.5, estimated distance to minimum: 0.000187445
                covariance matrix quality: Full, accurate covariance matrix
                Status : MINIMIZE=0 HESSE=0 HESSE=0 

    Floating Parameter  InitialValue    FinalValue +/-  Error     GblCorr.
  --------------------  ------------  --------------------------  --------
                M_mumu    1.0197e+00    1.0188e+00 +/-  2.84e-04  <none>
                    Nb    1.7650e+03    1.5705e+03 +/-  4.68e+01  <none>
               Nb_ctrl    6.2624e+03    6.5483e+03 +/-  9.04e+01  <none>
                    Ns    2.8240e+03    1.9588e+03 +/-  5.08e+01  <none>
               Ns_ctrl    6.2624e+03    1.2785e+03 +/-  5.38e+01  <none>
                    a0    0.0000e+00   -3.6247e-01 +/-  4.24e-02  <none>
                    b0    0.0000e+00   -2.8624e-01 +/-  2.10e-02  <none>
                 width    1.8887e-02    1.1727e-02 +/-  2.70e-04  <none>

RooFit log in ROOT 6.34/02:

[#1] INFO:Eval -- RooRealVar::setRange(dimu_OS1) new range named 'fit_nll_signal_mumu_data' created with bounds [0.98,1.08]
[#1] INFO:Fitting -- RooAbsPdf::fitTo(signal_mumu_over_signal_mumu_Int[dimu_OS1|fit_range_signal]) fixing normalization set for coefficient determination to observables in data
[#1] INFO:Fitting -- using CPU computation library compiled with -mavx2
[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_signal_mumu_over_signal_mumu_Int[dimu_OS1|fit_range_signal]_data) Summation contains a RooNLLVar, using its error level
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
Minuit2Minimizer: Minimize with max-calls 1000 convergence for edm < 1 strategy 1
Info in <Minuit2>: MnSeedGenerator Computing seed using NumericalGradient calculator
Info in <Minuit2>: MnSeedGenerator Initial state: FCN =      -6540.139974 Edm =       138022.4473 NCalls =      9
Info in <Minuit2>: NegativeG2LineSearch Doing a NegativeG2LineSearch since one of the G2 component is negative
Info in <Minuit2>: MnSeedGenerator Negative G2 found - new state: 
  Minimum value : -6759.661969
  Edm           : 1.708732621
  Internal parameters:	[                0    -0.3905360998]	
  Internal gradient  :	[     -9.246451549     -18.78991127]	
  Internal covariance matrix:
[[    0.078044331              0]
 [              0  0.00045993433]]]
Info in <Minuit2>: MnSeedGenerator Initial state  
  Minimum value : -6759.661969
  Edm           : 1.708732621
  Internal parameters:	[                0    -0.3905360998]	
  Internal gradient  :	[     -9.246451549     -18.78991127]	
  Internal covariance matrix:
[[    0.078044331              0]
 [              0  0.00045993433]]]
Info in <Minuit2>: VariableMetricBuilder Start iterating until Edm is < 0.001 with call limit = 1000
Info in <Minuit2>: VariableMetricBuilder    0 - FCN =      -6759.661969 Edm =       1.708732621 NCalls =     26
Info in <Minuit2>: VariableMetricBuilder    1 - FCN =      -6761.250973 Edm =     0.07328111069 NCalls =     32
Info in <Minuit2>: VariableMetricBuilder    2 - FCN =      -6761.337042 Edm =   1.380802967e-05 NCalls =     38
Info in <Minuit2>: VariableMetricBuilder After Hessian
Info in <Minuit2>: VariableMetricBuilder    3 - FCN =      -6761.337042 Edm =   1.619328585e-05 NCalls =     48
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = -6761.33704188590127
Edm   = 1.61932858511379351e-05
Nfcn  = 48
M_mumu	  = 1.01973	 +/-  0.000397116	(limited)
width	  = 0.0188872	 +/-  0.00032099	(limited)
Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 1000
Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization
[#1] INFO:Eval -- RooRealVar::setRange(dimu_OS1) new range named 'fit_nll_simul_model_datatofit' created with bounds [0.9,1.16]
[#1] INFO:Fitting -- RooAbsPdf::fitTo(simul_model) fixing normalization set for coefficient determination to observables in data
[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_simul_model_datatofit) Summation contains a RooNLLVar, using its error level
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
Minuit2Minimizer: Minimize with max-calls 4000 convergence for edm < 1 strategy 1
Info in <Minuit2>: MnSeedGenerator Computing seed using NumericalGradient calculator
[#0] ERROR:InputArguments -- RooArgSet::checkForDup: ERROR argument with name _tightBDT_signal_mumu_over_signal_mumu_Int[dimu_OS1]_Int[] is already in this set
[#0] ERROR:InputArguments -- RooArgSet::checkForDup: ERROR argument with name _tightBDT_bmodel_over_bmodel_Int[dimu_OS1]_Int[] is already in this set
[#0] ERROR:InputArguments -- RooArgSet::checkForDup: ERROR argument with name _looseBDT_signal_mumu_over_signal_mumu_Int[dimu_OS1]_Int[] is already in this set
[#0] ERROR:InputArguments -- RooArgSet::checkForDup: ERROR argument with name _looseBDT_bmodel_ctrl_over_bmodel_ctrl_Int[dimu_OS1]_Int[] is already in this set
Info in <Minuit2>: MnSeedGenerator Initial state: FCN =      -66667.33607 Edm =       4947424.615 NCalls =     33
Info in <Minuit2>: NegativeG2LineSearch Doing a NegativeG2LineSearch since one of the G2 component is negative
Info in <Minuit2>: MnSeedGenerator Negative G2 found - new state: 
  Minimum value : -70794.20641
  Edm           : 2382.596038
  Internal parameters:	[     -1.553566819                0     0.6435011088     -4.679872678     -1.504705178                0                0      1.559260277]	
  Internal gradient  :	[     0.3836497869     -1697.017873     -3099.523339      15.23508383      9.686819045      135.1214134      726.4935634     -10.20517518]	
  Internal covariance matrix:
[[    0.089816107              0              0              0              0              0              0              0]
 [              0   0.0015378866              0              0              0              0              0              0]
 [              0              0  0.00046715083              0              0              0              0              0]
 [              0              0              0   0.0042688608              0              0              0              0]
 [              0              0              0              0    0.014028471              0              0              0]
 [              0              0              0              0              0   0.0068249823              0              0]
 [              0              0              0              0              0              0  0.00092151164              0]
 [              0              0              0              0              0              0              0    0.002260788]]]
Info in <Minuit2>: MnSeedGenerator Initial state  
  Minimum value : -70794.20641
  Edm           : 2382.596038
  Internal parameters:	[     -1.553566819                0     0.6435011088     -4.679872678     -1.504705178                0                0      1.559260277]	
  Internal gradient  :	[     0.3836497869     -1697.017873     -3099.523339      15.23508383      9.686819045      135.1214134      726.4935634     -10.20517518]	
  Internal covariance matrix:
[[    0.089816107              0              0              0              0              0              0              0]
 [              0   0.0015378866              0              0              0              0              0              0]
 [              0              0  0.00046715083              0              0              0              0              0]
 [              0              0              0   0.0042688608              0              0              0              0]
 [              0              0              0              0    0.014028471              0              0              0]
 [              0              0              0              0              0   0.0068249823              0              0]
 [              0              0              0              0              0              0  0.00092151164              0]
 [              0              0              0              0              0              0              0    0.002260788]]]
Info in <Minuit2>: VariableMetricBuilder Start iterating until Edm is < 0.001 with call limit = 4000
Info in <Minuit2>: VariableMetricBuilder    0 - FCN =      -70794.20641 Edm =       2382.596038 NCalls =    179
Info in <Minuit2>: VariableMetricBuilder    1 - FCN =      -73527.13564 Edm =       8.125858153 NCalls =    202
Info in <Minuit2>: VariableMetricBuilder    2 - FCN =      -73536.24614 Edm =      0.3369509244 NCalls =    220
Info in <Minuit2>: VariableMetricBuilder    3 - FCN =      -73536.50858 Edm =     0.04668680801 NCalls =    238
Info in <Minuit2>: VariableMetricBuilder    4 - FCN =      -73536.54625 Edm =    0.004214518765 NCalls =    256
Info in <Minuit2>: VariableMetricBuilder    5 - FCN =      -73536.54991 Edm =   0.0001099576611 NCalls =    273
Info in <Minuit2>: VariableMetricBuilder After Hessian
Info in <Minuit2>: VariableMetricBuilder    6 - FCN =      -73536.54991 Edm =   0.0001633640581 NCalls =    334
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = -73536.549905802487
Edm   = 0.00016336405813592651
Nfcn  = 334
M_mumu	  = 1.017	 +/-  7.87593e-05	(limited)
Nb	  = 3530	 +/-  0.976784	(limited)
Nb_ctrl	  = 7828	 +/-  0.675656	(limited)
Ns	  = 3530	 +/-  4.7914	(limited)
Ns_ctrl	  = 2.36629e-05	 +/-  6.92393	(limited)
a0	  = -0.485823	 +/-  0.0439686	(limited)
b0	  = -0.330843	 +/-  0.0204784	(limited)
width	  = 0.05	 +/-  2.22373e-05	(limited)
Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 4000
Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate
[#1] INFO:Fitting -- RooAbsPdf::fitTo(simul_model) Calculating sum-of-weights-squared correction matrix for covariance matrix
Info in <Minuit2>: Minuit2Minimizer::Hesse Using max-calls 4000
Info in <Minuit2>: Minuit2Minimizer::Hesse Hesse is valid - matrix is accurate
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization

  RooFitResult: minimized FCN value: -73536.5, estimated distance to minimum: 0.00016331
                covariance matrix quality: Full, accurate covariance matrix
                Status : MINIMIZE=0 HESSE=0 HESSE=0 

    Floating Parameter  InitialValue    FinalValue +/-  Error     GblCorr.
  --------------------  ------------  --------------------------  --------
                M_mumu    1.0197e+00    1.0170e+00 +/-  6.04e-08  <none>
                    Nb    1.7650e+03    3.5300e+03 +/-  1.13e-02  <none>
               Nb_ctrl    6.2624e+03    7.8280e+03 +/-  8.30e-03  <none>
                    Ns    2.8240e+03    3.5300e+03 +/-  1.26e-01  <none>
               Ns_ctrl    6.2624e+03    2.3663e-05 +/-  2.56e-02  <none>
                    a0    0.0000e+00   -4.8582e-01 +/-  4.40e-02  <none>
                    b0    0.0000e+00   -3.3084e-01 +/-  2.05e-02  <none>
                 width    1.8887e-02    5.0000e-02 +/-  6.45e-08  <none>

Can you please let me know if any change in the minimizer was done in recent ROOT/RooFit versions? I would be happy to provide a reproducer if needed.

Thank you and best,
Federica

maybe @jonas knows

Are you sure your RooChebyshev is correctly defined so that it does not go into negative probabilities? See [RF] Handling of the negative values in RooChebychev causes fit divergence · Issue #12452 · root-project/root · GitHub

could you also try with ROOT 6.38.02 ?

Hi! Did you try with ROOT master? You can try is with the LCG nightlies:

If it still doesn’t work, could you please open a GitHub issue about this, including a reproducer?

Dear all,

thank you for the follow up.

  • The Chebychev is first order only, with the coefficient defined in [-1, 1], so it should not go negative
  • The output above was obtained on `lxplus`. For ROOT 6.30/02 I sourced the LCG_105 environment, while for ROOT 6.34/02 I’ve used LCG_107.

Tried now with LCG_109 (i.e. ROOT 6.38/00), the fit converges to the same final parameters as in ROOT 6.30/02, i.e. the correct ones.

Great! Indeed 6.32 contained quite big performance optimization changes for RooFit, and some problems with it were fixed in the subsequent releases.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.