1

我在 Nx3 矩阵中有许多分散的数据集,scatter3下面显示了一个简单的示例(原始值的 pastebin): 具有明显区域的分散数据 我的每个数据集都有任意数量的区域/斑点;例如,上面的示例有 4 个。

有谁知道以编程方式查找这种数据形式的区域数量的简单方法?

我最初的想法是使用delaunayTriangulation,convexHull方法,但如果没有任何数据处理,这仍然只会找到整个图的外部体积,而不是每个区域。

我的下一个想法将涉及获取每个点的最近邻统计信息,询问它是否在另一个点的网格大小距离内,然后将那些在单独的 blob/clusters 集中在一起。

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

4

4 回答 4

1

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

如果是这种情况,并且您的数据与您的示例一样“好”,我建议将kmeans与正确选择“k”的技术相结合,如此处所建议。

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

于 2013-06-16T04:48:56.913 回答
0

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

于 2013-06-16T06:17:06.230 回答
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

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

于 2013-06-17T05:21:51.153 回答
0

确定数据集中不同聚类的数量是一个棘手的问题,而且可能比我们乍看之下想的要难。事实上,像 k-means 这样的算法在很大程度上依赖于此。Wikipedia上有一篇不错的文章,但没有明确和简单的方法。

那里提到的肘部方法似乎比较容易做到,尽管计算成本可能很高。本质上,您可以尝试使用不同数量的集群,并选择解释的方差不会增长太多并趋于平稳的数字。

此外,需要明确定义集群的概念——如果放大任何斑点会显示与图片中的角结构相似的结构怎么办?

于 2013-06-16T04:48:29.217 回答