简体   繁体   English

如何使用线性最小二乘拟合拟合两个重叠的高斯?

[英]How can I fit two overlapping gaussians using linear least squares fitting?

First off, I created a jupyter notebook to show the code properly. 首先,我创建了一个jupyter笔记本来正确显示代码。 Please take a look . 请看一下 Second, I'm using linear least squares fitting rather than non-linear least squares fitting for speed. 其次,我使用线性最小二乘拟合而不是非线性最小二乘拟合速度。 The problem I'm trying to solves involves fitting a large number of gaussians on a spectrum image for electron microscopy, and our current nlls algorithm is slow. 我试图解决的问题涉及在电子显微镜的光谱图像上拟合大量的高斯,我们当前的nlls算法很慢。 It requires fitting within bounds, which is why we are not using numpy.linalg.lstsq 它需要在边界内拟合,这就是我们不使用numpy.linalg.lstsq

I'm trying to use scipy.optimize.lsq_linear to do a simple fit of two gaussian components ( g1 and g2 ) with fixed sigma and centre components, to a 2D array G that is a list of different mixes of those two gaussians. 我正在尝试使用scipy.optimize.lsq_linear将两个高斯组件( g1g2 )与固定的sigma和中心组件简单地拟合到一个2D阵列G ,这是两个高斯的不同混合列表。

First off, defining the gaussian: 首先,定义高斯:

def gaussian(x, mu, sig):
    return np.exp(-np.power(x - mu, 2.) / (2 * np.power(sig, 2.)))

Then creating the components: 然后创建组件:

x = np.linspace(-3, 3, 100)
g1 = gaussian(x, -0.5, 0.5)
g2 = gaussian(x, 0.5, 0.5)

And then creating two sets of data to fit to by mixing the components: 然后通过混合组件创建两组数据以适应:

G1 = 5*g1 + 8*g2
G2 = 2*g1 + 2*g2
G = np.stack([G1,G2]).T 

I take the transpose of the stack because the lsq_linear function requires the data to be of shape (m, n) where (m,) is the shape of the component to be fit. 我采用堆栈的转置,因为lsq_linear函数要求数据具有形状(m, n) ,其中(m,)是要拟合的组件的形状。

I fit the components one by one through 我逐个适应组件

g1_res = lsq_linear(G, g1)
g2_res = lsq_linear(G, g2)

which should give me the weight of the component for each mix in g1_res["x"] in the documentation . 这应该给我文档g1_res["x"]中每个混合的组件的权重。 Multiplying the weights with the components returns: 将权重与组件相乘会返回:

g1_fit = [g1*fit for fit in g1_res["x"]]
g2_fit = [g2*fit for fit in g2_res["x"]]

However, the fit (first mix is shown below) is incorrect. 但是,拟合(第一个混合如下所示)不正确。 Can someone help me figure out what I'm doing wrong? 有人能帮助我弄清楚我做错了什么吗?

plt.plot(x,G.T[0], label="mixed_signal")
plt.plot(x,g1_fit[0], label="gaussian 1")
plt.plot(x,g2_fit[0], label="gaussian 2")
plt.legend()

适合高斯人的数据

You mixed something up. 你混淆了什么。 You are fitting all measured spectra using 1 component. 您使用1个组件拟合所有测量的光谱。 Instead, you want to fit each spectrum using both components. 相反,您希望使用两个组件来拟合每个光谱。 Therefore, the things need to be swapped: 因此,需要交换的东西:

g = np.stack([g1,g2]).T

g1_res = lsq_linear(g, G1)
g2_res = lsq_linear(g, G2)



g1_res["x"]
# --> array([ 5.,  8.])
g2_res["x"]
# --> array([ 2.,  2.])

By the way, if you have many spectra and the shape parameters of the gaussian (as given here [+-0.5,0.5]) are always the same but not known or the shape is the same but does not even correspond ideally to gaussian, then you might want to try Principal Component Analysis. 顺便说一下,如果你有很多光谱,高斯的形状参数(这里给出[+ -0.5,0.5])总是相同但不知道或者形状相同但理想上与高斯不相符,那么您可能想尝试主成分分析。 There are already Python packages for it. 已有Python包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM