Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Math][Minuit2] Add new Strategy to Minuit2 for more precise hesse algorithm and return without forcing positive definite #13109

Merged
merged 3 commits into from
Oct 23, 2023

Conversation

will-cern
Copy link
Contributor

This proposed new Strategy in minuit2 is the same migrad behaviour as Strategy=2 but with the following changes to the Hesse calculation:

  • The step and g2 tolerances have been zeroed so that the 7 cycles are forced in the diagonal-term calculation. This was found to be necessary in cases where asimov datasets were used for the minimization and there were very few iterations for the approximate covariance to be determined from.
  • Central finite difference is used for mixed partial derivatives. This requires 3 extra function evaluations per derivative, but is necessary in the case of minima where there is high curvature (in the case of high stats) and the forward finite difference (default) behaviour leads incorrectly to a non-positive-definite covariance matrix
  • Return the uncorrected covariance matrix, even if it is not positive definite. This useful for checking just how far from positive-definiteness the matrix is by being able to examine the eigenvalues.

Additionally, a lower bound on the precision allowed for the spread of eigenvalues of the "hessian" correlation matrix (computing a correlation matrix with the hessian as if it was a covariance matrix) was reduced from 1e-6 to 1e-12 (see MnHesse.cxx) ... it is not clear why 1e-6 was the lower bound previously, but current machine precision can beat that (I get locally 1e-8). I left a comment about whether this lower bound should be made configurable or not...

This new strategy was tested with a model with high statistics (almost 50 million events) where the migrad minimization was successful but the hessian was being forced positive definite. With this new Strategy 3 the hessian is accurate and positive definite in all cases tested.

@will-cern will-cern requested a review from lmoneta as a code owner June 27, 2023 11:47
@phsft-bot
Copy link
Collaborator

Can one of the admins verify this patch?

@lmoneta lmoneta self-assigned this Jun 27, 2023
@lmoneta
Copy link
Member

lmoneta commented Jul 12, 2023

@phsft-bot build

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu2204/nortcxxmod, ROOT-ubuntu2004/python3, mac11/noimt, mac12arm/cxx20, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-ubuntu2204/nortcxxmod.
Running on root-ubuntu-2204-2.cern.ch:/home/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2023-07-12T16:32:46.317Z] CMake Error at /home/sftnight/build/workspace/root-pullrequests-build/rootspi/jenkins/root-build.cmake:1142 (message):

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-ubuntu2004/python3.
Running on root-ubuntu-2004-1.cern.ch:/home/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2023-07-12T16:32:41.124Z] stderr: error: Failed to merge in the changes.
  • [2023-07-12T16:32:46.737Z] CMake Error at /home/sftnight/build/workspace/root-pullrequests-build/rootspi/jenkins/root-build.cmake:1142 (message):

@phsft-bot
Copy link
Collaborator

Build failed on mac11/noimt.
Running on macphsft23.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2023-07-12T16:32:48.040Z] CMake Error at /Users/sftnight/build/workspace/root-pullrequests-build/rootspi/jenkins/root-build.cmake:1142 (message):

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-debian10-i386/soversion.
Running on pcepsft11.dyndns.cern.ch:/home/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2023-07-12T16:33:44.364Z] stderr: error: Failed to merge in the changes.
  • [2023-07-12T16:33:56.007Z] CMake Error at /home/sftnight/build/workspace/root-pullrequests-build/rootspi/jenkins/root-build.cmake:1142 (message):

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-performance-centos8-multicore/cxx17.
Running on olbdw-01.cern.ch:/data/sftnight/workspace/root-pullrequests-build
See console output.

Errors:

  • [2023-07-12T16:38:10.548Z] CMake Error at /data/sftnight/workspace/root-pullrequests-build/rootspi/jenkins/root-build.cmake:1142 (message):

@@ -43,7 +43,7 @@ MinimumError MnPosDef::operator()(const MinimumError &e, const MnMachinePrecisio
}
// std::cout<<"MnPosDef init matrix= "<<err<<std::endl;

double epspdf = std::max(1.e-6, prec.Eps2());
double epspdf = std::max(1.e-12, prec.Eps2()); // should this lower bound be configurable?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this should be a configurable parameter. It is important to decide later in the code (line 85, when looking at the eigenvalues, if the matrix need to be made positive defined by adding some extra values to the diagonal.
It is clear that we higher statistics there will be smaller and smaller eigenvalue of the covariance matrices and the spread of the eigenvalues will increase.
Note that the Fortran implementation of Minuit (and TMInuit) uses 1.E-6 as value for this parameter.

Copy link
Member

