Python lmfit最小化加权初始数据

Python lmfit最小化加权初始数据,python,curve-fitting,lmfit,Python,Curve Fitting,Lmfit,我是python的新手,我正在尝试使用lmfit进行一些曲线拟合。代码运行得很好,但我想强制拟合原点(0,0)。我在stakoverlow中看到,使用“曲线拟合”可以添加和属性“sigma”,这可以实现技巧,但在“最小化”中不起作用。你有解决这个问题的办法吗 到目前为止,这是我的代码: ############################################################################## ###################### IMPO

我是python的新手,我正在尝试使用lmfit进行一些曲线拟合。代码运行得很好,但我想强制拟合原点(0,0)。我在stakoverlow中看到,使用“曲线拟合”可以添加和属性“sigma”,这可以实现技巧,但在“最小化”中不起作用。你有解决这个问题的办法吗

到目前为止,这是我的代码:

##############################################################################
###################### IMPORT MODULES ########################################
##############################################################################
import numpy as np
import matplotlib.pyplot as plt
from lmfit import minimize, Parameters
from lmfit import report_fit

##############################################################################
##################### DATA ##################################
##############################################################################
x=np.array([0,1, 4, 6, 8, 9, 11, 13, 15, 18, 20, 27])
data=np.array([0, 67, 208, 339, 460, 539, 599, 635, 659, 685, 701, 731])

##############################################################################
######################## GOMPERTZ FUNCTION DEFINITION#########################
##############################################################################

def BMP_Gompertz(params, x, data):
    BMPmax=params['BMPmax'].value
    Rmax=params['Rmax'].value
    Lambda=params['Lambda'].value

    model=BMPmax*np.exp(-np.exp(Rmax*np.exp(1)/BMPmax*(Lambda-x)+1))

    global model_data
    model_data=[BMPmax,Rmax,Lambda]

    return data-model

params=Parameters()
params.add('BMPmax', value=300., min=0.)
params.add('Rmax', value=25., min=0.) 
params.add('Lambda',value=0.5, min=0.)

model_data=[]


##############################################################################
###################### GOMPERTZ CURVE FITTING & REPORT #######################
##############################################################################
result=minimize(BMP_Gompertz, params, args=(x,data))
report_fit(result.params)

##############################################################################
########################## GOMPERTZ PLOTTING #################################
##############################################################################
plt.plot(x, data, 'bo')
t=np.linspace(0.,100,10000)
plt.plot(t,model_data[0]*np.exp(-np.exp(model_data[1]*np.exp(1)/model_data[0]*(model_data[2]-t)+1)))
plt.xlabel('Days')
plt.ylabel('BMP (NLbiogas/kg SV)')
plt.show()
如您所见,拟合不是从(0,0)开始,而是在(0,10)左右开始,我希望始终强制它从(0,0)开始。。。看起来我仍然无法上传图片(还没有任务)。。。不管怎么说,我想你能理解这一点

还有一个问题,是否有其他方法存储参数并绘制结果?。现在,为了存储模型返回的参数,我将它们存储在一个名为“model_data”的全局变量中。然后,在绘图部分,我使用linspace创建了一个名为“t”的新“x”数组,然后使用“model_data”中存储的参数绘制t与BMP_Gompertz(myfunction)的关系。它工作得很完美,但看起来应该有其他更好的方法来实现这一点


非常感谢您的帮助

我不确定您所有的问题都能得到完全回答,但这里有几点意见:

  • 您可以为贴合度添加权重。通过使用
    minimize
    的示例,您可以传入一个数组
    sigma
    来保存数据中的不确定性,并将
    返回数据模型更改为
    返回(数据模型)/sigma
    。下面,我将推荐使用
    lmfit.Model
    ,它有一种稍微不同的方法来指定权重

  • 让您当前的模型通过(0,0)将是一个挑战,即使使用权重。也就是说,指数函数衰减,但永远不会达到0,所以您可能需要确定什么是“足够零”。如果这是物理需求,则可能需要修改模型

  • 拟合结果将被存储,您无需使用
    model\u数据
    。返回的
    result.params
    包含最佳拟合参数,您可以获得
    result.params['Rmax'].value

  • 由于您正在进行曲线拟合并使用
    lmfit
    ,因此我建议使用
    lmfit.Model
    ,这将简化您的代码并更容易提取预测模型进行绘图。使用
    lmfit.Model
    您在目标函数中所做的大部分工作都是为您完成的,您的脚本将变成:

    import numpy as np
    import matplotlib.pyplot as plt
    from lmfit import Model
    
    x=np.array([0,1, 4, 6, 8, 9, 11, 13, 15, 18, 20, 27])
    data=np.array([0, 67, 208, 339, 460, 539, 599, 635, 659, 685, 701, 731])
    
    # This function now returns the model. The function arguments are 
    # named so that Model() will know what to name the Parameters.
    def BMP_Gompertz(x, bmpmax, rmax, xlambda):
        return bmpmax *np.exp(-np.exp((rmax*np.exp(1)/bmpmax)*(xlambda-x)+1))
    
    # create a Model from the model function
    bmodel = Model(BMP_Gompertz)
    
    # create Parameters, giving initial values
    params = bmodel.make_params(bmpmax=300, rmax=25, xlambda=0.5)
    params['bmpmax'].min = 0
    params['rmax'].min = 0
    params['xlambda'].min = 0
    
    # do fit, print result
    result = bmodel.fit(data, params, x=x)
    print(result.fit_report())
    
    # plot results -- note that `best_fit` is already available
    plt.plot(x, data, 'bo')
    plt.plot(x, result.best_fit, 'r--')
    
    t=np.linspace(0.,100,10000)
    
    # use `result.eval()` to evaluate model given params and x
    plt.plot(t, bmodel.eval(result.params, x=t), 'k-')
    plt.xlabel('Days')
    plt.ylabel('BMP (NLbiogas/kg SV)')
    plt.show()
    
    要向模型拟合添加权重,可以定义一个权重数组,用于将数据模型相乘,并将其传递给模型拟合。要强调具有最低值的数据(并将拟合推向(0,0),可以使用以下方法:

    weights = 1.0 / np.sqrt(data + 1)
    result = bmodel.fit(data, params, x=x, weights=weights)
    

    同样,这将强调较小的
    y
    值,并倾向于在
    x=0
    处向下推模型值,但不会真正强制结果精确到(0,0)。

    我们如何看到它开始于(0,10)?我们没有您的数据集。请阅读并确定该数据集应该如何包含点(0,0)对于!=0?拟合未加权数据与拟合所有权重均设置为1的加权数据是一样的。如果不确定数据点的值,则权重通常较小,如果值的确定性较大,则权重会变大。实际上,您完全确定拟合曲线必须通过数据点[0,0],任何具有加权拟合选项的曲线拟合软件都可以执行此操作。将现有数据的所有权重设为1.0,您将获得现有拟合,因此,请执行此操作并添加点[0,0]权重非常大,比如说,1.0E6。我编辑了文本以提供我使用的确切数据集。感谢您的帮助,我使用了我在Gunary方程上建议的加权拟合,得到了比代码中的方程更好的拟合。我将您的数据与Gunary“y=x/(a+b*x+c*pow(x,0.5))”一起使用安装参数a=3.4870068291759794E-02,b=2.8734350762674270E-03,c=-1.435744019901366E-02非常感谢你,m Newville。答案非常有用!!!!我会尽快测试它,但看起来你解决了我所有的问题,再次感谢你!!!