且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将多个高斯拟合到python中的数据

更新时间:2022-03-17 03:50:04

这需要非线性拟合.一个很好的工具是 scipy 的 curve_fit 函数.

This requires a non-linear fit. A good tool for this is scipy's curve_fit function.

要使用 curve_fit,我们需要一个模型函数,称为 func,它接受 x 和我们的(猜测的)参数作为参数和返回 y 的相应值.作为我们的模型,我们使用高斯总和:

To use curve_fit, we need a model function, call it func, that takes x and our (guessed) parameters as arguments and returns the corresponding values for y. As our model, we use a sum of gaussians:

from scipy.optimize import curve_fit
import numpy as np

def func(x, *params):
    y = np.zeros_like(x)
    for i in range(0, len(params), 3):
        ctr = params[i]
        amp = params[i+1]
        wid = params[i+2]
        y = y + amp * np.exp( -((x - ctr)/wid)**2)
    return y

现在,让我们为我们的参数创建一个初始猜测.这个猜测从 x=0x=1,000 处的峰值开始,振幅为 60,000,e 折叠宽度为 80.然后,我们在 x= 处添加候选峰值60, 140, 220, ... 幅度为 46,000,宽度为 25:

Now, let's create an initial guess for our parameters. This guess starts with peaks at x=0 and x=1,000 with amplitude 60,000 and e-folding widths of 80. Then, we add candidate peaks at x=60, 140, 220, ... with amplitude 46,000 and width of 25:

guess = [0, 60000, 80, 1000, 60000, 80]
for i in range(12):
    guess += [60+80*i, 46000, 25]

现在,我们准备执行拟合:

Now, we are ready to perform the fit:

popt, pcov = curve_fit(func, x, y, p0=guess)
fit = func(x, *popt)

为了看看我们做得有多好,让我们绘制实际的 y 值(黑色实线曲线)和 fit(红色虚线曲线)相对于 x的图代码>:

To see how well we did, let's plot the actual y values (solid black curve) and the fit (dashed red curve) against x:

如您所见,合身度相当不错.

As you can see, the fit is fairly good.

from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt('data.txt', delimiter=',')
x, y = data

plt.plot(x,y)
plt.show()

def func(x, *params):
    y = np.zeros_like(x)
    for i in range(0, len(params), 3):
        ctr = params[i]
        amp = params[i+1]
        wid = params[i+2]
        y = y + amp * np.exp( -((x - ctr)/wid)**2)
    return y

guess = [0, 60000, 80, 1000, 60000, 80]
for i in range(12):
    guess += [60+80*i, 46000, 25]   

popt, pcov = curve_fit(func, x, y, p0=guess)
print popt
fit = func(x, *popt)

plt.plot(x, y)
plt.plot(x, fit , 'r-')
plt.show()