使用 lmfit python 将模型函数参数定义为自变量的函数
Define model function parameters as a function of independent variable using lmfit python
我正在尝试将模型函数拟合到我的数据中。数据是时间(t)序列。模型函数需要在特定时间(在本例中为 t=7 和 t=14)发生变化,以便在每个时间点向其添加另一个表达式。因此我想要一个随时间变化的参数,即 c = 0 if t < 7 else 1。
rate() 是我的模型函数,a 和 k 是我的参数我正在尝试优化,c1、c2 是上面讨论的时间相关系数。
我使用 .make_params 方法来定义我的参数,并传递了 c1、c2[= 的相关表达式38=],进入.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)
数据是一个pandas系列:
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>'
如有任何建议,我将不胜感激,
干杯,
lmfit
中的参数旨在包含单个值。它们将在每个拟合步骤(即每次调用您的 objective/model 函数)评估一次,并且不会针对每个数据点单独评估。
无论如何,您要使用 "numpy.where()" 代替比较运算符。
但是,我认为在代码中而不是在参数表达式中这样做 "where" 会更加明显和可靠,例如 with:
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)
提前一次计算 c1
和 c2
可能效率更高,更接近于您所做的。然后您可以告诉 lmfit 将这些视为独立的,non-varying 参数:
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)
当然,结果应该是一样的。
我正在尝试将模型函数拟合到我的数据中。数据是时间(t)序列。模型函数需要在特定时间(在本例中为 t=7 和 t=14)发生变化,以便在每个时间点向其添加另一个表达式。因此我想要一个随时间变化的参数,即 c = 0 if t < 7 else 1。
rate() 是我的模型函数,a 和 k 是我的参数我正在尝试优化,c1、c2 是上面讨论的时间相关系数。 我使用 .make_params 方法来定义我的参数,并传递了 c1、c2[= 的相关表达式38=],进入.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)
数据是一个pandas系列:
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>'
如有任何建议,我将不胜感激,
干杯,
lmfit
中的参数旨在包含单个值。它们将在每个拟合步骤(即每次调用您的 objective/model 函数)评估一次,并且不会针对每个数据点单独评估。
无论如何,您要使用 "numpy.where()" 代替比较运算符。
但是,我认为在代码中而不是在参数表达式中这样做 "where" 会更加明显和可靠,例如 with:
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)
提前一次计算 c1
和 c2
可能效率更高,更接近于您所做的。然后您可以告诉 lmfit 将这些视为独立的,non-varying 参数:
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)
当然,结果应该是一样的。