【问题标题】:Using __call__ method of a class as a input to Numpy curve_fit使用类的 __call__ 方法作为 Numpy curve_fit 的输入
【发布时间】:2012-12-16 23:07:05
【问题描述】:

我想使用一个类的__call__ 方法作为 Numpy curve_fit 函数的输入,因为我的函数和数据准备过程相当复杂(将分析模型数据拟合到某些测量值)。通过定义一个函数它工作得很好,但我不能让它与类一起工作。

要重现我的问题,您可以运行:

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

我怎样才能做到这一点?

【问题讨论】:

  • 在我看来,这是一个非常好的 StackOverflow 问题示例。问题概述得很清楚,并用可以重现问题的最少代码进行了演示。包括回溯。做得很好。我希望更多的人支持这个。

标签: python class numpy call curve-fitting


【解决方案1】:

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

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

有趣的是,numpy 会强制您将函数对象传递给 curve_fit,而不是任意可调用的 ...

快速检查curve_fit 的来源,似乎另一种解决方法可能是:

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

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

【讨论】:

  • 我不确定goal.__call__ 是否会起作用,因为该函数实际上是一个方法并且有一个额外的参数(self)。
  • @poke -- 试一试,效果很好。 goal.__call__ 是实例方法,它是一个环绕func.__call__ 并在调用func.__call__ 时将实例插入到正确位置的函数。
  • 好的,我相信你,因为我自己没有 numpy atm 来测试它。只是inspect.getargspec 仍然报告self 参数为goal.__call__
  • @poke -- 是的。但是如果你打印类型,它仍然是instancemethod 类型,这意味着它将通过python 的魔法正确地传递给它的第一个参数:) 我们在Tkinter 中一直使用回调做同样的事情——@ 987654338@
  • @poke -- 是的,numpy 仍然正确(正如我所希望的那样)。与 OP 所说的纯函数进行比较是正确的,表明它们产生了相同的答案。请注意,如果您在__call__ 中将第一个参数的名称从self 更改为fooself,它会中断。在这种情况下,显然 numpy 严重依赖该约定。 :)。确实非常有趣。感谢您指出这一点并激励我深入研究这一点。 (直到游戏的后期,我才意识到 numpy 正在检查该功能——如果不是你的评论,我永远不会意识到这一点)。
猜你喜欢
  • 2017-10-25
  • 2012-09-02
  • 2015-08-31
  • 2011-12-10
  • 2011-10-21
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
  • 2017-01-08
相关资源
最近更新 更多