我有一个小的谱峰,我正在尝试使用高斯函数。我在网上搜索了一个例子,并将代码与我制作的代码混合在一起。
wveleng=[ 639.188 639.454 639.719 639.985 640.25 640.516 640.781 641.046
641.312 641.577]
counts=[ 778. 1613.8 12977.4 32990. 33165.2 13171. 2067.2 900.8
788.8 747.8]
我的第一个代码是以下
def gaus(x,a,mu,sigma):
return a*exp(-(x-mu)**2/(2*sigma**2))
a=ydata.max()
x0=ydata.mean()
sigm=ydata.std()
mean = sum(ydata*xdata)/len(ydata)
sigma = np.sqrt(sum(ydata*(xdata-mean)**2)/len(ydata))
#print(ydata.max())
popt, pcov = curve_fit(Gauss, xdata,ydata,maxfev=991,p0=[a,x0,sigm])
#gmodel = Model(Gauss)
#result = gmodel.fit(ydata, x=xdata, a=ydata.max(),x0=ydata.mean(),sigm=ydata.std())
print(popt)
#plt.scatter(xdata,ydata,label='data points')
#plt.plot(xdata, result.best_fit, 'r-')
#popt, pcov = curve_fit(gauss, xdata, ydata,p0=[ydata.max(), ydata.mean(), ydata.std()])
xx = np.linspace(639,642, 10)
plt.plot(xx, gauss(xdata, *popt), 'r-', label='fit')
有了情节,我得到以下内容。
我认为它与初始猜测参数有关
第二个代码,我发现它更紧凑,更适合我。
def gauss(x, a, x0, sigma):
return a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2))
ydata = np.array([778.,1613.8,12977.4,32990.,33165.2,13171.,2067.2,900.8,788.8,747.8])
xx = np.arange(639,642, 100)
xdata=np.array([639.188,639.454,639.719,639.985,640.250,640.516,640.781,641.046,641.312,641.577])
#plt.plot(xdata, ydata, 'bo', label='data')
def Gauss(x, a, x0, sigm):
return a * np.exp(-(x - x0)**2 / (2 * sigm**2))
gmodel = Model(Gauss)
result = gmodel.fit(ydata, x=xdata, a=ydata.max(),x0=ydata.mean(),sigm=ydata.std())
plt.scatter(xdata,ydata,label='data points')
plt.plot(xdata, result.best_fit, 'r-')
我与第一种方法完全一致。有没有比数据本身更适合的点
答案 0 :(得分:1)
quad(function, lower_bound, upper_bound)[0]
将为边界之间的函数的积分返回单个值。
OTOH,curve_fit(func, ...)
需要一个模型函数的值数组,它抱怨它有一个浮点数,而不是一个ndarray。
也许你打算做curve_fit(vfunc, ...)
?
你可能会发现lmfit(https://lmfit.github.io/lmfit-py/)很有用。它具有方便,高级的工具曲线拟合,并且内置了像高斯这样的简单模型函数。它还具有一个拟合模型的机制,该模型是两个函数的和或产品,甚至可以创建一个由两个函数的卷积。例如,请参阅https://lmfit.github.io/lmfit-py/model.html#composite-models-adding-or-multiplying-models中描述的示例。
答案 1 :(得分:1)
我认为你真的很亲密,但我不得不承认我不明白xx
的意思。您肯定希望数据适合(ydata
)和自变量(xdata
)长度相同。
我认为你现在遇到的主要问题是你最初的猜测不是很好,并且你会得到很好的结果
result = gmodel.fit(ydata, x=xdata, a=ydata.max(), x0=xdata.mean(), sigma=xdata.std())
(xdata
代替ydata
控制x0
和sigma
的初始值。
或许更好的方法是在参数值范围内添加一些健全性检查,就像
一样params = gmodel.make_params(a=ydata.max(),
x0=xdata.mean(),
sigma=xdata.std())
params['x0'].min = min(xdata)
params['x0'].max = max(xdata)
params['sigma'].max = 5
result = gmodel.fit(ydata, params, x=xdata)
最后,使用像GaussianModel这样的内置模型将报告sigma
和fwhm
以及amplitude
(即高斯的积分)和height
(高斯所需的最大值)。所以,这个脚本:
import numpy as np
from lmfit.models import GaussianModel
import matplotlib.pyplot as plt
ydata = np.array([778.,1613.8,12977.4,32990.,33165.2,13171.,2067.2,900.8,788.8,747.8])
xdata = np.array([639.188,639.454,639.719,639.985,640.250,640.516,640.781,641.046,641.312,641.577])
gmodel = GaussianModel()
params = gmodel.make_params(amplitude=ydata.max(),
center=xdata.mean(),
sigma=xdata.std())
result = gmodel.fit(ydata, params, x=xdata)
print(result.fit_report())
plt.scatter(xdata,ydata,label='data points')
plt.plot(xdata, result.best_fit, 'r-')
plt.show()
将打印出来
[[Model]]
Model(gaussian)
[[Fit Statistics]]
# function evals = 27
# data points = 10
# variables = 3
chi-square = 2360971.771
reduced chi-square = 337281.682
Akaike info crit = 129.720
Bayesian info crit = 130.628
[[Variables]]
sigma: 0.27525232 +/- 0.004505 (1.64%) (init= 0.7623906)
center: 640.119396 +/- 0.004490 (0.00%) (init= 640.3828)
amplitude: 25633.2702 +/- 362.5571 (1.41%) (init= 33165.2)
fwhm: 0.64816968 +/- 0.010608 (1.64%) == '2.3548200*sigma'
height: 37152.0777 +/- 525.0717 (1.41%) == '0.3989423*amplitude/max(1.e-15, sigma)'
[[Correlations]] (unreported correlations are < 0.100)
C(sigma, amplitude) = 0.579
并给出一个非常漂亮的合身。对于高级练习,我建议尝试添加ConstantModel()以提供背景偏移。好吧,收集更多数据点;)。