python scipy.optimize.curve\u fit使用的参数太多

python scipy.optimize.curve\u fit使用的参数太多,python,scipy,curve-fitting,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 p

我试图在类实例方法中进行一些曲线拟合,而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
以及曲线拟合函数调用

    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_流并这样调用它来实现它:

spopt.curve_fit(get_flow, pressure_drop, flow)   
但这并不好,因为它确实需要成为类中的一个方法,才能像我所希望的那样具有多功能。如何将此工作作为类实例方法进行


我还希望能够通过self来获得更多的参数,这些参数不是曲线拟合所使用的拟合参数。这可能吗?

如果在
HeatData
类中定义
get\u flow
,则必须将
self
作为第一个参数:
def get\u flow(self、压降、系数):

编辑:在寻找曲线拟合的定义后,i
curve\u fit(f,xdata,ydata,p0=None,sigma=None,**kw)
因此第一个参数必须是一个可调用的参数,将第一个参数作为自变量调用: 尝试关闭:

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 ) 

尝试删除“self”并进行调用:
spopt.curve\u fit(get\u flow,pressure\u drop,flow)
类方法定义的第一个参数应该始终是self。它会自动传递并引用调用类,因此该方法在调用时总是比您传递的多接收一个参数。

不幸的情况,可能是曲线拟合中的错误。曲线拟合使用inspect来确定起始值的数量,如果存在额外的
self
,则会产生混淆或误导

@staticmethod   
def get_flow(pressure_drop, coeff):
    """Sets flow based on coefficient and pressure drop.""" 
    flow = coeff * pressure_drop**0.5
    return flow
所以我想,给出一个起始值应该可以避免这个问题。然而,在这种情况下也有一个isscalar(p0),我不知道为什么,我认为最好将其作为问题或bug报告:

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。

处理这个问题的唯一Python方法是让Python知道
get\u flow
是一个
staticmethod
:一个函数,你把它放在类中,因为概念上它属于类,但它不需要,因此不需要
self

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

staticmethod
可以通过函数中未使用
self
这一事实来识别。

我尝试过,然后错误是
get\u flow()正好取3个参数(给定4个)
在调用curve\u fit(self.get\u flow,self,…)时尝试添加self作为参数当前,我得到了
def get\u flow(self,压降,系数):
spopt.curve\u fit(self.get\u flow,pressure\u drop,flow)
这仍然会产生错误
get\u flow()只需要3个参数(4个给定)
如果调用
spopt.curve\u fit(self.get\u flow,self,pressure\u drop,flow)
?这个主意很酷,但它就是这样做的:
get\u flow()只需要2个参数(给定16个)
如果get\u flow被定义为一个HeatData方法,那么我通过删除self得到以下错误:
全局名称“get\u flow”没有定义
我想我只需要一种方法来调用get\u flow而不调用self引用,这显然是为绑定方法自动完成的,无论“self”是否作为参数传递。有点奇怪/酷的是,“self”一词只是一个约定,我可以用“hornswagle”一词代替self。我想这不是一个非常描述性的编码实践。太好了!我现在这样运行:
popt,pcov=spopt.curve\u fit(self.get\u flow,pressure\u drop,flow,p0=np.array([self.exh.flow\u coeff])
并且它工作得很好。我同意这是一个错误,因为如果我给p0一个值,它应该使用它来确定参数的数量,即使p0是一个标量。