Pass tuple as input argument for scipy.optimize.curve_fit

Yuxiang Wang picture Yuxiang Wang · Aug 20, 2013 · Viewed 11.7k times · Source

I have the following code:

import numpy as np
from scipy.optimize import curve_fit


def func(x, p): return p[0] + p[1] + x


popt, pcov = curve_fit(func, np.arange(10), np.arange(10), p0=(0, 0)) 

It will raise TypeError: func() takes exactly 2 arguments (3 given). Well, that sounds fair - curve_fit unpact the (0, 0) to be two scalar inputs. So I tried this:

popt, pcov = curve_fit(func, np.arange(10), np.arange(10), p0=((0, 0),))

Again, it said: ValueError: object too deep for desired array

If I left it as default (not specifying p0):

popt, pcov = curve_fit(func, np.arange(10), np.arange(10))  

It will raise IndexError: invalid index to scalar variable. Obviously, it only gave the function a scalar for p.

I can make def func(x, p1, p2): return p1 + p2 + x to get it working, but with more complicated situations the code is going to look verbose and messy. I'd really love it if there's a cleaner solution to this problem.

Thanks!

Answer

cass picture cass · Oct 17, 2013

Not sure if this is cleaner, but at least it is easier now to add more parameters to the fitting function. Maybe one could even make an even better solution out of this.

import numpy as np
from scipy.optimize import curve_fit


def func(x, p): return p[0] + p[1] * x

def func2(*args):
    return func(args[0],args[1:])

popt, pcov = curve_fit(func2, np.arange(10), np.arange(10), p0=(0, 0))
print popt,pcov

EDIT: This works for me

import numpy as np
from scipy.optimize import curve_fit

def func(x, *p): return p[0] + p[1] * x

popt, pcov = curve_fit(func, np.arange(10), np.arange(10), p0=(0, 0))
print popt,pcov