【问题标题】:Curve fit data issues曲线拟合数据问题
【发布时间】:2016-03-09 04:00:46
【问题描述】:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

xdata = np.array([177,180,183,187,189,190,196,197,201,202,203,204,206,218,225,231,234,
      252,262,266,267,268,277,286,303])

ydata = np.array([0.81,0.74,0.78,0.75,0.77,0.81,0.73,0.76,0.71,0.74,0.81,0.71,0.74,0.71,
      0.72,0.69,0.75,0.59,0.61,0.63,0.64,0.63,0.35,0.27,0.26])



def f(x, n1, n2, n3, n4, n5):
    if (n1 > 0.2 and n1 < 0.8 and
        n2 > -0.3 and n2 < 0):
        return n1 + (n2 * x + n3) * 1./ (1 + np.exp(n4 * (n5 - x)))
    return 1e38

coeffs, pcov = curve_fit(f, xdata, ydata, p0 = (0.29, -0.005, 1.0766, -0.36397, 104))

ploty = f(xdata, coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4])
for i in range(1, len(coeffs) + 1):
    print ('n%s = %s' % (i, coeffs[i - 1])) 

无法正常工作并出现以下警告:

OptimizeWarning: Covariance of the parameters could not be estimated
  category=OptimizeWarning)

但对

正常工作
xdata = np.array([73.0, 80.0, 88.0, 93.8, 96.3, 98.5, 100.0, 101.0, 102.3,  104.0, 105.3,
                 107.0, 109.5, 111.5, 114.0, 117.0, 119.5, 121.0, 124.0])
 ydata = np.array([0.725, 0.7, 0.66, 0.63, 0.615, 0.61, 0.59, 0.56, 0.53, 0.49, 0.45, 
                   0.41, 0.35, 0.32, 0.3, 0.29, 0.29, 0.29, 0.29])

Lmfit 也不起作用。

【问题讨论】:

标签: python numpy scipy curve-fitting lmfit


【解决方案1】:

由于您还使用了lmfit 作为标签,这里有一个使用lmfit 的解决方案。获取的参数值如下:

n1:   0.26564921 +/- 0.024765 (9.32%) (init= 0.2)
n2:  -0.00195398 +/- 0.000311 (15.93%) (init=-0.005)
n3:   0.87261892 +/- 0.068601 (7.86%) (init= 1.0766)
n4:  -1.43507072 +/- 1.223086 (85.23%) (init=-0.36379)
n5:   277.684530 +/- 3.768676 (1.36%) (init= 274)

产生以下输出:

如您所见,拟合很好地再现了数据,并且参数在要求的范围内;您的函数中不需要 if 语句。

这是用一些额外的 cmets 重现该图的完整代码:

from lmfit import minimize, Parameters, Parameter, report_fit
import numpy as np

xdata = np.array([177.,180.,183.,187.,189.,190.,196.,197.,201.,202.,203.,204.,206.,218.,225.,231.,234.,
      252.,262.,266.,267.,268.,277.,286.,303.])

ydata = np.array([0.81,0.74,0.78,0.75,0.77,0.81,0.73,0.76,0.71,0.74,0.81,0.71,0.74,0.71,
      0.72,0.69,0.75,0.59,0.61,0.63,0.64,0.63,0.35,0.27,0.26])

def fit_fc(params, x, data):
    n1 = params['n1'].value
    n2 = params['n2'].value
    n3 = params['n3'].value
    n4 = params['n4'].value
    n5 = params['n5'].value

    model = n1 + (n2 * x + n3) * 1./ (1. + np.exp(n4 * (n5 - x)))

    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('n1', value= 0.2, min=0.2, max=0.8)
params.add('n2', value= -0.005, min=-0.3, max=10**(-10))
params.add('n3', value= 1.0766, min=-1000., max=1000.)
params.add('n4', value= -0.36379, min=-1000., max=1000.)
params.add('n5', value= 274.0, min=0., max=1000.)

# do fit, here with leastsq model
result = minimize(fit_fc, params, args=(xdata, ydata))

# write error report
report_fit(params)

xplot = np.linspace(min(xdata), max(xdata), 1000)
yplot = result.values['n1'] + (result.values['n2'] * xplot + result.values['n3']) * \
                              1./ (1. + np.exp(result.values['n4'] * (result.values['n5'] - xplot)))
#plot results
try:
    import pylab
    pylab.plot(xdata, ydata, 'k+')
    pylab.plot(xplot, yplot, 'r')
    pylab.show()
except:
    pass

编辑:

事实证明,这只适用于 0.8.3 版本。如果您使用 0.9.x 版本,您需要相应地调整您的代码;检查 here 从 0.8.3 到 0.9.x 进行了哪些更改。

【讨论】:

  • 奇怪,lmfit 似乎真的不喜欢你 :( 上面的代码对我来说运行良好;但我不知道为什么你没有得到任何输出。你是否采用完全相同的代码和我一样;您使用的是哪个版本的 lmfit(我使用的是 0.8.3)?
  • 我在 0.9.2 版本中将 result.values['ni'] 替换为 result.params['n4'].value 并在其他版本的 lmfit 中使用完全相同的代码。来自官方网站的代码可以正常工作。
  • 好的,这应该对结果没有任何影响。抱歉,不知道你的实现出了什么问题;对我来说效果很好。您可以尝试 0.8.3 并检查它是否有效。您也可以尝试改变起始值,因为这个问题对于初始猜测非常敏感。
  • 我不知道我们有不同版本的 lmfit。我不得不在 0.9.2 中寻找一些变化的想法结果证明是个好主意。在 0.9.2 版本中,params 不会因合身而改变。我需要使用result.params 而不是params
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 2016-08-20
  • 1970-01-01
  • 2020-03-06
  • 2010-10-09
相关资源
最近更新 更多