2

我正在尝试在类实例方法中进行一些曲线拟合,而 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 使用的参数的参数。这可能吗?

4

5 回答 5

2

不幸的情况,可能是curve_fit中的一个错误。curve_fit 使用 inspect 来确定起始值的数量,如果有额外的self.

所以给出一个起始值应该可以避免这个问题,我想。但是,条件中还有一个 isscalar(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])

具有两个参数和给定起始值的示例避免了检查调用,一切都很好:

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 的第一个参数传递。
在 github 上提交 bug 修复提交

于 2011-10-05T04:39:13.500 回答
1

如果您get_flowHeatData类中定义,则必须将其self作为第一个参数:def get_flow(self, pressure_drop, coeff):

编辑:在寻找curve_fit的定义后,我发现原型是 curve_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 ) 
于 2011-09-30T20:42:04.810 回答
0

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

于 2011-10-02T02:11:32.303 回答
0

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

于 2011-09-30T21:23:40.053 回答
0

处理这个问题的唯一 Pythonic 方法是让 Python 知道get_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

staticmethodself可以通过函数中未使用的事实来识别。

于 2016-10-02T18:11:01.193 回答