我有一条离散曲线y = f(x)。我知道峰的位置和幅度。我想通过在每个峰值处拟合高斯来近似曲线。我该如何寻找优化的高斯参数?我想知道是否有任何内置函数可以使我的任务更简单。
我有固定的高斯手段,并试图优化使用西格玛 lsqcurvefit()在matlab中。 MSE较少。但是,我有一个额外的硬约束,即近似曲线的值应该等于峰值处的原始函数。我的模型不满足此约束。我在这里粘贴当前的工作代码。我想有一个解决方案,它遵循峰值处的硬约束并且在其他点处大致适合曲线。基本思想是近似曲线具有较少的参数,但仍然与原始曲线非常相似。
fun = @(x,xdata)myFun(x,xdata,pks,locs); %pks,locs are the peak locations and amplitudes already available
x0=w(1:6)*0.25; % my initial guess based on domain knowledge
[sigma resnorm] = lsqcurvefit(fun,x0,xdata,ydata); %xdata and ydata are the original curve data points
recons = myFun(sigma,xdata,pks,locs);
figure;plot(ydata,'r');hold on;plot(recons);
function f=myFun(sigma,xdata,a,c)
% a is constant , c is mean of individual gaussians
f=zeros(size(xdata));
for i = 1:6 %use 6 gaussians to approximate function
f = f + a(i) * exp(-(xdata-c(i)).^2 ./ (2*sigma(i)^2));
end
end
答案 0 :(得分:2)
如果你知道你的峰值位置和幅度,那么你剩下要做的就是找到每个高斯的宽度。您可以将此视为优化问题。
假设您有x
和y
,这些是您想要近似的曲线的样本。
首先,定义一个函数g()
,它将构造给定宽度值的近似值。 g()
采用包含每个高斯宽度的参数向量sigma
。高斯人的位置和幅度将受限于您已知的值。 g()
输出x
中每个点的高斯近似值的值。
现在,定义一个损失函数L()
,它将sigma
作为输入。 L(sigma)
返回一个衡量错误的标量 - 给定近似值(使用sigma
)与您尝试近似的曲线有多差异。平方误差是曲线拟合的常见损失函数:
L(sigma) = sum((y - g(sigma)) .^ 2)
现在的任务是搜索sigma
的可能值,并找到最小化错误的选项。这可以使用各种优化程序来完成。
如果您拥有Mathworks优化工具箱,则可以使用函数lsqnonlin()
(在这种情况下,您不必自己定义L()
)。曲线拟合工具箱可能是另一种选择。否则,您可以使用开源优化例程(请查看cvxopt)。
有几点需要注意。您需要强制约束sigma
中的所有值都大于零。您可以告诉优化算法有关此约束。此外,您需要指定参数的初始猜测(即sigma
)。在这种情况下,你可以通过查看每个峰值附近的曲线来选择合理的东西。可能是这种情况(当损失函数是非凸的时)最终解决方案是不同的,这取决于初始猜测(即你收敛到局部最小值)。处理这种情况有许多奇特的技巧,但一件简单的事情就是尝试多种不同的初始猜测,并选择最佳结果。
编辑添加:
在python中,您可以在scipy.optimize
模块中使用优化例程,例如curve_fit()
。
编辑2(对已编辑问题的回复):
如果您的高斯彼此有很多重叠,那么取它们的总和可能会导致峰的高度与您的已知值不同。在这种情况下,您可以采用加权和,并将权重视为另一个要优化的参数。
如果希望峰值高度与某些指定值完全相等,则可以在优化问题中强制执行此约束。 lsqcurvefit()
无法做到这一点,因为它只处理参数的绑定约束。看看fmincon()
。
答案 1 :(得分:1)
您可以使用Expectation–Maximization algorithm在数据上拟合高斯混合。它不关心数据维度。
在MATLAB的文档中,您可以查找gmdistribution.fit
或fitgmdist
。