tBuLi / symfit

Symbolic Fitting; fitting as it should be.
http://symfit.readthedocs.org
MIT License
233 stars 17 forks source link

Defining Models with numpy functions #322

Closed edmundsj closed 3 years ago

edmundsj commented 3 years ago

I am trying to fit some data to a nonlinear model (specifically a square root model), and it doesn't seem to be possible to use functions other than +, -, * and **. I am trying to use numpy's sqrt function to define a model:

import numpy as np
from symfit import Parameter, Variable

a = Parameter('a')
x = Variable('x')
model = np.sqrt(a*x)

When I try to run this, I get the following:

AttributeError: 'Parameter' object has no attribute 'sqrt'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: loop of ufunc does not support argument 0 of type Parameter which has no callable sqrt method

This would seem to indicate that in order to define a model, the functinons we are using have to already be known about by the Parameter class. Is there a way to define models explicitly with functions? Can we not use numpy functions to define models? Isn't this the major strength of scipy curve fitting? What is the workaround? Do we need to use sympy to define all non-basic functions?

edmundsj commented 3 years ago

Looks like symfit comes with its own equivalent of numpy's functions (which I assume are wrappers around sympy). I'd suggest adding examples to the documentation using these (because their presence was not at all obvious).

pckroon commented 3 years ago

which I assume are wrappers around sympy

Correct. Models are basically sympy Expressions, which mean that you can also use sympy to create e.g. polynomials in minimal time. It also allows you to work with the expression tree [1], and a few other nice things which may come in handy at some point. Internally, it allows us to take analytical derivatives. Before sending the model off to a scipy minimizer, we let sympy translate it to a function that uses the scipy/numpy functions [2]. The only thing you need to be aware of is that you need to use symfit Parameters and Variables, rather than plain sympy Symbols.

I agree it's not super clear in the docs. It's in at least one of the examples ([3]), and it's mentioned in 2 lines that all other sympy functions are also exposed [4]. Do you have suggestions where/how to make this more clear in the docs?

I hope this clears some things up :)

[1] https://docs.sympy.org/latest/tutorial/manipulation.html [2] https://docs.sympy.org/latest/modules/numeric-computation.html#lambdify [3] https://symfit.readthedocs.io/en/stable/tutorial.html#named-models [4] https://symfit.readthedocs.io/en/stable/tutorial.html#symfit-exposes-sympy-api