【问题标题】:ValueError: Unable to determine number of fit parameters. "Problem in curve fitting"ValueError:无法确定拟合参数的数量。 “曲线拟合问题”
【发布时间】:2020-03-06 20:28:22
【问题描述】:

我是python新手,所以我的知识不足。 我有一个名为“tlove_cc_seq2_k2_NL3.dat”的数据文件。我想为数据拟合曲线。 我使用的代码如下::

...

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    import math
    import pandas as pd
    import lmfit
    from lmfit import Model
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    from array import *

    def test(x, a, b, c): 
         return (a + b*math.log(x) + c*math.log(x)**2)

    func = np.vectorize(test)

    data_k2_2fl_NL3=np.loadtxt('tlove_cc_seq2_k2_NL3.dat')
    plt.plot(data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5], 'b-', label='data')
    popt, pcov = curve_fit(func, data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5])
    popt

    plt.plot(data_k2_2fl_NL3[:,8], func(data_k2_2fl_NL3[:,8], *popt), 'r-',
             label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
    popt, pcov = curve_fit(func, data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5], bounds=(-20, 
    [30., 30., 20.5]))
    popt

    plt.plot(data_k2_2fl_NL3[:,8], func(data_k2_2fl_NL3[:,8], *popt), 'g--',
             label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    plt.show()

...

我得到的错误如下::

... ValueError Traceback(最近一次调用最后一次) 在 13 #y = 数据[:, 1] 14 plt.plot(data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5], 'b-', label='data') ---> 15 popt, pcov = curve_fit(func, data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5]) 16 点 17

    ~/anaconda3/lib/python3.7/site-packages/scipy/optimize/minpack.py in curve_fit(f, xdata, 
    ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
        678         args, varargs, varkw, defaults = _getargspec(f)
        679         if len(args) < 2:
    --> 680             raise ValueError("Unable to determine number of fit parameters.")
        681         n = len(args) - 1
        682     else:

    ValueError: Unable to determine number of fit parameters.

我该如何解决这个问题? 谢谢。

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    我认为问题在于 curve_fit 函数无法通过自省来确定参数的数量,因为您要求它适合的函数 (test) 包含在 np.vectorize 函数中。

    我尝试了一个最小的示例,其中我使用了未矢量化的 test 函数并且它有效:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    
    def test(x, a, b, c): 
            return (a + b*np.log(x) + c*np.log(x)**2)
    
    func = np.vectorize(test)
    
    #Create some dummy data
    x_data = list(range(1, 11))
    y_data = np.log(x_data) + np.log(x_data)**2 + np.random.random(10)
    
    plt.plot(x_data, y_data, 'b-', label='data')
    popt, pcov = curve_fit(test, x_data, y_data)
    popt
    

    如果出于性能原因需要vectorize,您还可以将参数p0 传递给初始参数数组。例如:

    popt, pcov = curve_fit(func, x_data, y_data, p0=[1,1,1])
    

    【讨论】:

    • 问题是我需要从数据文件中拟合数据集。当我没有进行矢量化时,我收到了类似“TypeError:只有 size-1 数组可以转换为 Python 标量”之类的错误。由于这是在将数字数组作为输入代替单个数字时生成的,所以我进行了矢量化。主要问题是我需要从文件中拟合数据。
    • 您可以尝试在您的test 函数中使用np.log(如我的回答)代替math.log 吗? numpy 方法接受数组。传递初始化向量p0 不起作用吗?
    • 非常感谢,它成功了。主要问题是 np.log。它需要数组,而 math.log 不需要。
    • 太棒了。如果答案解决了您的问题,您可以将其标记为“已接受”,然后其他人就知道它已解决。
    • 我现在赞成 M Newville 的答案,因为它显示了对 lmfit 的更好使用。我以前没有使用过那个包,所以勉强让错误消失了。听起来他的回答显示了使用该软件包的更好方法。
    【解决方案2】:

    您遇到的大多数问题似乎都与使用 numpymath 相比。为了完整起见,既然您提到了lmfit,要使用lmfit 执行此操作,您可以使用

    import numpy as np
    import matplotlib.pyplot as plt
    from lmfit import Model
    
    def test(x, a, b, c): 
        return (a + b*np.log(x) + c*np.log(x)**2)
    
    # create model from your model function
    mymodel = Model(test)
    
    # create initial set of named parameters from argument of your function
    params = mymodel.make_params(a=0.5, b=1.1, c=0.5)
    
    # Create some dummy data
    x_data = np.linspace(1, 10, 10)
    y_data = np.log(x_data) + np.log(x_data)**2 + np.random.random(len(x_data))
    
    # run fit, get result
    result = mymodel.fit(y_data, params, x=x_data)
    
    # print out full fit report: fit statistics, best-fit values, uncertainties
    print(result.fit_report())
    
    # make a stacked plot of residual and data + fit
    result.plot()
    plt.show()
    

    请注意,curve_fit() 很乐意接受未初始化的参数,并为所有参数分配不可能证明的默认值 1。 Lmfit 不允许这样做并强制您显式设置初始值。但它也能更好地报告拟合统计数据、不确定性,并允许组合更复杂的模型。

    对于您的示例,适合报告将显示

    [[Model]]
        Model(test)
    [[Fit Statistics]]
        # fitting method   = leastsq
        # function evals   = 8
        # data points      = 10
        # variables        = 3
        chi-square         = 0.91573485
        reduced chi-square = 0.13081926
        Akaike info crit   = -17.9061352
        Bayesian info crit = -16.9983799
    [[Variables]]
        a:  0.69752193 +/- 0.34404583 (49.32%) (init = 0.5)
        b:  1.17700278 +/- 0.59765274 (50.78%) (init = 1.1)
        c:  0.85298657 +/- 0.23838141 (27.95%) (init = 0.5)
    [[Correlations]] (unreported correlations are < 0.100)
        C(b, c) = -0.961
        C(a, b) = -0.782
        C(a, c) =  0.607
    

    和一个情节

    【讨论】:

    • 感谢更详细的解释和分享您对lmfit的体验。我以前没用过那个包。
    猜你喜欢
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    相关资源
    最近更新 更多