Reputation: 1
I'm using the built-in Levenberg-Marquardt algorithm to fit some data. It calls some function which needs to have the syntax foo(x,a1,a2,...,an), where an are parameters and the number of input arguments specifies the number of dimensions the L-M algorithm minimizes. Currently this foo function calls some other function I have defined as :
foo(x, a1, a2, ..., an):
ai = [a1,a2,...,an]
result = somefun(x,ai)
return result
Is there a way to use a compact syntax in this case? I would like to be able to define some parameter L = n
, which specifies the number of input arguments somewhere before the function definition.
Note: Please also read that using
foo(x,*ai)
, will generateValueError: Unable to determine number of fit parameters
before marking as duplicate.
Upvotes: 0
Views: 506
Reputation: 281948
The function you're using, scipy.optimize.curve_fit
, only needs to introspect f
to find the number of arguments if you don't pass an initial guess as a p0
argument. If you can provide a good guess, do so; otherwise, you can pass in a guess of all ones:
scipy.optimize.curve_fit(f, xdata, ydata, p0=[1]*n)
Then you can use def f(x, *args)
syntax.
If for some reason you really need f
to have independently specified positional arguments, I would use exec
. That's rarely a good idea, but in this case, it may be warranted.
template = '''
def f(x, {args}):
return somefun(x, [{args}])
'''
definition = template.format(args=', '.join('a'+str(i) for i in xrange(n)))
namespace = {'somefun': somefun}
exec definition in namespace
f = namespace['f']
Upvotes: 0
Reputation: 99
You should probably specify in your question that the function you're using is from scipy, which is not part of the standard library.
From the docstring for scipy.optimize.curve_fit:
optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False, check_finite=True, **kw)
...
Parameters
----------
f : callable
The model function, f(x, ...). It must take the independent
variable as the first argument and the parameters to fit as
separate remaining arguments.
xdata : An M-length sequence or an (k,M)-shaped array
for functions with k predictors.
The independent variable where the data is measured.
ydata : M-length sequence
The dependent data --- nominally f(xdata, ...)
p0 : None, scalar, or N-length sequence
Initial guess for the parameters. If None, then the initial
values will all be 1 (**if the number of parameters for the function
can be determined using introspection, otherwise a ValueError
is raised**).
...
With the foo(x,*args) construction, the number of parameters can't be determined from introspection, so you get your ValueError, but you can still pass a sequence of initial values via the p0 argument, which will let the algorithm know that the number of parameters is the length of that sequence. So for example,
n=5
foo(x,*args):
return somefun(x,args)
curve_fit(foo,x0,y0,p0=[1]*n)
Upvotes: 1
Reputation: 10328
Use the *args
syntax:
foo(x, *args):
result = somefun(x, args)
return result
This grabs all arguments besides x
and stores them in the tuple args
.
Upvotes: 2