在Python中拟合高斯曲线到数据
我正在尝试将一个高斯曲线拟合到一些给定的数据上。这是我目前的进展:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# Generate data
mu, sigma = 0, 0.1
y, xe = np.histogram(np.random.normal(mu, sigma, 1000))
x = .5 * (xe[:-1] + xe[1:])
def gauss (x, y):
p = [x0, y0, sigma]
return p[0] * np.exp(-(x-p[1])**2 / (2 * p[2]**2))
p0 = [1., 1., 1.]
fit = curve_fit(gauss, x, y, p0=p0)
plt.plot(gauss(x, y))
plt.show()
当我运行代码时,出现了这个错误:
TypeError: gauss() takes exactly 2 arguments (4 given)
我不明白我在哪里给了我的函数4个参数。我也不太确定我是否正确使用了曲线函数,但我不太清楚自己到底哪里出错了。任何帮助都将不胜感激。
编辑
这是错误追踪信息:
Traceback (most recent call last):
File "F:\Numerical methods\rw893 final assignment.py", line 21, in <module>
fitE, fitI = curve_fit(gauss, x, y, p0=p0)
File "F:\Portable Python 2.7.5.1\App\lib\site-packages\scipy\optimize\minpack.py", line 515, in curve_fit
res = leastsq(func, p0, args=args, full_output=1, **kw)
File "F:\Portable Python 2.7.5.1\App\lib\site-packages\scipy\optimize\minpack.py", line 354, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "F:\Portable Python 2.7.5.1\App\lib\site-packages\scipy\optimize\minpack.py", line 17, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "F:\Portable Python 2.7.5.1\App\lib\site-packages\scipy\optimize\minpack.py", line 427, in _general_function
return function(xdata, *params) - ydata
TypeError: gauss() takes exactly 2 arguments (4 given)
3 个回答
from numpy import loadtxt
import numpy as np
from scipy import *
from matplotlib import *
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, a, b, c, d, x0):
return a*np.exp(-(x-x0)**2/(2*d**2)) + c
x = np.linspace(0,4,50)
y = func(x, 2.5, 1.3, 0.5, 1.0, 2.0)
yn = y + 0.2*np.random.normal(size=len(x))
p = [1,1,1,1,1]
popt, pcov = curve_fit(func, x, yn, p0=p)
plt.plot(x,func(x,popt[0],popt[1],popt[2],popt[3],popt[4]))
plt.plot(x,yn,'r+')
plt.show()
这应该能帮到你。这个方法也可以扩展到三维高斯分布,这样输入的数组 'x' 就应该是一个 k 维数组,用来表示 (x,y) 的值,而 'yn' 则是 z 值。
查看一下最初的 scipy 文档 docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.optimize.curve_fit.html:
scipy.optimize.curve_fit
scipy.optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, **kw)
Use non-linear least squares to fit a function, f, to data. Assumes ydata = f(xdata, *params) + eps
解释一下这个概念
你要拟合的函数应该只接受标量(不是: *p0
)。我想提醒你,在调用 curve_fit
的时候,你需要把初始化参数 x0
、y0
和 sigma
传给函数 gauss
。你可以把初始化参数写成 p0 = [x0, y0, sigma]
。
函数 gauss
返回的值是 y = y0 * np.exp(-((x - x0) / sigma)**2)
。所以输入的值需要是 x
、x0
、y0
和 sigma
。第一个参数 x
是你已知的数据,和函数的结果 y
一起使用。后面三个参数是需要拟合的,你把它们作为初始化参数传入。
工作示例
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# Create data:
x0, sigma = 0, 0.1
y, xe = np.histogram(np.random.normal(x0, sigma, 1000))
x = .5 * (xe[:-1] + xe[1:])
# Function to be fitted
def gauss(x, x0, y0, sigma):
p = [x0, y0, sigma]
return p[1]* np.exp(-((x-p[0])/p[2])**2)
# Initialization parameters
p0 = [1., 1., 1.]
# Fit the data with the function
fit, tmp = curve_fit(gauss, x, y, p0=p0)
# Plot the results
plt.title('Fit parameters:\n x0=%.2e y0=%.2e sigma=%.2e' % (fit[0], fit[1], fit[2]))
# Data
plt.plot(x, y, 'r--')
# Fitted function
x_fine = np.linspace(xe[0], xe[-1], 100)
plt.plot(x_fine, gauss(x_fine, fit[0], fit[1], fit[2]), 'b-')
plt.savefig('Gaussian_fit.png')
plt.show()
可能你的回调函数在 curve_fit
中被调用时,参数的数量不对。你可以看看这个文档,里面提到:
模型函数,f(x, ...)。它必须把自变量作为第一个参数,剩下的参数要单独传入。
为了确保这个能正常工作,你可以在第一个参数后面加上 *args
,然后看看你得到了什么。