在分散的数据中查找区域

时间:2013-06-16 04:40:16

标签: algorithm matlab

我在Nx3矩阵中有许多分散的数据集,下面显示了一个用scatter3绘制的简单示例(pastebin of the raw values): Scattered data with obvious regions 我的每个数据集都有任意数量的区域/ blob;例如上面的例子有4.

有没有人知道一种简单的方法来以编程方式查找此数据形式的区域数量?

我最初的想法是使用delaunayTriangulationconvexHull方法,但没有任何数据处理,这仍然只能找到整个地块的外部卷而不是每个地区。

我接下来的想法将涉及抓取每个点的最近邻居统计数据,询问它是否在另一个点的网格大小距离内,然后将那些点集中在单独的blob /簇中。

是否有更高级别的Matlab函数我不知道这可以帮助我,或者有没有人有更好的建议如何从这样的数据中拉出区域数?

4 个答案:

答案 0 :(得分:1)

听起来你需要一个聚类算法。幸运的是,MATLAB提供了许多开箱即用的功能。有很多算法可供选择,听起来你需要预先知道簇数的东西,对吗?

如果是这种情况,那么您的数据是"很好"作为您的示例,我建议kmeans结合使用技巧来正确选择" k",如建议here

当然还有其他选项,我建议您在MATLAB中了解有关聚类选项的更多信息,这里有一个很好的reference可供阅读。

答案 1 :(得分:0)

确定数据集中不同群集的数量是一个棘手的问题,可能比我们第一眼看到的要困难。事实上,像k-means这样的算法在很大程度上依赖于此。 Wikipedia有一篇很好的文章,但没有简单明了的方法。

这里提到的Elbow方法似乎比较容易做到,尽管可能计算成本很高。从本质上讲,您可以尝试使用不同数量的聚类,并选择所解释的方差不会增长太多并达到平稳的数字。

此外,需要明确定义群集的概念 - 如果放大任何blob显示与图片中的角落结构类似的结构会怎么样?

答案 2 :(得分:0)

我建议实现高斯混合模型的“轻型”版本。 让每个点“投票”一个立方体。在上面的例子中,所有点都以(-1.5,-1.5,0)为中心 将每个加1到正方形[-1,-2] x [-1,-2] x [0.2,-0.2]。最后,您可以分析投票矩阵中的峰值。

答案 3 :(得分:0)

为了完整性,这个问题(我已经建立)的答案要比分层聚类简单得多;它提供了更好的结果,可以区分1个集群或2个集群(我无法通过MarkV的建议解决这个问题)。这假设您的数据位于已知大小的常规网格上,并且您有未知数量的群集,这些群集至少相隔2 *(网格大小):

% Idea is as follows: 
% * We have a known grid size, dx. 
% * A random point [may as well be minima(1,:)] will be in a cluster of 
%   values if any others in the list lie dx away (with one dimention 
%   varied), sqrt(2)*dx (two dimensions varied) or sqrt(3)*dx (three 
%   dimensions varied).
% * Chain these objects together until all are found, any with distances
%   beyond sqrt(3)*dx of the cluster are ignored for now.
% * Set this cluster aside, repeat until no minima data is left.

function [blobs, clusterIdx] = findClusters(minima,dx)
%problem setup
dx2 = sqrt(2)*dx;
dx3 = sqrt(3)*dx;
eqf = @(list,dx,dx2,dx3)(abs(list-dx) < 0.001 | abs(list-dx2) < 0.001 | abs(list-dx3) < 0.001);
notDoneClust = true;
notDoneMinima = true;

clusterIdx = zeros(size(minima,1),1);
point = minima(1,:);
list = minima(2:end,:);
blobs = 0;

while notDoneMinima
    cluster = nan(1,3);

    while notDoneClust
        [~, dist] = knnsearch(point,list); %All distances to each other point in data
        nnidx = eqf(dist,dx,dx2,dx3); %finds indexes of nn values to point

        cluster = cat(1,cluster,point,list(nnidx,:)); %add points to current cluster
        point = list(nnidx,:); %points to check are now all values that are nn to initial point
        list = list(~nnidx,:); %list is now all other values that are not in that list

        notDoneClust = ~isempty(point); %if there are no more points to check, all values of the cluster have been found
    end
    blobs = blobs+1;
    clusterIdx(ismemberf(minima,cluster(2:end,:),'rows')) = blobs;

    %reset points and list for a new cluster
    if ~isempty(list)
        if length(list)>1
            point = list(1,:);
            list = list(2:end,:);
            notDoneClust = true;
        else
            %point is a cluster of its own. Don't reset loops, add point in
            %as a cluster and exit (NOTE: I have yet to test this portion).
            blobs = blobs+1;
            clusterIdx(ismemberf(minima,point,'rows')) = blobs;
            notDoneMinima = false;
        end
    else
        notDoneMinima = false;
    end
end
end

我完全理解这种方法对于一般意义上的数据聚类是无用的,因为任何外围数据都将被标记为单独的聚类。这(如果它发生)是我需要的,所以这可能只是一个边缘情况。