将lmfit中的Model类与参数类

时间:2019-07-10 12:42:11

标签: python lmfit

我正在尝试使用lmfit拟合一些数据。最初,我使用Model类,该类根据此示例/教程运行良好: https://lmfit.github.io/lmfit-py/model.html 但是后来我想向模型添加一些参数约束,因此我看了本教程: https://lmfit.github.io/lmfit-py/parameters.html

但是,在将两个类组合在一起以使它们很好地协同工作时,我遇到了一些问题。 它要么抱怨fit函数缺少参数,要么抱怨参数无效(在我将发布的示例中就是这种情况),或者我得到的模型实际上并没有采用我指定的参数。 我实际上可以使用以下不同方法之一解决问题: 1.使用model.make_params(...)传递参数,但我想将它们单独拆分 2.我可以使用Minimizer代替Model,但是我想了解为什么它们实现如此不同,尽管我希望它们非常相似(除了它们适用于不同类型的输入)

任何帮助/解释将不胜感激。 :)

此代码基于“参数”教程页面上的示例。 我在这里所做的是修改示例,以便使用Model类而不是Minimizer类,该类原则上应该起作用,但是我以某种方式做错了。 作为比较,原始示例在此处(滚动到底部): https://lmfit.github.io/lmfit-py/parameters.html

# <examples/doc_parameters_basic.py>
import numpy as np

from lmfit import Model, Parameters

# create data to be fitted
x = np.linspace(0, 15, 301)
data = (5. * np.sin(2*x - 0.1) * np.exp(-x*x*0.025) +
        np.random.normal(size=len(x), scale=0.2))


# define objective function: returns the array to be minimized
def fcn2min(params, x):
    """Model a decaying sine wave and subtract data."""
    amp = params['amp']
    shift = params['shift']
    omega = params['omega']
    decay = params['decay']
    model = amp * np.sin(x*omega + shift) * np.exp(-x*x*decay)
    return model


# create a set of Parameters
params = Parameters()
params.add('amp', value=10, min=0)
params.add('decay', value=0.1)
params.add('shift', value=0.0, min=-np.pi/2., max=np.pi/2)
params.add('omega', value=3.0)

# do fit, here with leastsq model
fitmodel = Model(fcn2min)
result = fitmodel.fit(data, params, x=x)

# calculate final result
final = result.fit_report()

# try to plot results
try:
    import matplotlib.pyplot as plt
    plt.plot(x, data, 'k+')
    plt.plot(x, final, 'r')
    plt.show()
except ImportError:
    pass
# <end of examples/doc_parameters_basic.py>

但是像这样使用它,我得到一个错误

ValueError: Invalid independent variable name ('params') for function fcn2min

我尝试过: 将所有参数都指定为函数参数,例如

def fcn2min(x, amp, shift, omega, decay):

但是在这种情况下,我最终没有连接模型/功能参数,却得到了一个“不适合”的东西。

现在我尝试指定以下内容:

fitmodel = Model(fcn2min, independent_vars=['x'], param_names=params)

但是在这种情况下,我得到了

Invalid parameter name ('amp') for function fcn2min

也尝试过这样的事情:

params = fitmodel.make_params()
params.add('amp', value=10, min=0)
...

但是在这种情况下,我也没有获得与模型连接的参数,可以从

的输出中看到
fitmodel.param_names

返回一个空列表。

1 个答案:

答案 0 :(得分:0)

您混淆了Model类包装的模型函数和用于通过minimizeleastsq进行通用最小化的目标函数进行曲线拟合的函数。目标函数的签名如下:

 def objective(params, *args): 

其中params是一个lmfit.Parameters实例,您必须在函数中解包,而*args是可选参数。此函数将返回数组-目标-在最小二乘意义上将最小化。

相反,用于创建曲线拟合模型的模型函数将具有类似的签名

 def modelfunc(x, par1, par2, par3, ..., **kws):

其中x是自变量,而par1 ...将包含模型参数的。模型函数将返回一个对数据进行建模的数组。

有许多示例使用目标函数和模型函数 https://github.com/lmfit/lmfit-py/tree/master/examples。要对数据建模,您可以

# define MODEL **not objective** function: returns the array to model the data
def sinedecay(x, amp, shift, omega, decay):
    """Model a decaying sine wave""" . 
    return amp * np.sin(x*omega + shift) * np.exp(-x*x*decay)


# create model:
smodel = Model(sinedecay)

# create a set of Parameters
params = smodel.make_params(amp=10, decay=0.1, shift=0, omega=3)
params.set('amp', min=0)
params.set('shift',  min=-np.pi/2., max=np.pi/2)

# do fit
result = smodel.fit(data, params, x=x)