Определить параметры функции модели как функцию независимой переменной с помощью lmfit python - PullRequest
2 голосов
/ 03 июля 2019

Я пытаюсь приспособить функцию модели к моим данным. данные представляют собой временной ряд (t). функция модели должна меняться в определенные моменты времени (в данном случае t = 7 и t = 14), чтобы в каждый момент времени к ней добавлялось другое выражение. поэтому я хотел бы иметь параметр, который является функцией времени, то есть c = 0, если t <7, иначе 1 </strong>.


rate () - это функция моей модели, a и k - параметры, которые я пытаюсь оптимизировать, и c1 , 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 голосов
/ 04 июля 2019

Параметры в 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)

Возможно, это более эффективно и ближе к тому, что вы делали для вычисления c1 и c2 один раз раньше времени. Затем вы можете указать 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)

Конечно, результаты должны быть одинаковыми.

...