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

Support scipy optimiser #414

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Conversation

MarcelHoh
Copy link

@MarcelHoh MarcelHoh commented Jun 24, 2023

This PR implements the suggestions on #413.

  1. Add a minimizer option to limit,ranking,scan,significance , _fit_model and fit_model that allows for switching between minuit and scipy. Set defaults to use scipy when no uncertainties are needed.
  2. Removes the custom_fit option entirely. This goes beyond your suggestion. Should this still be supported?

I haven't looked into tests yet, I thought I would first make the PR to start the discussion.

@alexander-held
Copy link
Member

alexander-held commented Jul 1, 2023

Thanks for getting this started and sorry for the slow feedback!

I would like to keep custom_fit around for fit.fit() (fine to remove from ranking and scan) as it is sometimes convenient to switch to it for debugging and adjust the Minuit functions being called within _fit_model_custom, which gives convenient full access. This is certainly more of a power user feature, I suspect most people would not need that, but it is the reason I've kept around this function.

There is no need to implement a scipy-equivalent of _fit_model_custom though I would say, so if fit() is called with both custom_fit and minimizer=scipy then we could just raise a NotImplementedError.

As mentioned on the issue, I would also prefer to stick with Minuit by default due to having more confidence in the MIGRAD algorithm. That makes it a conscious choice for the user to go with a faster (but possibly slightly less safe) scipy choice.

The pre-commit CI failure is unrelated and fixed by #416.

elif minimizer == "scipy":
bestfit = pyhf.tensorlib.to_numpy(result)
# scipy does not return uncertainty or correlation results
uncertainty = np.zeros(bestfit.shape)
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be safer to go with something like np.nan here for the uncertainties. Zero is also used to indicate that a parameter is constant (see discussion in scikit-hep/iminuit#762), so it is a bit of an overloaded value already.

# scipy does not return uncertainty or correlation results
uncertainty = np.zeros(bestfit.shape)
corr_mat = np.diag(np.ones(bestfit.shape))
minos_results = None
Copy link
Member

Choose a reason for hiding this comment

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

So far the code has used an empty dict {} in this case, I don't mind None necessarily but is there a difference in functionality between them for this case or can we stick with the dict?

bestfit = pyhf.tensorlib.to_numpy(result)
# scipy does not return uncertainty or correlation results
uncertainty = np.zeros(bestfit.shape)
corr_mat = np.diag(np.ones(bestfit.shape))
Copy link
Member

Choose a reason for hiding this comment

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

Super minor, the rest of the code base uses np.diagflat instead of np.diag and I think the reasoning behind this is that np.diag does both extraction and creation while diagflat is only for creating and thus perhaps a bit more concise.

I am unsure how I feel about returning a diagonal matrix here. On one hand, it is the best guess we still have (we know nothing about correlations in this setup), on the other hand it may suggest that we know things that we really do not know. Filling everything with np.nan also doesn't seem ideal as clearly the diagonal will all be ones regardless. Just wondering whether making this a nice diagonal might cause issues with e.g. people using the results to do post-fit plots that do not make any sense.


Returns:
FitResults: object storing relevant fit results
model (pyhf.pdf.Model): the model to use in the fit
Copy link
Member

Choose a reason for hiding this comment

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

some accidental whitespace additions in this docstring

@MarcelHoh
Copy link
Author

Thanks for the feedback! Sorry for the delay on my side as well, I've been quite busy the last week.
I will probably not have time to get back to this for a few more weeks, but it's high on my to-do list.

@alexander-held
Copy link
Member

Hi @MarcelHoh, no worries! Feel free to get back to this when you have time, I don't think it is going to collide with anything in the short term.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants