2

这是我的代码(这是一段较大代码的示例):

from scipy.optimize import curve_fit

def func(x, a, b):
   return a + b*x

xlist = [10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 230]
ylist = [0.0074999999999999997, 0.011875, 0.0057812499999999999, 0.0036458333333333334, 0.0020312500000000001, 0.0013125000000000001, 0.00098958333333333342, 0.00089285714285714283, 0.00074218750000000001, 0.00093749999999999997, 0.00071874999999999999, 0.00088068181818181821]

popt, pcov = curve_fit(func, xlist, ylist)

print(popt[0], popt[1])

如您所见,我正在尝试使用非常简单的a + b*x功能进行非常简单的拟合。问题是这会返回值:

(-119.99689110581872, 1.0)

对于a=popt[0]b=popt[1]但与 zunzun.com 相同的拟合给出了更合理的值:

a = 7.8372289537296004E-03
b = -3.9402329475524466E-05

对于完全相同的功能。

我在这里做错了什么?


编辑

下面的沃伦说这可能是一个错误。我应该这样报告还是这是预期的行为?

4

2 回答 2

3

如果将值更改xlist为 numpy 数组,它会起作用:

In [38]: popt, pcov = curve_fit(func, array(xlist, dtype=float), ylist)

In [39]: popt
Out[39]: array([  7.83722896e-03,  -3.94023294e-05])

起初这看起来像一个错误,但实际情况是底层代码接受参数xdata并将其原封不动地传递给您的函数。在您的示例中,这意味着在表达式a + b*x中,x是一个 Python 列表。 意味着b*x没有进行您想要的计算。

因此,要定义func工作,参数xdata必须是一个 numpy 数组。或者,您可以这样定义func

def func(x, a, b):
    return a + b*np.asarray(x)
于 2013-06-04T23:47:05.950 回答
2

如果我没记错的话,scipy 曲线拟合例程的默认初始参数都是 1.0。虽然这适用于直线等简单情况 - 因为直线曲线拟合的误差空间更简单 - 如果您尝试拟合误差空间“崎岖不平”的地方,您可能会再次看到您的结果与 zunzun 的结果之间的差异.com。

如果您对应该存在最佳解决方案的正确值(或值范围)有所了解,那么使用这些值启动 scipy 例程几乎在所有情况下都会比从所有值开始提供更好的结果。

虽然 zunzun.com 允许输入初始参数“估计值”或猜测值,但网站不需要这些参数,因为使用遗传算法来确定初始参数估计值。zunzun.com 网站的 BSD 许可 Python 拟合源代码位于

http://code.google.com/p/pyeq2/

它附带了非常广泛的示例。查看 zunzun.com 网页底部的代码链接。如果您有任何问题,请告诉我,我很乐意为您提供帮助。

詹姆斯·菲利普斯 zunzun@zunzun.com

于 2013-06-05T13:47:35.077 回答