简体   繁体   中英

Using __call__ method of a class as a input to Numpy curve_fit

I would like to use a __call__ method of a class as a input to a Numpy curve_fit function due to my rather elaborate function and data preparation process (fitting analytical model data to some measurements). It works just fine by defining a function, but I can't get it to work with classes.

To recreate my problem you can run:

import numpy as np
from scipy.optimize import curve_fit

#WORKS:
#def goal(x,a1,a2,a3,a4,a5):
#    y=a1*x**4*np.sin(x)+a2*x**3+a3*x**2+a4*x+a5
#    return y

# DOES NOT WORK:
class func():
    def __call__(self,x,a1,a2,a3,a4,a5):
        y=a1*x**4*np.sin(x)+a2*x**3+a3*x**2+a4*x+a5
        return y    

goal=func()

#data prepraration ***********
xdata=np.linspace(0,50,100)
ydata=goal(xdata,-2.1,-3.5,6.6,-1,2)
# ****************************

popt, pcov = curve_fit(goal, xdata, ydata)
print 'optimial parameters',popt
print 'The estimated covariance of optimial parameters',pcov

The error i get is:

Traceback (most recent call last):
  File "D:\...some path...\test_minimizacija.py", line 35, in <module>
    popt, pcov = curve_fit(goal, xdata, ydata)
  File "C:\Python26\lib\site-packages\scipy\optimize\minpack.py", line 412, in curve_fit
    args, varargs, varkw, defaults = inspect.getargspec(f)
  File "C:\Python26\lib\inspect.py", line 803, in getargspec
    raise TypeError('arg is not a Python function')
TypeError: arg is not a Python function

How can I make this work?

Easy (although, not pretty), just change it to:

popt, pcov = curve_fit(goal.__call__, xdata, ydata)

It's interesting that numpy forces you to pass a function object to curve_fit rather than an arbitrary callable ...

quickly inspecting the source for curve_fit , it appears that another workaround might be:

popt,pcov = curve_fit(goal, xdata, ydata, p0=[1]*5)

Here, p0 is the initial guess for the fit parameters. The problem appears to be that scipy inspects the arguments to the function so that it knows how many parameters to use if you don't actually provide parameters as an initial guess. Here, since we have 5 parameters, my initial guess is a list of all ones of length 5. ( scipy defaults to using ones if you don't provide a guess also).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM