我必须找到具有至少两个峰值的数据系列的高斯参数。我该如何管理?假设我有yi = f(xi
),我需要参数mu和sigma。
我知道我可以取所有数据的对数,然后使用polyfit进行处理,但用这种方式我会得到一些我不需要的东西(太久不能说明原因)。
我该怎么办?
重要细节:我的MATLAB版本没有normfit。
答案 0 :(得分:3)
如果MATLAB支持kmeans
,您可以尝试将数据聚类为两个聚类,然后独立计算每个聚类的均值和方差:
%// Cluster bimodal data
idx = kmeans(y, 2);
y1 = y(idx == 1);
y2 = y(idx == 2);
%// Compute means and variances of clusters
M = [mean(y1), mean(y2)];
V = [var(y1), var(y2)];
对于 k 模式的一般情况,您可以使用以下代码:
idx = kmeans(y, k); %// Cluster data
C = arrayfun(@(x)y(idx == x), 1:k, 'UniformOutput', false);
M = cellfun(@mean, C); %// Mean of clusters
V = cellfun(@var, C); %// Variance of clusters
这种方法的好处是,只要知道先验,它就适用于任意数量的集群。
让我们先生成一些任意的双峰高斯数据:
N = 1e4; %// Number of samples per mode
M = [1, 5]; V = [0.2, 0.4]; %// Means and variances of two normal distributions
y = bsxfun(@plus, bsxfun(@times, randn(1e4, 1), sqrt(V), M);
y = y(randperm(numel(y))); %// Shuffle samples
我们应该得到以下直方图:
现在让我们执行k-means聚类并计算每个聚类的均值和方差:
idx = kmeans(y, 2); %// Cluster bimodal data
C = arrayfun(@(x)y(idx == x), 1:k, 'UniformOutput', false);
M = cellfun(@mean, C); %// Mean of clusters
V = cellfun(@var, C); %// Variance of clusters
我得到的结果是:
M =
0.9985 4.9802
V =
0.1949 0.3854
非常接近原始数据。
如果您没有MATLAB的kmeans
,则可以使用FEX实现,例如litekmeans
。
答案 1 :(得分:0)
我已经在这里多次回答了这类问题,每次我都认为“只有必须才能做到这一点更简单......”但是,我还没有还没有看到或想到一个更简单的方法,所以......忍受我:)
如果你事先知道了峰的数量,你可以这样做:
function GaussFit
% DATA TO REPRODUCE
mu = [112 -45];
sigma = [ 12 24];
F =[...
mu(1) + sigma(1)*randn(1e4, 1)
mu(2) + sigma(2)*randn(1e4, 1)];
% interpolate with splines through the histogram
[y,x] = hist(F, 1500);
G = spline(x,y);
% Find optimum curve fit
P0 = [% mu S A
80 2 2e3; % (some rough initial estimate)
-8 12 2e3];
P = fminunc(@(P) Obj(P, x,G), P0); % refine the estimate
% REPRODUCED DATA
P(:,1:2).'
figure, clf, hold on
plot(x, P(1,3)*Gaussian(P(1,1),P(1,2),x) + P(2,3)*Gaussian(P(2,1),P(2,2),x))
plot(x, ppval(G,x),'r.', 'MarkerSize', 1)
end
% The objective function for the curve fitting optimizer
function val = Obj(P, x,F)
G = zeros(size(x));
for ii = 1:size(P,1);
mu = P(ii,1); % mean
sigma = P(ii,2); % std. deviation
A = P(ii,3); % "amplitude"
G = G + A/sigma/sqrt(2*pi) * exp(-(x-mu).^2/2/sigma^2);
end
val = sum((G-ppval(F,x)).^2);
end
% just a function for plotting
function G = Gaussian(mu,sigma,x)
G = 1/sigma/sqrt(2*pi) * exp(-(x-mu).^2/2/sigma^2);
end
结果:
ans =
112.1633 -45.2013
12.6777 24.6723
相当不错的结果我会说:)
与往常一样,这种方法有一些缺点;它需要你事先知道
如果您事先不知道峰的数量(并希望自动找到峰的数量),则必须使用kmeans
和some heuristics来定位峰的数量(在你的数据集中。及其手段。
在任何情况下,重要的是 方法可以找到峰的数量,但是没有办法自动找到合适的初始估算值。如果您只有一个或几十个数据集,那么仍然可以手动完成初始估算,但除此之外的任何内容都会使上述方法的吸引力越来越小。
然而,您可以使用全局优化器,在这种情况下,您不必再提出初始估算值。但正是在这一点上我无法思考
“对于这么简单的问题,这不应该是必要的!”
但是哦。