RooFit Hessian matrix error fitting a flat PDF with RooFit 's maximum likelihood method


ROOT Version: 6.30/02
Platform: Ubuntu 20.04.6 LTS
Compiler: gcc 12.3.0


Hello; I am trying to fit a flat pdf using RooFit, f(x) = b. I would like to recover the value b with an uncertainty, so instead of using RooUniform I am using a RooGenericPdf, that I manually normalize. I have tried both an extended ML, and a non extended ML, and I’m using the fitTo function to make sure I’m fitting the log likelihood rather than a chi2. However, when I perform this fit I get the error message:

Minuit2Minimizer: Minimize with max-calls 1000 convergence for edm < 1 strategy 2
Warning in <Minuit2>: MnHesse 2nd derivative zero for parameter b ; MnHesse fails and will return diagonal matrix
Warning in <Minuit2>: MnHesse 2nd derivative zero for parameter b ; MnHesse fails and will return diagonal matrix
Warning in <Minuit2>: VariableMetricBuilder Invalid Hessian - exit the minimization
Warning in <Minuit2>: Minuit2Minimizer::Minimize Minimization did NOT converge, Hesse is not valid
Minuit2Minimizer : Invalid Minimum - status = 2
FVAL  = 1072.61
Edm   = 5.92343e-08
Nfcn  = 49
Warning in <Minuit2>: MnHesse 2nd derivative zero for parameter b ; MnHesse fails and will return diagonal matrix
Warning in <Minuit2>: Minuit2Minimizer::Hesse Hesse failed - matrix is full but not positive defined
Warning in <Minuit2>: Minuit2Minimizer::Hesse 3
Warning in <ROOT::Math::Fitter::CalculateHessErrors>: Error when calculating Hessian

I don’t understand why the error message says the second derivative of b is 0, as manually calculating the hessian error I would expect b/\sqrt(n_{bins}) because it should be fitting the log likelihood, not just the likelihood. When I perform this fit without RooFit, with just a TF1 function, the fit works and returns Hessian and Minos errors (though the returned error is smaller than what I would expect from b/\sqrt(n_{bins}), which I would also be interested in help understanding, but it does seem to minimize the function at least). Is there a reason that RooFit isn’t doing this hessian calculation?

The code I’m using follows below:

 // initialize fit parameter seeds
  double maxHist = hist->GetMaximum();
  double minHist = hist->GetMinimum();
  double GuessBinCont = hist->GetBinContent(0);

  RooWorkspace *w = new RooWorkspace("w", kTRUE);
  RooRealVar time("time", "time (days)", 0, 1794);

  RooDataHist* data = new RooDataHist("data", "data", RooArgSet(time), Import(*hist));
  RooRealVar b("b", "b", GuessBinCont, minHist, maxHist);
  RooRealVar N("N", "N", 54750, 100, 100000);
  RooGenericPdf sigpdf("sigpdf", "sigpdf", "b", RooArgList(b));

  RooAbsReal *pdfint = sigpdf.createIntegral(time);
  double norm = pdfint->getVal();
  RooFormulaVar normform("normform", "normform", "(@0)/@1", RooArgList(sigpdf, *pdfint));
  RooGenericPdf normpdf("normpdf", "normpdf", "normform", RooArgList(normform));
  RooExtendPdf extendedPdf("extendedPdf", "extendedPdf", normpdf, N);

  w->import(b);
  w->import(time);
  w->import(N);
  w->import(extendedPdf);

  RooFitResult *result = extendedPdf.fitTo(*data, Strategy(2), Extended(true), Verbose(false), PrintLevel(0), Hesse(true), Save(true));

The data in “hist” is filled with randomly generated numbers from a poisson distribution that I set the mean = 30, just as a test.

Thank you for any help!

Respectfully,
Becky

Hi Becky,

Thanks for the post and welcome to the ROOT community!
I am adding in the loop @jonas and @moneta , the roofit experts. Please mind that during the holidays period, answers may take a while.

Cheers,
D

Hello,

I wanted to make an update because I realize I had the wrong error value. Instead of the expected Hesse error being b/\sqrt{n_{bins}}, it should be \sqrt{b/n_{bins}}. With this correct value, a normal TF1 root fit gives what I would expect if I fit with the likelihood “L” option.

I still get the MnHesse 2nd derivative zero for parameter b warning, if I fit normpdf to the data in the code snippit above. If I however fit sigpdf, the un-normalized one, I do get a fit result, and a converged minimizer, but the value doesn’t make sense. The output is as follows:

