拟合反比例函数

时间:2017-08-22 18:12:35

标签: python scipy

我想将函数f(x) = b + a / x放到我的数据集中。为此我发现优化的scipy leastsquares是合适的。

我的代码如下:

x = np.asarray(range(20,401,20))

y是我计算的距离,但是是一个长度为20的数组,这里只是随机数,例如

y = np.random.rand(20)

对参数a和b的初步猜测:

params = np.array([1,1])

最小化的功能

def funcinv(x):
    return params[0]/x+params[1]

res = least_squares(funinv, params, args=(x, y))

给出错误:

 return np.atleast_1d(fun(x, *args, **kwargs))
  

TypeError:funinv()占用1个位置参数但是3个被赋予

我如何适合我的数据?

1 个答案:

答案 0 :(得分:2)

要做一点清晰。有两个相关的问题:

  1. 最小化功能
  2. 将模型拟合到数据
  3. 使模型适合观察到的数据是找到模型的这些参数,这些参数最小化模型数据和观测数据之间的某种错误

    least_squares方法只是最小化关于x的后续函数(x可以是向量)。

      

    F(x)= 0.5 *总和(rho(f_i(x)** 2),i = 0,...,m - 1)

    rho是一种损失函数,默认为rho(x) = x,所以暂时不要介意)

    least_squares(func, x0)预计对func(x)的调用将返回一个向量[a1, a2, a3, ...],其中将计算平方和:S = 0.5 * (a1^2 + a2^2 + a3^2 + ...)

    least_squares将调整x0以最小化S

    因此,为了使用它来使模型适合数据,必须在模型和实际数据之间构建误差函数 - 残差然后最小化残差功能。在您的情况下,您可以按如下方式编写它:

    import numpy as np
    from scipy.optimize import least_squares
    
    x = np.asarray(range(20,401,20))
    y = np.random.rand(20)
    params = np.array([1,1])
    
    def funcinv(x, a, b):
        return b + a/x
    
    def residuals(params, x, data):
        # evaluates function given vector of params [a, b]
        # and return residuals: (observed_data - model_data)
        a, b = params
        func_eval = funcinv(x, a, b)
        return (data - func_eval)
    
    res = least_squares(residuals, params, args=(x, y))
    

    这给出了一个结果: print(res)

    ... 
    message: '`gtol` termination condition is satisfied.'
        nfev: 4
        njev: 4   optimality: 5.6774618339971994e-10
        status: 1
        success: True
        x: array([ 6.89518618,  0.37118815])
    

    但是,由于残差函数始终基本相同(res = observed_data - model_data),因此scipy.optimize中有一个名为curve_fitcurve_fit(func, xdata, ydata, x0)的快捷方式。 curve_fit自动构建残差函数,您只需编写:

    import numpy as np
    from scipy.optimize import curve_fit
    
    x = np.asarray(range(20,401,20))
    y = np.random.rand(20)
    params = np.array([1,1])
    
    def funcinv(x, a, b):
        return b + a/x
    
    res = curve_fit(funcinv, x, y, params)
    print(res)  #  ... array([ 6.89518618,  0.37118815]), ...