使用lmfit python

时间:2019-07-03 08:48:21

标签: python lmfit

我正在尝试将模型函数拟合到我的数据中。数据是一个时间序列。模型函数需要在特定时间(在这种情况下,t = 7和t = 14)进行更改,以便在每个时间点向其添加另一个表达式。因此我想有一个随时间变化的参数,即 c = 0,如果t <7否则为1


rate()是我的模型函数, a k 是我要优化的参数, c1 < / strong>, c2 是上述时间相关系数。 我使用 .make_params 方法定义参数,并将 c1 c2 的相关表达式传递到 .add 方法。

from numpy import exp
from lmfit import Model


# model function
def rate(x, a, k, c1, c2):
    def rate_unit(z):
        return a * (exp(-k * (z - 0.5)) - exp(-k * (z + 0.5)))

    return rate_unit(x) + c1 * rate_unit(x - 7) + c2 * rate_unit(x - 14)

# define independent and dependent variables
t = data.index.values
y = data.values

# setup the model
rate_model = Model(rate)

# setup parameters
parameters = rate_model.make_params()
parameters.add('a', value=200)
parameters.add('k', value=0.5)
parameters._asteval.symtable['t'] = t
parameters.add('c1', expr='0 if t < 7 else 1')
parameters.add('c2', expr='0 if t < 14 else 1')

# fit model to data
fit_result = rate_model.fit(y, parameters, x=t)

数据是熊猫系列:

In [32]: data                                                                                                                                               
Out[32]: 
days
0      0.000000
1     50.986817
3      8.435668
7      0.519960
8     80.628749
10    10.067202
14     6.065180
15    88.029249
21     4.854688
Name: ORG, dtype: float64

这是我得到的错误:

ValueError
   <_ast.Module object at 0x7fab7d47f278>
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Traceback (most recent call last):
  File "model_dynamics.py", line 58, in <module>
    parameters.add('c1', expr='0 if t < 7 else 1')

ValueError: at expr='<_ast.Module object at 0x7fab7d47f278>'

如果有任何建议,我将不胜感激,

欢呼

1 个答案:

答案 0 :(得分:0)

lmfit中的参数旨在包含单个值。将在每个拟合步骤(即,对目标/模型函数的每次调用)中对它们进行一次评估,而不会针对每个数据点分别进行评估。

无论如何,您要使用的是“ numpy.where()”代替比较运算符。

但是,我认为,只需在代码中的“位置”而不是在参数表达式中(例如:)使用“ ”,就会更明显和更可靠。

import numpy as np
# model function
def rate(x, a, k):
    def rate_unit(z):
        return a * (np.exp(-k * (z - 0.5)) - enp.xp(-k * (z + 0.5)))
    c1 = np.zeros(len(x))
    c2 = np.zeros(len(x))
    c1[np.where(x>7)] = 1
    c2[np.where(x>14)] = 1
    return rate_unit(x) + c1 * rate_unit(x-7) + c2 * rate_unit(x-14)


# setup the model
rate_model = Model(rate)

# setup parameters
parameters = rate_model.make_params(a=200, k=0.5)

# fit model to data
fit_result = rate_model.fit(y, parameters, x=t)

它可能会更高效,并且更接近于您提前计算c1c2所做的工作。然后,您可以告诉lmfit将它们视为独立的,不变的参数:

import numpy as np
# helper function (define once, not each time `rate` is called!)
def rate_unit(z):
    return a * (np.exp(-k * (z - 0.5)) - enp.xp(-k * (z + 0.5)))

# model function
def rate(x, a, k, c1, c2):
    return rate_unit(x) + c1 * rate_unit(x-7) + c2 * rate_unit(x-14)

# setup the model
rate_model = Model(rate, independent_vars=('x', 'c1', 'c2'))

# setup parameters
parameters = rate_model.make_params(a=200, k=0.5)

c1 = np.zeros(len(t))
c2 = np.zeros(len(t))
c1[np.where(t>7)] = 1
c2[np.where(t>14)] = 1
# fit model to data
fit_result = rate_model.fit(y, parameters, x=t, c1=c1, c2=c2)

当然,结果应该相同。