使用来自scipy和python 3.x的*** curve_fit ***改进高斯拟合

时间:2017-10-21 00:08:28

标签: python-3.x scipy

我相信我使用scipy的曲线拟合成功实现了高斯拟合。但我遇到的问题是......合适性不是很大,因为优化的参数正在改变质心。

    data =np.loadtxt('mock.txt')
    my_x=data[:,0]
    my_y=data[:,1]

    def gauss(x,mu,sigma,A):
        return A*np.exp(-(x-mu)**2/2/sigma**2)
    def trimodal_gauss(x,mu1,sigma1,A1,mu2,sigma2,A2,mu3,sigma3,A3):
        return gauss(x,mu1,sigma1,A1)+gauss(x,mu2,sigma2,A2)+gauss(x,mu3,sigma3,A3)



    """""
    Gaussian fitting parameters recognized in each file
    """""
    first_centroid=(10180.4*2+9)/9
    second_centroid=(10180.4*2+(58.6934*1)+7)/9
    third_centroid=(10180.4*2+(58.6934*2)+5)/9
    centroid=[]
    centroid+=(first_centroid,second_centroid,third_centroid)

    apparent_resolving_power=1200
    sigma=[]
    for i in range(len(centroid)):
        sigma.append(centroid[i]/((apparent_resolving_power)*2.355))

    height=[1,1,1]

    p=[]    

    p = np.array([list(t) for t in zip(centroid, sigma, height)]).flatten() 


    popt, pcov = curve_fit(trimodal_gauss,my_x,my_y,p0=p) 

输出:enter image description here

我知道这里有很多高峰,但我真的需要它只适合三个高斯但是在正确的质心(在我最初的猜测中给出)。换句话说,我真的不希望我给出的质心不会改变。有没有人遇到这样的挑战?我能帮助我做些什么来实现它吗?

2 个答案:

答案 0 :(得分:0)

您应该为中心定义三个具有固定值的单独函数。然后,只为剩余参数拟合这些函数的和函数。

简而言之,您的trimodal_gauss()不应该mu而只能Asigmamu应该是常量。

这样做的一个微不足道的(但不是很一般的)方法是:

def trimodal_gauss(x, sigma1, A1, sigma2, A2, sigma3, A3):
    mu1 = 1234 # put your mu's here
    mu2 = 2345
    mu3 = 3456
    g1 = gauss(x, mu1, sigma1, A1)
    g2 = gauss(x, mu2, sigma2, A2)
    g3 = gauss(x, mu3, sigma3, A3)
    return g1 + g2 + g3

从这一点可以通过"生成器来概括这个想法"对于trimodal_gauss函数,它取三个(或n?)mu s并创建其他参数的函数。像这样:

def make_trimodal_gauss(mu1, mu2, mu3):
    def result_function(x, sigma1, A1, sigma2, A2, sigma3, A3):
        g1 = gauss(x, mu1, sigma1, A1)
        g2 = gauss(x, mu2, sigma2, A2)
        g3 = gauss(x, mu3, sigma3, A3)
        return g1 + g2 + g3
    return result_function


mu1 = 1234 # put your mu's here
mu2 = 2345
mu3 = 3456

trimodal_gauss = make_trimodal_gauss(mu1, mu2, mu3)

#usage like this: trimodal_gauss(x, sigma1, A1, sigma2, A2, sigma3, A3)

答案 1 :(得分:-1)

如果使用lmfit模块(https://github.com/lmfit/lmfit-py),您可以轻松地将边界放在高斯函数的质心上,甚至可以修复它们。 Lmfit还可以轻松构建多峰模型。

您没有提供完整的示例或链接到您的数据,但适合您的数据的lmfit可能如下所示:

import numpy as np
from lmfit import GaussianModel
data =np.loadtxt('mock.txt')
my_x=data[:,0]
my_y=data[:,1]

model = ( GaussianModel(prefix='p1_') +
          GaussianModel(prefix='p2_') +
          GaussianModel(prefix='p3_') )

params = model.make_params(p1_amplitude=100, p1_sigma=2, p1_center=2262,
                           p2_amplitude=100, p2_sigma=2, p2_center=2269,
                           p3_amplitude=100, p3_sigma=2, p3_center=2276,
                       )

# set boundaries on the Gaussian Centers:
params['p1_center'].min = 2260
params['p1_center'].max = 2264

params['p2_center'].min = 2267
params['p2_center'].max = 2273

params['p3_center'].min = 2274
params['p3_center'].max = 2279

# or you could just fix one of the centroids like this:
params['p3_center'].vary = False

# if needed, you could force all the sigmas to be the same value
# or related by simple mathematical expressions
params['p2_sigma'].expr = 'p1_sigma'
params['p3_sigma'].expr = '2*p1_sigma'

# fit this model to data:
result  = model.fit(my_y, params, x=my_x)

# print results
print(result.fit_report())

# evaluate individual gaussian components:
peaks = model.eval_components(params=result.params, x=my_x)

# plot results:
plt.plot(my_x, my_y, label='data')
plt.plot(my_x, result.best_fit, label='best fit')
plt.plot(my_x, peaks['p1_'])
plt.plot(my_x, peaks['p2_'])
plt.plot(my_x, peaks['p3_'])
plt.show()