9

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

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

XX 可以在此链接中找到XX 值并且 K 设置为 3 所以如果有人可以请告诉我为什么会这样。

4

3 回答 3

20

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

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

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

您也可以尝试不同的emptyactionoption 值,它告诉 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

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

3d_points

可以看到 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进行 5 次运行中最好的)后的结果:replicates

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%

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

最终聚类

于 2013-08-02T09:36:28.320 回答
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  
于 2013-08-26T21:54:33.117 回答
0

Amro清楚地描述了原因:

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

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

如果集群丢失其所有成员观察,则要采取的行动。

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

drop:删除任何变为空的簇。kmeans将相应的返回值设置为C和。(有关信息 ,请参阅文档页面DNaNCDkmeans

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

Second call withdrop选项也显示相同的警告消息,但返回不同的结果:

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

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

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

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

Empty cluster created at iteration 1.

于 2016-07-22T10:27:09.490 回答