@lmoneta lmoneta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Will for this nice improvement.
This PR provides actually two new improvements:

  • strategy=3 to have an improved Hessian using a 5 evaluations for the second derivatives of the off-diagonal elements.
  • increase tolerance value (epspdf to decide when the covariance matrix needs to be corrected and made pos defined.

For strategy 3 this PR is not doing two things that are done in strategy 2:

  • compute full Hessian in MnSeedGenerator.cxx (see line 214). I think this is good since it is often not very useful
  • compute Hessian at the end of the minimization iterations to re-calculate the elm (line 136 in VariableMetricBuilder.cxx). I think we can probably leave it as it is, the user can always force the Hessian computation.

Another comment: should we maybe also consider extra function evaluations also for computing the diagonal elements of the covariance ? At the moment we use only 2 extra points.

@phsft-bot
Copy link
Collaborator

Build failed on mac12arm/cxx20.
Running on macphsft26.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2023-07-12T18:37:59.449Z] CMake Error at /Users/sftnight/build/workspace/root-pullrequests-build/rootspi/jenkins/root-build.cmake:1142 (message):

@github-actions
Copy link

github-actions bot commented Jul 12, 2023

Test Results

       10 files         10 suites   1d 15h 47m 48s ⏱️
  2 446 tests   2 444 ✔️ 0 💤 2
24 297 runs  24 290 ✔️ 0 💤 7

For more details on these failures, see this check.

Results for commit 5971f1a.

♻️ This comment has been updated with latest results.

New Minuit2 strategy for improved Hessian calculation and return without
making positive definite.

This proposed new Strategy in minuit2 is the same migrad behaviour as
Strategy=2 but with the following changes to the Hesse calculation:

  * The step and g2 tolerances have been zeroed so that the 7 cycles are
    forced in the diagonal-term calculation. This was found to be
    necessary in cases where asimov datasets were used for the
    minimization and there were very few iterations for the approximate
    covariance to be determined from.

  * Central finite difference is used for mixed partial derivatives.
    This requires 3 extra function evaluations per derivative, but is
    necessary in the case of minima where there is high curvature (in
    the case of high stats) and the forward finite difference (default)
    behaviour leads incorrectly to a non-positive-definite covariance
    matrix

  * Return the uncorrected covariance matrix, even if it is not positive
    definite. This useful for checking just how far from
    positive-definiteness the matrix is by being able to examine the
    eigenvalues.

Additionally, a lower bound on the precision allowed for the spread of
eigenvalues of the "hessian" correlation matrix (computing a correlation
matrix with the hessian as if it was a covariance matrix) was reduced
from 1e-6 to 1e-12 (see MnHesse.cxx) ... it is not clear why 1e-6 was
the lower bound previously, but current machine precision can beat that
(I get locally 1e-8). I left a comment about whether this lower bound
should be made configurable or not...

This new strategy was tested with a model with high statistics (almost
50 million events) where the migrad minimization was successful but the
hessian was being forced positive definite. With this new Strategy 3 the
hessian is accurate and positive definite in all cases tested.
@guitargeek guitargeek changed the title Add new Strategy to Minuit2 for more precise hesse algorithm and return without forcing positive definite [Math][Minuit2] Add new Strategy to Minuit2 for more precise hesse algorithm and return without forcing positive definite Oct 23, 2023
@@ -1201,7 +1204,43 @@ bool Minuit2Minimizer::Hesse()
return false;
}

const int strategy = Strategy();

// set strategy and add extra options if needed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if the code is not duplicated from Minimize(), but I can also take care of this technicality.

@guitargeek
Copy link
Contributor

@phsft-bot build

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-performance-centos8-multicore/soversion, ROOT-ubuntu2204/nortcxxmod, ROOT-ubuntu2004/python3, mac12arm/cxx20, windows10/default
How to customize builds

@phsft-bot
Copy link
Collaborator

Build failed on windows10/default.
Running on null:C:\build\workspace\root-pullrequests-build
See console output.

Errors:

  • [2023-10-23T10:59:06.408Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(270,22): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(273,22): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(275,22): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(277,22): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(280,22): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(282,22): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(284,25): error C2679: binary '=': no operator found which takes a right-hand operand of type 'initializer list' (or there is no acceptable conversion) [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(396,100): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'ROOT::VecOps::RVec<CustomStruct>' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(401,94): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'CustomStruct' [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]
  • [2023-10-23T10:59:06.768Z] C:\build\workspace\root-pullrequests-build\root\tree\ntuple\v7\test\ntuple_show.cxx(401,27): error C2672: 'ROOT::Detail::VecOps::RVecImpl<T>::emplace_back': no matching overloaded function found [C:\build\workspace\root-pullrequests-build\build\tree\ntuple\v7\test\ntuple_show.vcxproj]

And 12 more

@guitargeek guitargeek merged commit 7b9f26e into root-project:master Oct 23, 2023
4 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants