2013-08-02 30 views
9

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

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

XX可以在这个环节XX value可以发现,K为3 因此,如果任何人都可以请告诉我为什么发生这种情况。

回答

20

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

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

  • 样品:样品K点随机地从该数据作为初始簇(默认)
  • 均匀:均匀地将数据
  • 簇的范围选择K个点:上的小的子集进行初步聚类
  • 手册:手动指定初始簇

还可以尝试的不同值选项,它告诉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 

clustered points

因此,如果您先删除重复点,您可能会获得更好的群集......


另外,你有一些异常值可能会影响聚类的结果。在视觉上,我缩小数据以以下时间间隔的其包含大多数的数据的范围:

>> 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% 

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

final clustering

+0

非常感谢你,我真的很感激您的热心帮助!我已经使用了这段代码,但是图中没有用不同颜色聚集点:XX = unique(XX,'rows'); XX(XX(:,1)<-500 | XX(:,1)> 100,:) = []; (XX,:2)< - 500 | XX(:,2)> 100,:) = []; XX(XX(:,3)<900 | XX(:,3)> 1500,:) = []; [IDX,C] = kmeans(XX,3,'replicates',5); clr = lines(max(IDX)); (XXX(i = 0,1),XX(IDX == ii,2),XX(IDX == ii,3),... 'Color',clr( ','LineStyle','none','Marker','。','MarkerSize',1) axis vis3d;图(3); 结尾 – Tak

+1

oops有一个错字('for i = 1:1'应该是'for i = 1:K',其中'K'是簇的数量)。现在修复,看看编辑:) – Amro

+0

感谢这个惊人的解决方案,我真的很感激它。我想知道你是否可以帮助我做另一件事。是否有可能删除大区域以外的区域?例如,在右上角的上图中有两个区域未连接到大区域,我想知道如何删除异常区域?许多感谢 – Tak

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 
0

荷银described原因明确:

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

但是其他的选项,可以帮助解决这个问题是emptyaction

采取的措施如果群集失去其所有成员的意见。

error:将空簇视为错误(默认值)。

drop:删除所有变空的簇。 kmeans将相应的返回值设置为CDNaN。 (用于信息 约CD看到kmeansdocumentioan page

singleton:创建一个由从它的质心的一个点最远的一个新的簇。


一个例子:

让我们运行一个简单的代码,看看这个选项是如何改变的行为和kmeans结果。此示例试图在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决定数量。您可以删除NaN行形式C这样的:

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

最后第三次调用生成异常和预期暂停该计划。

Empty cluster created at iteration 1.