Python 使用类的_调用_方法作为Numpy曲线拟合的输入

Python 使用类的_调用_方法作为Numpy曲线拟合的输入,python,class,numpy,call,curve-fitting,Python,Class,Numpy,Call,Curve Fitting,由于我的函数和数据准备过程相当复杂(将分析模型数据拟合到一些测量值),我想使用类的\u调用\u方法作为Numpy曲线拟合函数的输入。通过定义一个函数,它工作得很好,但我无法让它与类一起工作 要重新创建我的问题,您可以运行: 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*

由于我的函数和数据准备过程相当复杂(将分析模型数据拟合到一些测量值),我想使用类的
\u调用\u
方法作为Numpy曲线拟合函数的输入。通过定义一个函数,它工作得很好,但我无法让它与类一起工作

要重新创建我的问题,您可以运行:

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
我得到的错误是:

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
回溯(最近一次呼叫最后一次):
文件“D:\…某个路径…\test\u miniminacija.py”,第35行,在
popt,pcov=曲线拟合(目标、扩展数据、ydata)
文件“C:\Python26\lib\site packages\scipy\optimize\minpack.py”,第412行,曲线拟合
args,varargs,varkw,默认值=inspect.getargspec(f)
getargspec中第803行的文件“C:\Python26\lib\inspect.py”
raise TypeError('arg不是Python函数')
TypeError:arg不是Python函数
我怎样才能做到这一点

简单(虽然不漂亮),只需将其更改为:

popt, pcov = curve_fit(goal.__call__, xdata, ydata)
有趣的是,numpy强制您将函数对象传递给
curve\u fit
,而不是任意调用的函数对象

快速检查源代码的曲线拟合情况,另一个解决方法可能是:

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

这里,
p0
是拟合参数的初始猜测。问题似乎在于
scipy
检查函数的参数,以便在您没有实际提供参数作为初始猜测的情况下,它知道要使用多少参数。在这里,由于我们有5个参数,我最初的猜测是长度为5的所有参数的列表。(
scipy
默认情况下,如果您不提供猜测,则也会使用一个)。

在我看来,这是一个非常好的StackOverflow问题的示例。这个问题被清楚地描述出来,用最少的代码演示,可以重现这个问题。包括回溯。干得好。我希望有更多的人对此表示支持。我不确定
goal.\uuuu call\uuuu
是否有效,因为函数实际上是一个方法,并且有一个额外的参数(
self
)。@poke——试试看,效果很好
goal.\uuu call\uu
是一个实例方法,它是一个围绕
func.\uu call\uu
的函数,在调用
func.\uu call\uu
时将实例插入正确的位置。好的,我相信你,因为我自己没有numpy atm来测试它。只是
inspect.getargspec
仍然报告
goal的
self
参数。但是如果您打印类型,它仍然是类型
instancemethod
,这意味着它将通过python的魔力正确地传递给它的第一个参数:)我们在
Tkinter
中一直使用回调来做同样的事情--
self.button=tk.button(master,text=“foo”,command=self.method)
@poke--是的,numpy仍然做对了(正如我所希望的那样)。与OP所说的纯函数的比较表明,它们得到了相同的答案。请注意,如果在
\uuuu call\uuuu
中将第一个参数的名称从
self
更改为
fooself
,则它将中断。显然,在这种情况下,numpy严重依赖于该公约。真的很有趣。感谢你指出这一点,并激励我在这一点上深入挖掘。(直到游戏进行到很晚的时候,我才意识到numpy在检查这个函数——如果没有你的评论,我永远也不会意识到)。