Python中的非线性最小二乘回归

时间:2019-12-03 16:28:57

标签: python

我必须按照公式为〜30个数据点计算非线性最小二乘回归

non-linear least-square formula

我尝试使用以下代码在scipy.optimize中尝试curve_fit函数

def func(x, p1 ,p2):
  return p1*x/(1-x/p2)

popt, pcov = curve_fit(func, CSV[:,1], CSV[:,0])

p1 = popt[0]
p2 = popt[1]

,p1和p2分别等于A和C,而CSV是我的数据数组。该函数运行时没有错误消息,但结果与预期不符。我已经绘制了函数的结果以及原始数据点。我本来不是想要得到这条几乎是直线的线(图中的红线),但是更接近绿线,这只是Excel的二阶多项式拟合。绿色虚线只是快速​​手动尝试以接近多项式拟合。

拟合函数的错误计算结果以及原始数据点:1

有人知道如何使计算按我的意愿运行吗?

2 个答案:

答案 0 :(得分:0)

您的代码很好。数据虽然不容易适应。图表右侧的点太少,左侧的噪声太大。这就是为什么curve_fit失败。 改善解决方案的一些方法可能是:

  • 提高curve_fit()的maxfev参数,请参见here
  • 将起始值提供给curve_fit()-参见same place
  • 添加更多数据点
  • 在该函数或其他函数中使用更多参数。

curve_fit()可能不是最强大的工具。看看是否可以使用其他回归类型的工具获得更好的结果。

以下是我可以从您的初始数据和公式中得到的最好的结果:

df = pd.read_csv("c:\\temp\\data.csv", header=None, dtype = 'float' )
df.columns = ('x','y')

def func(x,  p1 ,p2):
    return p1*x/(1-x/p2)

popt, pcov = curve_fit(func, df.x, df.y,  maxfev=3000)
print('p1,p2:',popt)
p1, p2 = popt

y_pred = [ p1*x/(1-x/p2)+p3*x for x in range (0, 140, 5)]
plt.scatter(df.x, df.y)
plt.scatter(range (0, 140, 5), y_pred)

plt.show()

p1,p2:[-8.60771432e + 02 1.08755430e-05]

enter image description here

答案 1 :(得分:0)

我认为我已经找到了使用lmfit软件包(https://lmfit.github.io/lmfit-py/v)解决此问题的最佳方法。当我尝试将非线性最小二乘回归拟合到Excel所提供的拟合函数而不是原始数据,而不是原始数据时,效果最好。(

from lmfit import Model
import matplotlib.pyplot as plt
import numpy as np

def func(x,  o1 ,o2):
    return o1*x/(1-x/o2) 

xt = np.arange(0, 0.12, 0.005)
yt = 2.2268*np.exp(40.755*xt)

model = Model(func)
result = model.fit(yt, x=xt, o1=210, o2=0.118)

print(result.fit_report())

plt.plot(xt, yt, 'bo')
plt.plot(xt, result.init_fit, 'k--', label='initial fit')
plt.plot(xt, result.best_fit, 'r-', label='best fit')
plt.legend(loc='best') 
plt.show

结果看起来非常好,而且程序包真的很容易使用(我省略了最后的情节)

[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 25
    # data points      = 24
    # variables        = 2
    chi-square         = 862.285318
    reduced chi-square = 39.1947872
    Akaike info crit   = 89.9567771
    Bayesian info crit = 92.3128848
[[Variables]]
    o1:  310.243771 +/- 12.7126811 (4.10%) (init = 210)
    o2:  0.13403974 +/- 0.00120453 (0.90%) (init = 0.118)
[[Correlations]] (unreported correlations are < 0.100)
    C(o1, o2) =  0.930