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