trouble using ModelFit/ModelResult eval method

354 views
Skip to first unread message

Christoph Rosemann

unread,
Nov 13, 2017, 9:09:58 AM11/13/17
to lmfit-py
Hi,

thanks for this fabulous library. It completely replaces everything I have written so far in the respect of python parameter estimation toolkits.

I'm in middle of the first project that really uses lmfit, but I get stuck. I have searched the Release Notes and the mailing list, but either I have overlooked the hint or I didn't recognize it.

For now I'm stuck with an older version of lmfit (0.8.0), due to the infrastructue I'm developing for (currently still Debian 8). But also didn't get it to work with 0.8.3, nor with the most recent 0.9.3.

I do a pre-defined model curve fit to some data. The result seems promising enough, but as a step in the further processing I'd like to evaluate the found result function at a number of different points.

My understanding was a chain like: model.fit( data)  ---> fitresult() ---> .eval(data=different_xdata) ---> evaluated y-values

But this only returns the initially used data points (actually only the used x-values); with a complete disregard for the argument keyword 'data'.

Am I doing something wrong? And if so, what is it?

Cheers,
Christoph

Matt Newville

unread,
Nov 14, 2017, 7:45:54 AM11/14/17
to lmfit-py
Hi Christoph,


On Mon, Nov 13, 2017 at 8:09 AM, Christoph Rosemann <mymindis...@gmail.com> wrote:
Hi,

thanks for this fabulous library. It completely replaces everything I have written so far in the respect of python parameter estimation toolkits.

I'm in middle of the first project that really uses lmfit, but I get stuck. I have searched the Release Notes and the mailing list, but either I have overlooked the hint or I didn't recognize it.

For now I'm stuck with an older version of lmfit (0.8.0), due to the infrastructue I'm developing for (currently still Debian 8). But also didn't get it to work with 0.8.3, nor with the most recent 0.9.3.


The latest version is actually 0.9.7. Version 0.8.0 is over three years old.  Version 0.9.0 is two years old, and there was a major change in behavior between 0.8.3 and 0.9.0 such that scripts need rewriting.  This is a small enough project that it's hard enough for us to support most recent version. 

It's unfortunate to be stuck with old versions of python, numpy, and scipy provided by the system package manager.   The scientific python stack has been evolving much more quickly than the "stable" linux distributions.  Installing and using sometihing like Anaconda Python (or another scientific python distribution) is pretty easy, and allows the latest scientific python packages without disturbing the system-installed python.  Conveniently, there are conda and pypi packages for 0.9.7.


I do a pre-defined model curve fit to some data. The result seems promising enough, but as a step in the further processing I'd like to evaluate the found result function at a number of different points.

My understanding was a chain like: model.fit( data)  ---> fitresult() ---> .eval(data=different_xdata) ---> evaluated y-values

Do you mean 'eval(x=different_xdata)'?  If so, that's roughly correct.  But it isn't specific about the Parameters used, which might be important because that is what changed with 0.9.0 



But this only returns the initially used data points (actually only the used x-values); with a complete disregard for the argument keyword 'data'.

Hm, don't you mean 'x'? 


Am I doing something wrong? And if so, what is it?
 

Well, I see a couple things you might be doing wrong:

 a) tryng to use a very old, unsupported version of the library.
 b) not providing a complete example of actual code that shows the problem you're having.

For sure, we're more likely to be able to help if you provide a small example that we can read or perhaps even run.

Hope that helps,

--Matt 

Christoph Rosemann

unread,
Nov 16, 2017, 3:18:19 AM11/16/17
to lmfit-py
HI Matt,

thanks for your reply. I agree on all the topics you mentioned about writing, maintaining and deploying software. There is a large gap between the different roles in terms of what they want and what can be achieved. As usual I also wear all the different hats.

On the matter at hand, I've already found out that I was using the wrong keyword -- as you mentioned in the post. I mixed up the documentation of the different versions and got confused.
To show some pseudo-code:
 fitresult = myfunc.fit(data, x=independentVariable)

And then I or anyone can use either of the two calls:
fitresult.eval(x=otherData)
fittedmodel
= fitresult.model
fittedmodel
.eval(x=otherData)

Thanks!

Cheers,
Christoph

Anton

unread,
Dec 3, 2017, 4:15:14 PM12/3/17
to lmfit-py
What I have just noticed, is that after a call such as this one:

fitresult.eval(x=otherData)

the otherData replaces the original data in the fitresult object.  So when you then call:

fitresult.eval()

it uses otherData again.  Same behaviour for any keyword arguments.

If this is by design, it should probably be mentioned somewhere (in addition to here).

Doing a plot() after this uses the old data with the new x, which will most probably not be correct.
Also, the plot doesn't appear to to pass keyword arguments on to the model function.

Hopefully this is useful information for someone.

Anton

Matt Newville

unread,
Dec 3, 2017, 8:03:56 PM12/3/17
to lmfit-py
Hi Anton,

On Sun, Dec 3, 2017 at 3:15 PM, Anton <anton....@gmail.com> wrote:

Is this reply really a follow-up to this thread? It sort of seems like a different topic to me.  

Anyway, for sure, documenting implicit behavior and finding spots where implicit behavior could be improved or made explicit are good things to work on.

What I have just noticed, is that after a call such as this one:

fitresult.eval(x=otherData)

the otherData replaces the original data in the fitresult object.  So when you then call:

fitresult.eval()

it uses otherData again.  Same behaviour for any keyword arguments.

If this is by design, it should probably be mentioned somewhere (in addition to here).

I would say it is not by design, but rather laziness or ambiguity. 

If you don't specify `x` (or any other independent variable) to `fitresult.eval()`, what should it do?   I think reasonable choices would be
   a) raise an exception, complaining that `x` must specified.
   b) use the original `x` used to create the `fitresult`.
   c) use the last provided `x`.

Apparently, it currently uses choice "c".  I don't know that I have a strong opinion for which of these is best. I think "a" would be slightly obnoxious but it might be the right choice.

I think that a Model should not retain data or independent variables (or parameters).  But a ModelResult probably should retain at least some of those, which would suggest option "b".


Doing a plot() after this uses the old data with the new x, which will most probably not be correct.
Also, the plot doesn't appear to to pass keyword arguments on to the model function.

Hm, yeah the `plot_*` methods of ModelResult look like they implicitly assume that the independent variables have not been changed after the initial fit. I guess that should be fixed, or at least better documented. 


Hopefully this is useful information for someone.

Yes, thanks for that.  I agree it is not ideal, but I'm also not sure what the best solution is.
Does anyone have a suggestion for the right behavior here?

If you are up for it, creating a Github Issue about this is probably a good idea.

--Matt


Reply all
Reply to author
Forward
0 new messages