[#1] INFO:ObjectHandling -- RooWorkspace::import(w) importing RooRealVar::b
[#1] INFO:ObjectHandling -- RooWorkspace::import(w) importing RooRealVar::time
[#1] INFO:ObjectHandling -- RooWorkspace::import(w) importing RooGenericPdf::sigpdf
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
Minuit2Minimizer: Minimize with max-calls 500 convergence for edm < 1 strategy 2
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = -214390.65627552598
Edm   = 3.33116956277800433e-08
Nfcn  = 26
b         = 51   +/-  0.000467657       (limited)
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization
[#0] ERROR:Plotting -- RooGenericPdf::sigpdf:plotOn: WARNING: variable is not an explicit dependent: time
[#0] ERROR:Plotting -- RooGenericPdf::sigpdf:plotOn: WARNING: variable is not an explicit dependent: time
[#0] ERROR:Plotting -- RooGenericPdf::sigpdf:createPlotProjection: "time" is not a dependent and will be ignored.
[#0] WARNING:InputArguments -- RooRealBinding: The function scaled_func does not depend on the parameter time. Note that passing copies of the parameters is not supported.

I would still appreciate any help with this. It may be some difference between how root handle’s normalizing (which I don’t think a simple tf1 root fit considers), and how the RooGenericPdf normalizes, that I don’t understand, because I would think the root TF1 method should give the same results as the RooFit method. Again, thank you for any help!

Hi @bkowal!

Thanks for following up on your question. Unfortunately, I still don’t understand how you expect this to work. Looking at your RooFit code, the dependency on the parameter b cancels out in your normform. So it’s expected that the fit and Hesse don’t work, because all derivatives with respect to b are zero.

\text{normform}(t) = \frac{b}{\int b dt} = \frac{1}{\int dt} = 1/1794.

There is indeed a difference for normalizations with RooFit with respect to binned fits with TF1. RooFit always auto-normalized the pdf, and the normalization integral doesn’t matter. Do parameters that affect only the scale have no effect. If you want to have a parameter for the overall yield, you have to do an extended fit, like with the RooExtendPdf using the overall yield parameter N.

The TF1 fit instead directly uses the normalization integral of the function as the prediction for the overall yield, which would be \int b dt in your case.

So you should maybe go ahead with the RooUniform and do an extended fit, getting a fit result and uncertainty for the overall yield N. Then, you can manually propagate to the value and uncertainty of b, since they are simply related by N=b\cdot\int dt, where the integral is a constant.

Or, to mimic what the TF1 fit does, maybe use the normalization integral as the yield prediction instead of the extra parameter N:

  RooDataHist* data = new RooDataHist("data", "data", RooArgSet(time), Import(*hist));
  RooRealVar b("b", "b", GuessBinCont, minHist, maxHist);
  RooGenericPdf sigpdf("sigpdf", "sigpdf", "0.0 * time + b", RooArgList(time, b));
  RooAbsReal *pdfint = sigpdf.createIntegral(time);
  RooExtendPdf extendedPdf("extendedPdf", "extendedPdf", normpdf, *pdfint);

There, I got rid of the double-RooGenericPdf because RooFit will normalize correctly anyway (as long as the pdf depends on the observable, which is why I added this dummy dependency on time).

Let me know if these ideas help!

Cheers,
Jonas

Hi Jonas,

Thank you for the response! I understand what you mean about normform(t), though I thought that because RooFit uses numerical techniques to get the integral (at least this is what I thought RooAbsPdf’s createIntegral did), I didn’t realize it would cancel out b. So just to understand better, this createIntegral uses the pdf’s function explicitly, rather than something like trapezoidal sums?

In regards to the fit, I tried both of your suggestions for using RooFit to get a flat function. If I try the modification of the RooGeneric pdf, where I have the function “0.0*time + b” and use pdfint for the RooExtendPdf, this returns very incorrect values ( I expect b to be at 30) with a very large uncertainty, as shown below:

[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
Minuit2Minimizer: Minimize with max-calls 500 convergence for edm < 1 strategy 2
[#1] INFO:NumericIntegration -- RooRealIntegral::init(sigpdf_Int[time]) using numeric integrator RooRombergIntegrator to calculate Int(time)
Warning in <Minuit2>: VariableMetricBuilder No improvement in line search
Minuit2Minimizer : Valid minimum - status = 0
FVAL  = 409695.313443333202
Edm   = 3.63797880709171255e-12
Nfcn  = 28
b         = 10.41        +/-  23.6608   (limited)
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization
[#1] INFO:NumericIntegration -- RooRealIntegral::init(sigpdf_Int[time]) using numeric integrator RooRombergIntegrator to calculate Int(time)

When I use an EML with RooUniform and a RooAbsReal of N events, after propagating N to b and propagating the N uncertainty of \sqrt{n_{obs}} to \delta b, this returns exactly what the root fit returns.

What I would like to understand is why the RooGenericPdf has such an incorrect value and such a high uncertainty on it. I took a look at the negative log likelihood of fit parameter b (from extendedPdf.createNLL(*data) as a function of b), and it looks flat, so I can understand that the uncertainty would be high, but then how did the fit converge at all?

The reason I’ve been trying to fit a flat line is because I am interested in expanding the pdf from just a flat line to a sinusoidal function, with some offset (so b+a*cos(\omega t + \phi), for example). When I try to fit this more complicated function about the same data, I’d hope for a to be zero with some uncertainty. But because I’ve gotten such large uncertainty values using RooGenericPdfs with this flat (and sinusoidal) fit, it’s hard to make a convincing statement about the sinousoidal amplitude.

Is there a reason that using a RooGenericPdf, even if it has time dependence (be it this dummy dependency for the flat fit, or a physical sinusoidal dependence) would give such high uncertainty values?

Again, thank you for your help!

Respectfully,
Becky