我有一条离散曲线y = f(x) . 我知道峰的位置和幅度 . 我想通过在每个峰值处拟合高斯来近似曲线 . 我该如何寻找优化的高斯参数?我想知道是否有任何内置函数可以使我的任务更简单 .
编辑
我有固定的高斯平均值,并试图在matlab中使用lsqcurvefit()来优化sigma . 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
2 回答
如果你知道你的峰值位置和幅度,那么你剩下要做的就是找到每个高斯的宽度 . 您可以将此视为优化问题 .
假设您有
x
和y
,它们是您想要近似的曲线的样本 .首先,定义一个函数
g()
,它将构造给定宽度值的近似值 .g()
采用包含每个高斯宽度的参数向量sigma
. 高斯人的位置和幅度将受限于您已知的值 .g()
输出x
中每个点的高斯近似值的值 .现在,定义一个损失函数
L()
,它将sigma
作为输入 .L(sigma)
返回一个衡量误差的标量 - 给定近似值(使用sigma
)与您尝试逼近的曲线有多么不同 . 平方误差是曲线拟合的常见损失函数:现在的任务是搜索
sigma
的可能值,并找到最小化错误的选项 . 这可以使用各种优化例程来完成 .如果您有Mathworks优化工具箱,则可以使用函数
lsqnonlin()
(在这种情况下,您不必自己定义L()
) . 曲线拟合工具箱可能是另一种选择 . 否则,您可以使用开源优化例程(请查看cvxopt) .有几点需要注意 . 您需要施加约束,使
sigma
中的所有值都大于零 . 您可以告诉优化算法有关此约束 . 此外,您需要指定参数的初始猜测(即sigma
) . 在这种情况下,你可以通过查看每个峰值附近的曲线来选择合理的东西 . 可能是这种情况(当损失函数是非凸的时)最终解决方案是不同的,这取决于初始猜测(即你收敛到局部最小值) . 有许多奇特的技术可以处理这种情况,但一个简单的事情就是尝试多种不同的初始猜测,并选择最佳结果 .编辑添加:
在python中,您可以在
scipy.optimize
模块中使用优化例程,例如curve_fit()
.编辑2(对编辑问题的回复):
如果您的高斯彼此之间有很多重叠,那么取它们的总和可能会导致峰的高度与您的已知值不同 . 在这种情况下,您可以采用加权和,并将权重视为另一个要优化的参数 .
如果希望峰值高度与某些指定值完全相等,则可以在优化问题中强制执行此约束 .
lsqcurvefit()
将无法执行此操作,因为它只处理参数的绑定约束 . 看看fmincon()
.您可以使用Expectation–Maximization algorithm在数据上拟合高斯混合 . 它不关心数据维度 . 在MATLAB的文档中,您可以查找
gmdistribution.fit
或fitgmdist
.