Open karllark opened 2 years ago
I'm not quite sure how to proceed. Do others have more knowledge of the LevMar algorithm that could provide insight? Maybe there are parameters we could set? @jdtsmith?
One possible longer term solution would be to use the LevMar fit as the starting point for a MCMC sampler (e.g., emcee) and then compute the parameter uncertainties (and any combined parameter uncertainties) needed from the sampler chains. This should be more robust and provide full 1d posterior probability distribution functions (pPDFs) as well. Or 2D pPDFs. Or whatever nD pPDFs one is interested in.
Current astropy.modeling LevMarLSQFitter uses older scipy.optimize.leastsq interface. https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html
If updating to new scipy.optimize.least_squares interface would help (e.g., access to more tuning parameters from what I can see), this could be done (I could put in a PR to astropy to do this). https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html
Both use the MINPACK implementation of the Levenberg-Marquardt algorithm.
LM certainly provides uncertainty estimates as a matter of course, since it uses these during optimization to make informed guesses about steps to take. BUT, I know that MPFIT for example sets parameter uncertainty to zero when it hits a boundary:
PERROR - The formal 1-sigma errors in each parameter, computed
from the covariance matrix. If a parameter is held
fixed, or if it touches a boundary, then the error is
reported as zero.
You can see why they might make that choice: if you've hit a boundary, by definition you now have a limiting result. I believe @ThomasSYLai asked me that questions about non-zero parameters in the IDL PAHFIT with zero uncertainty on Monday, and I think this is the answer. If scipy makes the same choice, this could be the problem. What happens if you remove all fitting parameter limits?
Current astropy.modeling LevMarLSQFitter uses older scipy.optimize.leastsq interface. https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html
If updating to new scipy.optimize.least_squares interface would help (e.g., access to more tuning parameters from what I can see), this could be done (I could put in a PR to astropy to do this). https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html
Both use the MINPACK implementation of the Levenberg-Marquardt algorithm.
We can check if for example scipy's curve_fit
would return the covariance matrix in our test examples.
Setting something like:
pars, covar = curve_fit(func, xdata, ydata, sigma=ydata_unc, p0=p0, bounds=bounds, absolute_sigma=True)
where the func would be our compound model.
And then retrieve uncertainties by: perr = np.sqrt(np.diag(covar))
.
As noted in PRs #141, #142, #143, we are not getting uncertainties when using the LevMar fitter interface provided by in astropy.modeling. Initial thoughts were that the problem could be the Compound astropy.model we use or that some of the components in this Compound model were not "stock" astropy functions.
Work by @alexmaragko showed that it was not the Compound model.
Continuing this investigation, I have been able to show that it is not the use of non-"stock" models. The issue seems to be when a parameter is not needed or is at one of the limits (zero in the example 2 below). This is not an issue with astropy.modeling, but is the result of the underlying scipy function not returning a covariance matrix. Astropy.modeling uses the scipy returned covariance matrix to calculate the uncertainties.
1st example works - uncertainties reported. 2nd example does not report uncertainties. Only difference is that the simulation has tau_sil = 0 instead of tau_sil = 1.
Example 1 of fitting a Compound model with (Drude + line) * S07_attenuation model (see code below). The tau_sil = 1 in the simulation.
Example 2 of fitting a Compound model with (Drude + line) * S07_attenuation model (see code below). The tau_sil = 0 in the simulation.
Test code used (based on the code given in PR #143):