Python optimize.curve_fit(关于现有答案)

1 投票
1 回答
1635 浏览
提问于 2025-04-17 15:14

我想问一个关于用户回复其他问题的事情,但不知道为什么评论框没有显示出来。如果我做错了什么,真是抱歉。

无论如何,关于这个回复:

https://stackoverflow.com/a/11507723/1950164

我有一个问题:我该如何使用这段代码来将不同的数据拟合到不同的函数上?我遇到的问题和他解决的类似,只不过我想拟合的是累积分布。所以我开始尝试将代码进行一些通用化。我做了三个修改:

a) 在计算直方图的那一行之后,我添加了:

hist = numpy.cumsum(hist)

这将我们的分布转换为累积分布。

b) 我没有使用示例中的高斯函数,而是定义了一个新函数:

def myerf(x, *p):
    A, mu, sigma = p
    return A/2. * (1+math.erf((x-mu)/(math.sqrt(2)*sigma)))

这应该是高斯的累积分布。

c) 最后,当然,我把curve_fit那一行改成调用我的函数:

coeff, var_matrix = curve_fit(myerf, bin_centres, hist, p0=p0)

这应该是个简单的练习,但它却不工作。程序现在返回了以下错误信息:

bash-3.2$ python fitting.py
Traceback (most recent call last):
  File "fitting.py", line 27, in <module>
    coeff, var_matrix = curve_fit(myerf, bin_centres, hist, p0=p0)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 506, in curve_fit
    res = leastsq(func, p0, args=args, full_output=1, **kw)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 348, in leastsq
    m = _check_func('leastsq', 'func', func, x0, args, n)[0]
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 14, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 418, in _general_function
    return function(xdata, *params) - ydata
  File "fitting.py", line 22, in myerf
    return A/2. * (1+math.erf((x-mu)/(math.sqrt(2)*sigma)))
TypeError: only length-1 arrays can be converted to Python scalars

那我到底做错了什么呢?

附加问题:给我一个参考,解释一下函数参数中的那个*p是什么。

谢谢!

编辑:我尝试用累积分布数据运行程序,但仍然调用高斯函数。这样是可以的,只是拟合效果不好。所以错误应该出在我的myerf函数里。

编辑2:如果我尝试用更简单的东西替代myerf函数的返回值,比如:

return A + mu*x + sigma*x**2

那么它就能工作。所以返回值里一定有某些东西没有按预期工作。

编辑3:所以,我尝试用scipy中的误差函数代替math中的那个,结果现在可以了。我不知道之前为什么不行,但现在可以了。所以代码是:

import matplotlib
matplotlib.use('Agg')
import numpy, math
import pylab as pl
from scipy.optimize import curve_fit
from scipy.special import erf

# Define some test data which is close to Gaussian
data = numpy.random.normal(size=10000)

hist, bin_edges = numpy.histogram(data, density=True)
bin_centres = (bin_edges[:-1] + bin_edges[1:])/2
hist = numpy.cumsum(hist)

def myerf(x, *p):
    A, mu, sigma = p
    return A/2. * (  1+erf(((x-mu)/(math.sqrt(2)*sigma)))  )

# p0 is the initial guess for the fitting coefficients (A, mu and sigma above)
p0 = [1., 0., 1.]

coeff, var_matrix = curve_fit(myerf, bin_centres, hist, p0=p0)

# Get the fitted curve
hist_fit = myerf(bin_centres, *coeff)

pl.plot(bin_centres, hist, label='Test data')
pl.plot(bin_centres, hist_fit, label='Fitted data')

# Finally, lets get the fitting parameters, i.e. the mean and standard deviation:
print 'Fitted mean = ', coeff[1]
print 'Fitted standard deviation = ', coeff[2]

pl.savefig('fitting.png')
pl.show()

1 个回答

0

math库的函数不同,numpy库的函数可以接受向量作为输入:

>>> import numpy, math
>>> numpy.exp([4,5])
array([  54.59815003,  148.4131591 ])
>>> math.exp([4,5])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: a float is required

撰写回答