【问题标题】:How to put constraints on fitting parameter?如何对拟合参数施加约束?
【发布时间】:2015-11-26 20:40:04
【问题描述】:

我想为我的数据拟合一条曲线:

x=[24,25,28,37,58,104,200,235,235]  
y=[340,350,370,400,430,460,490,520,550]  
xerr=[1.1,1,0.8,1.4,1.4,2.6,3.8,2,2]

def fit_fc(x, a, b, c):  
return a*x**b+c

popt, pcov=curve_fit(fit_fc,x,y,maxfev=5000)

plt.plot(x,fit_fc(x,popt[0],popt[1],popt[2]))
plt.errorbar(x,y,xerr=xerr,fmt='-o') 

但我想对 a、b 和 c 施加一些限制。例如,我希望它们在某个范围内,比如说在 0 到 20 之间。我怎样才能做到这一点?我是 Python 新手,如果有任何帮助,我们将不胜感激。

【问题讨论】:

    标签: python python-2.7 curve-fitting


    【解决方案1】:

    您可以使用lmfit 来约束您的参数。对于下图,我将您的参数ab 限制在[0,20] 的范围内(您在帖子中提到过),将c 限制在[0, 400] 的范围内。你得到的参数是:

    a:   19.9999991
    b:   0.46769173
    c:   274.074071
    

    对应的情节如下:

    如您所见,模型对数据的再现合理,参数在给定范围内。

    下面是使用附加 cmets 重现结果的代码:

    from lmfit import minimize, Parameters, Parameter, report_fit
    import numpy as np
    
    x=[24,25,28,37,58,104,200,235,235]  
    y=[340,350,370,400,430,460,490,520,550]  
    
    
    def fit_fc(params, x, data):  
        a = params['a'].value
        b = params['b'].value
        c = params['c'].value
    
        model = np.power(x,b)*a + c
        return model - data #that's what you want to minimize
    
    # create a set of Parameters
    #'value' is the initial condition
    #'min' and 'max' define your boundaries
    params = Parameters()
    params.add('a', value= 2, min=0, max=20) 
    params.add('b', value= 0.5, min=0, max=20)
    params.add('c', value= 300.0, min=0, max=400) 
    
    # do fit, here with leastsq model
    result = minimize(fit_fc, params, args=(x, y))
    
    # calculate final result
    final = y + result.residual
    
    # write error report
    report_fit(params)
    
    #plot results
    try:
        import pylab
        pylab.plot(x, y, 'k+')
        pylab.plot(x, final, 'r')
        pylab.show()
    except:
        pass
    

    如果您将所有参数限制在[0,20] 范围内,则绘图看起来很糟糕:

    【讨论】:

      【解决方案2】:

      如果变量超出范围,这取决于您希望发生什么。您可以使用简单的if 语句(在本例中为程序exit()s):

      x = 21
      
      if (x not in range(0, 20)):
          print("var x is out of range")
          exit()
      

      另一种方法是assert 变量必须在范围内。在这种情况下,它被包裹在一个优雅地处理问题的try/except 块中,以及像上面一样的exit()s:

      try:
          assert(x in range(0, 20))
      except AssertionError:
          print("variable x is out of range")
          exit()
      

      【讨论】:

      • 感谢您的帮助,但它还没有解决我的问题。我希望程序用所选范围内的 a、b 和 c 来拟合数据的曲线。我希望程序始终从该范围内选择参数,没有任何例外,尽管使用超出范围的 a、b 或 c 可以实现更好的拟合。
      【解决方案3】:

      Scipy 使用无约束的最小二乘法来拟合曲线参数,因此不会那么简单:https://github.com/scipy/scipy/blob/v0.16.0/scipy/optimize/minpack.py#L454

      您可能想要做的就是所谓的受约束(非线性?,给出您想要拟合的)最小二乘问题。例如,看看这些讨论:

      【讨论】:

      • 看起来更像。谢谢,我得检查一下。
      猜你喜欢
      • 2013-05-08
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多