-
Notifications
You must be signed in to change notification settings - Fork 0
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
API: Minimizer #1
Comments
I have a fundamental question: I am not sure what this should accomplish? I don't think zfit has the influence to establish an interface that is then adopted by independent much larger projects such as libnlopt or scipy.optimize. For iminuit, I already provide a standard interface (scipy.optimize.minimize). If you want to establish standards, I think you need to do that from within the scipy community. They already put a lot of thought into the scipy.optimize.minimize interface, so perhaps any proposal should build on that interface? There is more to consider than what you write here. What about setting limits and constraints? Regarding "statefulness or not": stateless functions are easier to reason about and they can be trivially parallelized. I would generally prefer that, but the stateful approach of Minuit also has its merits. This design does not allow me to start the minimization with extra information that I have already acquired in previous calls (I cannot pass a previously calculated Hessian matrix, for example, and there is no way for the minimizer to know that I am already close to the minimum). Minuit was designed to pass a maximum of internal information from one method to another. This idea is deeply ingrained into Minuit, but not in scipy.optimize. That's ok, because scipy.optimize is only about minimization, while Minuit also computes errors. It does extra things and so another design makes sense. |
I overall agree with your points. Thanks a lot for the inputs! Let's be more specific: The scope: It's true that zfit won't have that influence and it ain't that goal. Indeed, the goal is rather to converge to a standard in HEP before many people build their own optimizers interface (as they do unfortunately...). So better get a good standard within the niche of HEP than 10+ all over the place. The question on the API is not standalone, it also ask for a good integration with parameters and objective functions as well as the returned fit-result. Here are the main thoughts why something "new" is needed:
So the idea is: what is the optimal interface for "complicated" minimizations as used in HEP? If we can converge, great! If not, well, then not. But we should at least try and collect the inputs. The more we converge (even with names etc) the better. And additionally adapting to a standard interface such as scipy is oc always a possibility. About limits and constraints: that's indeed a point and it may be well suited to pass this alongside the As said, it ain't about to have the perfect API. But to at least have had this discussion once and see what we can actually share. |
I still don't see how you can converge to "a standard in HEP". Do you think you can change the scipy interface? Or libnlopt? I think the best you can do is write an isolated wrapper library which does the adjustment and then share that between projects.
A stateless function can have the same functionality as a stateful function, it is not a drawback in principle. It is a matter of initialization. The stateful object passes information implicitly. A stateless function must pass information explicitly (that's also why they are easier to reason about, everything is transparent and open). You can always go for stateless, if you make the initialization rich enough to pass all required info.
Computing errors as part of the minimization is one of the synergies achieved in Minuit. This is a good thing. Minuit has to compute an accurate Hessian anyway for its stopping criterion. It then also uses the output of that calculation to give you the errors. When running Minos, it also uses the previously computed Hessian matrix to find the intervals faster. Everything is deeply connected in Minuit and synergies are achieved this way. All this makes sense when you actually care about computing the errors. You cannot easily separate error computation from minimization, because there are synergies between the two steps. You have to think about these two steps together when you come up with an API. I am not saying that the API must be that of Minuit, but I strongly disagree with your statement that we can define a minimizer API in isolation and then worry about a separate error computation API. These two things need to be thought of together or you will regret it later.
Scipy is complex because it offers a lot of knobs and tweaks and a lot of functionality. It is not overloaded IMHO. Try to do the same as scipy does with less API and you will see. I don't think you can simplify the API a lot without also cutting away functionality.
I don't know these, but they probably do less. Do they allow for linear and non-linear constraints, for example? |
No, not at all. But this is not in our interest as scipy and nlopt are not HEP focused libraries. When talking about a standard, I don't mean this large projects. I mean the dozens of projects that do something along the line of minimization and invent their own optimizer (e.g. flamedisx, tensorwave etc.). The idea is to provide this standard so that
I fully agree! This is the goal with zfit and why we care so much about the API: because we want to distribute a "possible standard" and that API should be nice. Now one thing is to have wrappers, another is a certain convergence in small things, e.g. on keywords used in iminuit etc. The less we need to wrap, the better. And the whole discussion is about that: what's the most useful API for our usecases? (Maybe the answer is scipy or nlopt, that's great! I am very happy whoever sticks to these interfaces instead of reinventing the wheel or offers an interface, such as in iminuit) Now of course, iminuit is different in its scope compared to scipy and nlopt, so a different interface makes sense.
While true theoretically, it requires to introduce some kind of function that allows to actually execute the minimization. Not impossible to do, sure.
These are two different things: that you cannot separate vs that there are synergies. I think you can separate quite well but you may loose synergies. The question is then simply, what is actually needed. And in this case I think it's "just" the Hessian estimate, right? The advantage of the big picture is that this allows to use other minimizers such as scipy which do not need to implement error methods (if we separate the two). Otherwise, any minimizer would need to implement its own error method which is more or less identical and would be a large hurdle to be used.
They do less, however I meant the principle that you do:
so that you move the type of the minimizer and the options specific to the minimimzer in the instantiation (which than can look very different for different minimizers) and you're left with a more general and lean Just to get the overall picture right: what we try to achieve with zfit is to have this well defined interfaces, not just of a minimizer, but also of a fit result (including error calculation), cost function, pdf. Not every detail. But at least many attributes. In order to converge as much as possible and avoid that everyone has their own wrapper of scipy, nlopt etc. This would also apply to maybe think about the A problem that currently e.g. arises is the output of the fit which contains this P.S: we're very grateful about the comments and I do fully agree that e.g. iminuit will have it's own API (and the 2.0 break was great!), especially with the uncertainties. But this is just about a discussion on a more general case and your expertise and opinion is very welcome. |
Discussion for an optimal minimizer interface to be used for likelihood (-like) minimization tasks.
Questions
Statefullness
Should the minimizer be stateful or not or both (e.g. within a context)? A stateful minimizer has the advantage of enabling a simple way of fine-grained minimization control which alternatively has to be done via arguments to the
minimize
function. However, it requires to create a new minimizer for every minimization and the minimization procedure cannot be simply replicated (while if it's stateless, it's always a simple call tominimize
).API
minimize(loss, params)
minimize the loss fully using the given params. Return a
FitResult
.minimize_step
minimize a single step, can be not implemented.
Returned result
What is the best result to be returned? a
FitResult
, but maybe just a minimal API is fine?The text was updated successfully, but these errors were encountered: