我需要为两个甜甜圈形状数据集进行光谱聚类。(Matlab)

时间:2015-11-20 03:24:04

标签: matlab cluster-analysis spectral

我已经尝试了几个小时但我找不到解决方案。

我有两个甜甜圈"数据样本(变量" X")

您可以在链接下载文件

donut dataset(rings.mat)

传播到2D形状,如图像

前250个位于甜甜圈内,最后750个位于甜甜圈外。

2 Donut 2D sample

我需要进行光谱聚类。

我用高斯相似距离做了(相似矩阵" W")。

我用" W"

的每个原始的总和制作了度矩阵

然后我计算了特征值(E)和特征向量(V)

和" V"的形状不好。

我的审判有什么问题???

我无法弄清楚。

load rings.mat
[D, N] = size(X); % data stored in X
%initial plot data
figure; hold on; 
for i=1:N,
    plot(X(1,i), X(2,i),'o');
end
% perform spectral clustering
W = zeros(N,N); 
D = zeros(N,N);

sigma = 1;
for i=1:N,
    for j=1:N,
        xixj2 = (X(1,i)-X(1,j))^2 + (X(2,i)-X(2,j))^2 ;
        W(i,j) =  exp(  -1*xixj2 / (2*sigma^2) ) ;   % compute weight here
%          if (i==j)
%              W(i,j)=0;
%          end;
    end;
     D(i,i) = sum(W(i,:))    ;
end;

L = D - W ;
normL = D^-0.5*L*D^-0.5;
[u,s,v] = svd(normL);

Image

1 个答案:

答案 0 :(得分:1)

如果您使用类似于您的代码中的拉普拉斯算子(“真实”拉普拉斯算子),那么要将您的点聚类成两组,您将需要对应于第二个最小特征值的特征向量。

直观的想法是用弹簧将所有点相互连接,如果点彼此靠近,弹簧会更硬,而远处的点则不那么僵硬。拉普拉斯算子的特征向量是振动模式,如果你用锤子击中你的弹簧网并注意它振荡 - 较小的特征值对应于较低频率的“体积”模式,较大的特征值对应于较高频率的振荡。你想要的特征值对应于第二个最小的特征值,它就像鼓中的第二个模式,正面聚集在一起,而负面部分聚集在一起。

现在关于是否使用最大或最小特征值的评论中存在一些混淆,这是因为由dave链接的纸张中的拉普拉斯略有不同,因为身份减去了你的拉普拉斯。所以他们想要最大的,而你想要最小的。本文中的聚类也更先进,更好,但不易实现。

以下是您的代码,已修改为可以使用:

load rings.mat
[D, N] = size(X); % data stored in X
%initial plot data
figure; hold on; 
for i=1:N,
    plot(X(1,i), X(2,i),'o');
end
% perform spectral clustering
W = zeros(N,N); 
D = zeros(N,N);

sigma = 0.3; % <--- Changed to be smaller
for i=1:N,
    for j=1:N,
        xixj2 = (X(1,i)-X(1,j))^2 + (X(2,i)-X(2,j))^2 ;
        W(i,j) =  exp(  -1*xixj2 / (2*sigma^2) ) ;   % compute weight here
%          if (i==j)
%              W(i,j)=0;
%          end;
end;
     D(i,i) = sum(W(i,:))    ;
end;

L = D - W ;
normL = D^-0.5*L*D^-0.5;
[u,s,v] = svd(normL);

% New code below this point
cluster1 = find(u(:,end-1) >= 0);
cluster2 = find(u(:,end-1) < 0);

figure
plot(X(1,cluster1),X(2,cluster1),'.b')
hold on
plot(X(1,cluster2),X(2,cluster2),'.r')
hold off
title(sprintf('sigma=%d',sigma))

结果如下:

enter image description here

现在注意我将sigma改为更小 - 从1.0到0.3。当我把它放到1.0时,我得到了以下结果:

enter image description here

我假设是因为sigma = 1,内部集群中的点能够“拉”到外部集群(它们距离距离1远),这样才能更有利于拆分两者。圆形的一半像一个坚固的振动鼓,而不是两个不同的圆圈。