python scipy.optimize.curve_fit使用的参数太多

时间:2011-09-30 20:27:04

标签: python scipy curve-fitting

我正在尝试在类实例方法中进行一些曲线拟合,而curve_fit函数为我的类实例方法提供了太多参数。

代码是

class HeatData(hx.HX):
    """Class for handling data from heat exchanger experiments."""

然后几行方法工作正常,那么我的功能是:

    def get_flow(pressure_drop, coeff):
        """Sets flow based on coefficient and pressure drop.""" 
        flow = coeff * pressure_drop**0.5
        return flow

和curve_fit函数调用

    def set_flow_array(self):
        """Sets experimental flow rate through heat exchanger"""
        flow = self.flow_data.flow
        pressure_drop = self.flow_data.pressure_drop
        popt, pcov = spopt.curve_fit(self.get_flow, pressure_drop, flow)
        self.exh.flow_coeff = popt
        self.exh.flow_array = ( self.exh.flow_coeff * self.exh.pressure_drop**0.5 )

给出错误

get_flow() takes exactly 2 arguments (3 given)

我可以通过在类之外定义get_flow并像这样调用它来使它工作:

spopt.curve_fit(get_flow, pressure_drop, flow)   

但这并不好,因为它真的需要成为课堂上的一种方法才能像我想要的那样多才多艺。如何将此工作作为类实例方法?

我还希望能够将self传递给get_flow,以便为其提供更多参数,这些参数不适合curve_fit使用的参数。这可能吗?

5 个答案:

答案 0 :(得分:2)

不幸的情况,也许是curve_fit中的错误。 curve_fit使用inspect来确定起始值的数量,如果有额外的self,它会被混淆或误导。

所以给出一个起始值应该避免这个问题,我想。但是,在条件中还有一个问题(p0),我不知道为什么,我认为将其报告为问题或错误会很好:

if p0 is None or isscalar(p0):
        # determine number of parameters by inspecting the function
        import inspect
        args, varargs, varkw, defaults = inspect.getargspec(f)

编辑:避免将标量作为起始值

>>> np.isscalar([2])
False

表示只有1个参数的示例在起始值定义为[...]时有效,例如与下面的示例类似:

mc.optimize([2])

带有两个参数和一个给定起始值的示例可以避免inspect调用,一切都很好:

import numpy as np
from scipy.optimize import curve_fit

class MyClass(object):
    def get_flow(self, pressure_drop, coeff, coeff2):
        """Sets flow based on coefficient and pressure drop.""" 
        flow = coeff * pressure_drop**0.5 + coeff2
        return flow

    def optimize(self, start_value=None):
        coeff = 1
        pressure_drop = np.arange(20.)
        flow = coeff * pressure_drop**0.5 + np.random.randn(20)
        return curve_fit(self.get_flow, pressure_drop, flow, p0=start_value)

mc = MyClass()
print mc.optimize([2,1])

import inspect
args, varargs, varkw, defaults = inspect.getargspec(mc.get_flow)
print args, len(args)

编辑:这个错误已经修复,所以如果你有一个足够新的scipy版本,现在可以将绑定方法作为curve_fit的第一个参数传递。
Commit of bug fix submission on github

答案 1 :(得分:1)

如果您在get_flow课程中定义HeatData,则必须将self作为第一个参数:def get_flow(self, pressure_drop, coeff):

编辑:在寻找curve_fit的定义之后,i found that the prototype is curve_fit(f, xdata, ydata, p0=None, sigma=None, **kw)所以第一个arg必须是一个可调用的,它将被第一个参数作为自变量调用: 尝试使用闭包:

def set_flow_array(self):
        """Sets experimental flow rate through heat exchanger"""
        flow = self.flow_data.flow
        pressure_drop = self.flow_data.pressure_drop
        def get_flow((pressure_drop, coeff):
           """Sets flow based on coefficient and pressure drop.""" 
           #here you can use self.what_you_need
           # you can even call a self.get_flow(pressure_drop, coeff) method :)
           flow = coeff * pressure_drop**0.5
           return flow
        popt, pcov = spopt.curve_fit(get_flow, pressure_drop, flow)
        self.exh.flow_coeff = popt
        self.exh.flow_array = ( self.exh.flow_coeff * self.exh.pressure_drop**0.5 ) 

答案 2 :(得分:0)

尝试删除“自我”并拨打电话:spopt.curve_fit(get_flow, pressure_drop, flow)

答案 3 :(得分:0)

类方法定义的第一个参数应始终为self。它会自动传递并引用调用类,因此该方法总是会收到比调用时传递的参数多一个。

答案 4 :(得分:0)

解决这个问题的唯一方法就是让Python知道get_flowstaticmethod:你在课堂上放的一个函数,因为它在概念上属于那里,但它并不需要是的,因此不需要self

@staticmethod   
def get_flow(pressure_drop, coeff):
    """Sets flow based on coefficient and pressure drop.""" 
    flow = coeff * pressure_drop**0.5
    return flow
{p> staticmethod可以通过函数中未使用self的事实来识别。