Python - Multipeak拟合 - 直方图

时间:2015-02-25 19:45:04

标签: python statistics histogram gaussian data-fitting

我想用高斯函数的总和来拟合我的数据,但程序不会收敛。我不知道这是代码还是数据的问题。

#My function: sum of two gaussian
def gauss2(x, *p):
    A, mu, sigma, A1, mu1, sigma1 = p                                    
    return (A / (math.sqrt(2 * math.pi) * sigma)) * np.exp(- (x - mu) ** 2 / (2. * sigma ** 2)) + (A1 / (math.sqrt(2 * math.pi) * sigma1)) * np.exp(- (x - mu1) ** 2 / (2. * sigma1 ** 2))

#Histogram
hist, bin_edges = np.histogram(data, density=True)
#I consider the center of each column of the histogram for the fit
bin_centres = (bin_edges[:-1] + bin_edges[1:]) / 2
#Guess
p0 = [2., 50.,0.05, 2., 52.,1.]
#Fit using curve_fit
coeff, var_matrix = curve_fit(gauss2, bin_centres, hist, p0=p0)

#For the plot
xx = []
ss = -14
prova2 = []
for i in range(10000):
    ss += 0.01
    xx.append(ss)

hist_fit = gauss2(xx, *coeff)
plt.plot(xx, hist_fit, 'b')

拟合的结果是:

1:[  1.45724361e+05   3.14206364e+03  -2.95328767e+02   8.89521631e-01
   5.20036421e+01   5.79493687e-01]!

我的数据将在50.5和52附近达到峰值。

是否有不同于'曲线拟合的程序'用于拟合函数?

2 个答案:

答案 0 :(得分:0)

这是EM算法的草图(伪代码,而不是真实代码)。您根本不需要直方图。

function M_step (x, responsibility, j)
  bump_mean[j] = sum (x[j]*responsibility[i, j], j, 1, n)
    where n = length(x)
  bump_mean_x2[j] = sum (x[j]**2 * responsibility[i, j], j, 1, n)
  bump_variance[j] = bump_mean_x2[j] - bump_mean[j]**2
  mixing_proportion[j] = sum (responsibility[i, j], j, 1, n)

function E_step (x, means, variances, mixing weights)
  responsibility[i, j] = p(bump i | x[j])
    for each bump i and datum x[j]

function EM (x)
  for many times:
    call E_step for data x and current parameter estimates
      to obtain responsibility values
    call M_step with responsibility values for each bump
      to update parameters

我省略了很多细节,而且我在记忆中工作,所以可能会有错误。但总结如下:E-step =估算每个基准的每个凸起的责任,然后M-step =估计凸起参数和混合权重给出的责任。 M步骤与使用加权数据计算均值和方差相同。

答案 1 :(得分:0)

我解决了最小化负对数似然函数的问题,如下面的伪代码:

#Gaussian function
def mygauss(x, *p):
    mu, sigma = p                                    
    return (1 / (math.sqrt(2 * math.pi) * sigma))  * np.exp(- (x - mu) ** 2 / (2. * sigma ** 2))

#Model to calculate the likelihood
def pdf_model(x, p):
    mu1, sig1= p
    return mygauss(x, mu1, sig1)

#Negative Log likelohood function
def log_likelihood_two_1d_gauss(p, sample):
    h = 0
    for x in sample:
        h = h + math.log(pdf_model(x, p))    
    return -h


from scipy.optimize import minimize
#Guess    
p0 = np.array([a,   b])
#My data
mydata = mydata

res = minimize(log_likelihood_two_1d_gauss, x0 = p0, args = (mydata,), method='nelder-mead')
print res.success
print res.message
print res.x