Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Inconsistencies with non-parameter model function arguments #917

Closed
schtandard opened this issue Nov 7, 2023 · 1 comment
Closed

Inconsistencies with non-parameter model function arguments #917

schtandard opened this issue Nov 7, 2023 · 1 comment

Comments

@schtandard
Copy link
Contributor

Description

I have a model function that contains a keyword argument that is not part of the fit parameters (but not a compulsory independent variable either). My expectation was that I can just pass it as a keyword argument to the model's fit() method when I need to set it. Here's an example with s being the argument in question.

import lmfit
import numpy as np
from matplotlib import pyplot as plt

# Create a model.
def foo(x, a=3, b=5, s=1):
    return a + s * b * x**2
mdl = lmfit.Model(foo, param_names=['a', 'b'])
mdl.set_param_hint('a', value=3)
mdl.set_param_hint('b', value=5)

# Synthesize some noisy data.
x = np.linspace(-5, 5, 101)
s = 1 + 0.7 * np.sin(x)
y = foo(x, 2.3, 1.7, s) + np.random.normal(0, 1, x.shape)

# Fit the data and report the result
fitres = mdl.fit(y, x=x, s=s)
print(fitres.fit_report())
fitres.plot()
plt.show()

# Manually check the result.
plt.plot(x, y, '.', label='data')
plt.plot(x, fitres.eval(x=x), label='fit result eval()')
plt.plot(x, foo(x, a=fitres.params['a'], b=fitres.params['b'], s=s), label='manual check')
plt.legend()
plt.show()

Passing s to fit() like this results a warning.

C:\Users\wilde\miniconda3\lib\site-packages\lmfit\model.py:1053: UserWarning: The keyword argument s does not match any arguments of the model function. It will be ignored.

However, the fit still seems to perform as expected, i.e. the argument is passed on to the fitting function, the resulting parameters are correct. Here's the fit report (a = 2.3 and b = 1.7 were used during data synthesis).

[[Model]]
    Model(foo)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 7
    # data points      = 101
    # variables        = 2
    chi-square         = 109.127855
    reduced chi-square = 1.10230157
    Akaike info crit   = 11.8173660
    Bayesian info crit = 17.0476071
    R-squared          = 0.99636556
[[Variables]]
    a:  2.13258073 +/- 0.13627980 (6.39%) (init = 3)
    b:  1.69611547 +/- 0.01029550 (0.61%) (init = 5)
[[Correlations]] (unreported correlations are < 0.100)
    C(a, b) = -0.6421

Adding to the confusion, the fit result's plot() function draws the correct residuals and data but an incorrect best fit, i.e. it really does ignore s here.
image
The eval() method on the other hand seems to respect s.
image

Version information
Python: 3.9.18 | packaged by conda-forge | (main, Aug 30 2023, 03:40:31) [MSC v.1929 64 bit (AMD64)]

lmfit: 1.2.2, scipy: 1.11.3, numpy: 1.26.0,asteval: 0.9.31, uncertainties: 3.1.7
@reneeotten
Copy link
Contributor

The plotting feature is a very rudimentary convenience function. You presumably need to pass the independent variable to the plot function as well. I can take a closer look at this, but it doesn’t necessarily appear as a real GitHub Issue. If you read the instructions you would have realized that, and at least provided all the information requested in the template.

@lmfit lmfit locked and limited conversation to collaborators Nov 7, 2023
@reneeotten reneeotten converted this issue into discussion #920 Nov 7, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
2 participants