AttributeError при оценке модели symfit с вычитанием в показателе степени - PullRequest
0 голосов
/ 10 января 2019

Я настроил модель для подбора некоторых данных с вычитанием в показателе степени. Он отлично подходит для подгонки, но когда я явно оцениваю модель, я получаю странные результаты и объект AttributeError: 'Mul' не имеет атрибута 'exp'.

Проблема, похоже, связана с тем, как работает lambdify, и возникает при оценке модели, содержащей нетривиальные функции, такие как потенцирование или возведение в степень.

import symfit as sf

a = sf.Parameter('a',1,0,2) #name, initial value, minimum, maximum
b = sf.Parameter('b',1,0,2)
c=sf.Parameter('c',1,0,2)
x, y = sf.variables('x, y')

model=sf.Model({y: a * (c - sf.exp((x) / b))})
model(1,a,b,c)
Out: Ans(y=a*(c + 1))

model=sf.Model({y: a * (1 - sf.exp((x-c) / b))})
model(1,a,b,c)
Traceback (most recent call last):

  File "<ipython-input-9-faba3b52b923>", line 1, in <module>
    model(1,a,b,c)

  File "C:\PortablePrograms\Python\WPy-3670\python-3.6.7.amd64\lib\site-packages\symfit\core\fit.py", line 334, in __call__
    return Ans(*self.eval_components(**bound_arguments.arguments))

  File "C:\PortablePrograms\Python\WPy-3670\python-3.6.7.amd64\lib\site-packages\symfit\core\fit.py", line 296, in eval_components
    return [expr(*args, **kwargs) for expr in self.numerical_components]

  File "C:\PortablePrograms\Python\WPy-3670\python-3.6.7.amd64\lib\site-packages\symfit\core\fit.py", line 296, in <listcomp>
    return [expr(*args, **kwargs) for expr in self.numerical_components]

  File "C:\PortablePrograms\Python\WPy-3670\python-3.6.7.amd64\lib\site-packages\sympy\utilities\lambdify.py", line 444, in wrapper
    return funcarg(*newargs, **kwargsx)

  File "<string>", line 1, in <lambda>

AttributeError: 'Mul' object has no attribute 'exp'

Я бы ожидал, что будет использоваться начальное значение параметров, или получу символический ответ, но не получу ни того, ни другого.

Для первой модели результат, следовательно, неверный и несовместимый, я бы ожидал

Ans(y=a*(c-exp(1/b)) 

или

Ans(y=a*(c-1)) 

или просто

Ans(y=0)

Для второй модели lambdify, похоже, не может разобрать выражение.

Это также имеет место при использовании sf.sqrt () или sympy.exp (). Я работаю в Python 3.6.7 и IPython 7.1.1, используя Symfit 0.4.6 и Sympy 1.1.1 (так как Symfit не работает с более высокими версиями в соответствии с pip).

Я могу использовать любую модель для подбора данных и оценки модели с параметрами наилучшего соответствия, как показано в примере здесь (https://pypi.org/project/symfit/). Линия

yfit = model(x=xdata, **fit_result.params)[y] 

тоже не работает (пробовал на python 2.7, 3.5 и 3.6), если не изменить на

yfit = [model(x=x, **fit_result.params) for x in xdata]

1 Ответ

0 голосов
/ 29 января 2019

Вызов Model в symfit означает, что символическое выражение преобразуется в лямбда-функцию, то есть в обычную функцию python, которая больше не является символической.

В вашем примере вызов

sf.Model({y: a * (c - sf.exp((x) / b))})

эквивалентно написанию

lambda x, a, b, c: a * (c - np.exp((x) / b))

Обратите внимание, что символическая экспонента теперь заменена на numpy. Из этого примера вы можете видеть, что модель не предназначена для вызова с символическими выражениями, она предназначена для вызова с числами или массивами.

Таким образом, ваш звонок должен быть изменен на

model(x=1, a=1, b=1, c=1)

Если вам нужно работать на символическом уровне, продолжайте работать с выражениями в Model напрямую, вызов здесь только для числового использования.

Наконец, пример в документации предполагает, что xdata является массивом, но в примере это список. Это должно быть обновлено (мной).

В качестве последнего замечания, научитесь любить ключевые аргументы в python;). Следующее эквивалентно:

a = sf.Parameter('a',1,0,2) #name, initial value, minimum, maximum
a = sf.Parameter('a', value=1, min=0, max=2)

но только один самодокументируется:).

...