简体   繁体   中英

Define model function parameters as a function of independent variable using lmfit python

I'm trying to fit a model function to my data. the data is a time(t) series. the model function needs to change at specific times (in this case, t=7 and t=14) so that another expression is added to it at each time point. therefore i'd like to have a parameter that is a function of time, ie c = 0 if t < 7 else 1 .


rate() is my model function, a and k are parameters that i'm trying to optimize and c1 , c2 are the above discussed time dependent coefficients. I used the .make_params method to define my parameters and passed the relevant expressions for c1 , c2 , into the .add method.

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)

data is a pandas Series:

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

this is the error i got:

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>'

I'd be grateful for any advice,

cheers,

Parameters in lmfit are meant to contain a single value. They will be evaluated once per fitting step (that is, per call to your objective/model function) and will not be evaluated separately for each data point.

Anyway, what you would want to use is "numpy.where()" in place of the comparison operator.

But, I think it would be more obvious and reable to just do that "where" in the code, not in parameter expressions, such as 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)

It is probably more efficient and closer to what you were doing to compute c1 and c2 once ahead of time. You can then tell lmfit to treat these as independent, non-varying parameters:

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)

Of course, the results should be the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM