【问题标题】:Kmeans matlab "Empty cluster created at iteration 1" errorKmeans matlab“在迭代 1 中创建空簇”错误
【发布时间】:2013-08-03 07:08:14
【问题描述】:

我正在使用此脚本使用 kmeans matlab 函数对一组 3D 点进行聚类,但我总是收到此错误“在迭代 1 时创建了空簇”。 我正在使用的脚本:

[G,C] = kmeans(XX, K, 'distance','sqEuclidean', 'start','sample');

XX可以在这个链接XX value找到,K设置为3 所以如果有人能告诉我为什么会这样。

【问题讨论】:

    标签: matlab cluster-analysis k-means


    【解决方案1】:

    它只是告诉您在分配-重新计算迭代期间,一个集群变成了空的(丢失了所有分配的点)。这通常是由于集群初始化不充分,或者数据具有的固有集群少于您指定的数量。

    尝试使用start 选项更改初始化方法。 Kmeans 提供了四种可能的技术来初始化集群:

    • sample:从数据中随机抽取 K 个点作为初始聚类(默认)
    • uniform:在数据范围内均匀选择 K 个点
    • 集群:对一个小子集执行初步集群
    • 手动:手动指定初始集群

    您还可以尝试emptyaction 选项的不同值,它会告诉 MATLAB 在集群变为空时要做什么。

    最终,我认为您需要减少集群的数量,即尝试K=2集群。


    我尝试将您的数据可视化以感受一下:

    load matlab_X.mat
    figure('renderer','zbuffer')
    line(XX(:,1), XX(:,2), XX(:,3), ...
        'LineStyle','none', 'Marker','.', 'MarkerSize',1)
    axis vis3d; view(3); grid on
    

    经过一些手动缩放/平移后,它看起来像一个人的剪影:

    可以看到307200个点的数据确实密集紧凑,印证了我的猜想;数据没有那么多簇。


    这是我试过的代码:

    >> [IDX,C] = kmeans(XX, 3, 'start','uniform', 'emptyaction','singleton');
    >> tabulate(IDX)
      Value    Count   Percent
          1    18023      5.87%
          2    264690     86.16%
          3    24487      7.97%
    

    更重要的是,簇2中的整个点都是重复点([0 0 0]):

    >> unique(XX(IDX==2,:),'rows')
    ans =
         0     0     0
    

    另外两个集群看起来像:

    clr = lines(max(IDX));
    for i=1:max(IDX)
    line(XX(IDX==i,1), XX(IDX==i,2), XX(IDX==i,3), ...
        'Color',clr(i,:), 'LineStyle','none', 'Marker','.', 'MarkerSize',1)
    end
    

    因此,如果您首先删除重复点,您可能会得到更好的聚类...


    此外,您还有一些异常值可能会影响聚类结果。从视觉上看,我将数据范围缩小到包含大部分数据的以下区间:

    >> xlim([-500 100])
    >> ylim([-500 100])
    >> zlim([900 1500])
    

    这是删除重复点(超过 250K 点)和异常值(大约 250 个数据点)并使用 K=3 聚类后的结果(使用 replicates 选项运行 5 次中最好的):

    XX = unique(XX,'rows');
    XX(XX(:,1) < -500 | XX(:,1) > 100, :) = [];
    XX(XX(:,2) < -500 | XX(:,2) > 100, :) = [];
    XX(XX(:,3) < 900 | XX(:,3) > 1500, :) = [];
    
    [IDX,C] = kmeans(XX, 3, 'replicates',5);
    

    三个集群几乎相等:

    >> tabulate(IDX)
      Value    Count   Percent
          1    15605     36.92%
          2    15048     35.60%
          3    11613     27.48%
    

    回想一下,默认距离函数是欧几里得距离,它解释了形成的簇的形状。

    【讨论】:

    • 非常感谢,非常感谢您的热心帮助!我已经使用了这段代码,但该图没有用不同颜色聚集点:XX = unique(XX,'rows'); XX(XX(:,1) 100, :) = []; XX(XX(:,2) 100, :) = []; XX(XX(:,3) 1500, :) = []; [IDX,C] = kmeans(XX, 3, 'replicates',5); clr = 线(最大(IDX));对于 ii=1:1 线(XX(IDX==ii,1), XX(IDX==ii,2), XX(IDX==ii,3), ... '颜色',clr(ii,: ), 'LineStyle','none', 'Marker','.', 'MarkerSize',1) 轴 vis3d;视图(3);网格结束
    • 哎呀有一个错字(for i=1:1 应该是 for i=1:K 其中K 是集群的数量)。现已修复,请参阅编辑 :)
    • 感谢这个惊人的解决方案,我真的很感激。我想知道你是否可以帮助我做另一件事。是否可以删除大区域之外的区域?例如,上图中右下角有两个点区域没有连接到大区域,我想知道如何去除异常区域?非常感谢
    • @user1460166:也许另一种聚类算法,如DBSCANmean-shift(基于密度)可能会以您期望的方式分离点。这里还有一些其他帖子可以为您指明正确的方向:stackoverflow.com/questions/4567515/…stackoverflow.com/a/2303583/97160
    • 您始终可以使用 MATLAB 的 brushing 功能将其作为一次性交互式过滤来执行。请参阅此示例:stackoverflow.com/a/7455390/97160
    【解决方案2】:

    如果您对“k=3”的选择有信心,以下是我为不获取空集群而编写的代码:

    [IDX,C] = kmeans(XX,3,'distance','cosine','start','sample', 'emptyaction','singleton');
    
    while length(unique(IDX))<3 ||  histc(histc(IDX,[1 2 3]),1)~=0
    % i.e. while one of the clusters is empty -- or -- we have one or more clusters with only one member
    [IDX,C] = kmeans(XX,3,'distance','cosine','start','sample', 'emptyaction','singleton');
    end  
    

    【讨论】:

      【解决方案3】:

      Amrodescribed原因很清楚:

      它只是告诉您在分配重新计算迭代期间, 一个集群变空(丢失所有分配的点)。这通常是 由于集群初始化不充分或数据已 比您指定的更少的固有集群。

      但可以帮助解决此问题的另一个选项是emptyaction

      如果集群丢失其所有成员观测值时要采取的措施。

      error:将空集群视为错误(默认)。

      drop:删除所有变为空的集群。 kmeansCD 中对应的返回值设置为NaN。 (供参考 关于CDkmeansdocumentioan page)

      singleton:创建一个由离其质心最远的一点组成的新集群。


      一个例子:

      让我们运行一个简单的代码来看看这个选项如何改变kmeans 的行为和结果。此示例尝试将 3 个观测值划分为 3 个集群,其中 2 个位于同一点:

      clc;
      X = [1 2; 1 2; 2 3];
      [I, C] = kmeans(X, 3, 'emptyaction', 'singleton');
      [I, C] = kmeans(X, 3, 'emptyaction', 'drop');
      [I, C] = kmeans(X, 3, 'emptyaction', 'error')
      

      第一次调用singleton 选项显示警告并返回:

      I =                               C =
       3                                 2     3
       2                                 1     2
       1                                 1     2
      

      如您所见,在同一位置 ([1 2]) 创建了两个集群质心,并将 X 的前两行分配给这些集群。

      使用drop 选项的第二次调用也显示相同的警告消息,但返回不同的结果:

      I =                               C =
       1                                 1     2
       1                               NaN   NaN
       3                                 2     3
      

      它只返回两个簇中心并将X 的前两行分配给同一个簇。我认为大多数时候这个选项最有用。如果观测值太接近并且我们需要尽可能多的聚类中心,我们可以让 MATLAB 决定数量。您可以像这样从C 中删除NaN 行:

      C(any(isnan(C), 2), :) = [];
      

      最后第三次调用产生异常并按预期停止程序。

      Empty cluster created at iteration 1.

      【讨论】:

        猜你喜欢
        • 2014-05-09
        • 1970-01-01
        • 2021-03-03
        • 1970-01-01
        • 2014-01-01
        • 2018-11-15
        • 1970-01-01
        • 2016-11-26
        • 2014-02-20
        相关资源
        最近更新 更多