计算两个叠加高斯函数的质心

4

我正在尝试找到以下问题的解决方案:我有一组点应该模拟分布在不同点上的两个高斯函数之和。我需要找到这两个点。目前我的方法是找出整个集合的质心,然后将数据分成低于和高于质心的两部分。然后我计算每个部分的质心,这些就是我的中心点。然而,这种方法砍掉了左侧高斯泄漏到数据右半部分的信息,因此当高斯函数靠得很近时,该过程会失败。有没有更智能的方法?由于计算的难度,我希望解决方案不涉及曲线拟合。


我有一个Python示例,用遗传算法将两个洛伦兹峰拟合到碳纳米管的拉曼光谱中,以自动提供初始参数估计。在这里,你可以用自己的数据和方程式替换它,可能会很容易地运行起来:https://bitbucket.org/zunzuncode/RamanSpectroscopyFit - James Phillips
对于在FFT中找到频率,有一种使用高斯窗口函数的方法。在对数尺度上,您可以从两个连续的bin计算中心。但是,这仅适用于单峰情况,如果接近最大值,则效果更好。您可以尝试更远离峰值。但是,如果两个高斯函数混合强烈,则很难看出如何避免拟合。不过我认为计算上没有困难。 - mikuszefski
2
这是一个高斯混合模型。寻找这种模型参数的传统方法是所谓的期望最大化算法,它只是你已经掌握的切割和拟合过程的一般化。在网络上搜索“高斯混合期望最大化”应该会找到很多资源。许多编程语言中都有实现此算法的软件包。 - Robert Dodier
1个回答

0

由于OP没有展示任何数据,因此不清楚数据有多嘈杂。此外,在这里“紧密在一起”是如何定义的也不清楚。接下来我有一个简单的近似方法,适用于低噪声和左侧数据由左高斯主导,右侧数据由右高斯主导的假设。这对位置、高度和特别是标准差有一些限制。

它肯定适用于单个峰值,但对于混合双峰也相当不错(在上述限制范围内)

#!/usr/bin/python
import matplotlib.pyplot as plt
import numpy as np

def gaussian( x, x0, s, a):
    return a * np.exp( -( x - x0 )**2 / ( 2 * s**2 ) ) / np.sqrt( 2 * np.pi * s**2 )

def get_x0( x1, x2, x3, y1, y2, y3 ):
    l12= np.log( y1 / y2 )
    l13= np.log( y1 / y3 )
    return ( ( x2 + x1 )/2. - ( x3 + x1 )/2. * l12/l13 * ( x3 - x1 ) / ( x2 - x1 ) ) / ( 1 - l12 / l13 * (x3 - x1 ) / ( x2 - x1 ) )


fig = plt.figure( )
ax = fig.add_subplot( 2, 1, 1 )

xL = np.linspace(-8, 8, 150 )
yL = np.fromiter( ( gaussian( x,-2.1, 1.2, 8 ) for x in xL ), np.float )
marker=[10,15,20]

x1 = xL[ marker[0] ]
x2 = xL[ marker[1] ]
x3 = xL[ marker[2] ]
y1 = yL[ marker[0] ]
y2 = yL[ marker[1] ]
y3 = yL[ marker[2] ]

print get_x0( x1, x2, x3, y1, y2, y3 )

ax.plot( xL, yL )
ax.scatter( [ x1, x2, x3 ],[ y1, y2, y3 ])

bx = fig.add_subplot( 2, 1, 2 )
yL = np.fromiter( ( gaussian( x,-2.1, 1.2, 8) + gaussian( x,0.7, 1.4, 6 ) for x in xL ), np.float )
marker=[10,15,20]
x1 = xL[ marker[0] ]
x2 = xL[ marker[1] ]
x3 = xL[ marker[2] ]
y1 = yL[ marker[0] ]
y2 = yL[ marker[1] ]
y3 = yL[ marker[2] ]
bx.scatter( [ x1, x2, x3 ],[ y1, y2, y3 ])
print get_x0( x1, x2, x3, y1, y2, y3 )
marker=[-20,-25,-30]
x1 = xL[ marker[0] ]
x2 = xL[ marker[1] ]
x3 = xL[ marker[2] ]
y1 = yL[ marker[0] ]
y2 = yL[ marker[1] ]
y3 = yL[ marker[2] ]
bx.scatter( [ x1, x2, x3 ],[ y1, y2, y3 ])
print get_x0( x1, x2, x3, y1, y2, y3 )
bx.plot( xL, yL )

plt.show() 

显示:

#Single
-2.0999999999999455
#Double
-2.0951188129317813
0.6998760921436634

这相当接近于-2.10.7

gaussians

在出现噪音的情况下,可能需要进行一些平均处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接