Создание модели Python lmfit с произвольным количеством параметров
Есть ли способ построить модель lmfit на основе функции с произвольным числом зависимых переменных? Например:
from lmfit import Model
def my_poly(x, *params):
func = 0
for i in range(len(params)):
func+= params[i]*z**i
return func
#note: below does not work
my_model = Model(my_poly, independent_vars = ['x'], param_names = ['A','B','C'])
Что-то похожее на вышесказанное было бы замечательно, если бы я заинтересовался полиномиальными сериями и хотел бы проверить производительность по мере роста или уменьшения серии.
1 ответ
Поскольку Model()
использует имена аргументов функций для построения имен параметров, используя *params
не будет легко работать (как узнать, как их назвать A
, B
, C
, и не coeff0
, coeff1
, coeff2
, или что-то другое?).
Я не знаю, что действительно произвольное число может быть поддержано, но должно быть возможно сделать очень большое число. Полиномиальная модель (см. http://lmfit.github.io/lmfit-py/builtin_models.html и https://github.com/lmfit/lmfit-py/blob/master/lmfit/models.py для реализации) поддерживает до 7 коэффициентов. Не должно быть никаких проблем распространить это на гораздо большее число. Это может легко привести к вычислительным проблемам, но я думаю, это то, что вы ожидаете изучить.
Если вы хотите внести небольшое изменение, можно сделать что-то, что вы ищете. Это использует аргументы ключевого слова вместо позиционных аргументов и опирается на порядок имен параметров (то есть с sort
), чтобы указать, какой коэффициент идет с каким показателем, а не порядком позиционных аргументов. Это может быть близко к тому, что вы ищете:
import numpy as np
from lmfit import Model, Parameters
def my_poly(x, **params):
val= 0.0
parnames = sorted(params.keys())
for i, pname in enumerate(parnames):
val += params[pname]*x**i
return val
my_model = Model(my_poly)
# Parameter names and starting values
params = Parameters()
params.add('C00', value=-10)
params.add('C01', value= 5)
params.add('C02', value= 1)
params.add('C03', value= 0)
params.add('C04', value= 0)
x = np.linspace(-20, 20, 101)
y = -30.4 + 7.8*x - 0.5*x*x + 0.03 * x**3 + 0.009*x**4
y = y + np.random.normal(size=len(y), scale=0.2)
out = my_model.fit(y, params, x=x)
print(out.fit_report())
Надеюсь, это поможет.