简介

非监督学习是一种机器学习算法,用于在没有人工干预的情况下从数据集中得到分类结果。最常见的非监督学习方法是聚类分析,它应用聚类方法来探索数据并查找数据中的隐藏模式或分组。基于Matlab常用的流行的聚类算法有:(1)Hierarchical clustering;(2)k-Means and k-medoids clustering;(3)Gaussian mixture models;(4)Density-based spatial clustering (DBSCAN);(5)Self-organizing maps;(6)Spectral clustering。下面分别对这几种方法进行一个测试及总结。

测试数据集

费舍尔Fisher虹膜数据:在1920年代,植物学家收集了150个虹膜标本的萼片长度、萼片宽度、花瓣长度和花瓣宽度的测量值,其中三个物种(setosa 刺芒野古草 、versicolor 花斑癣、 virginica 海滨锦葵,翻译可能不准)各有50个。这些测量结果被称为Fisher虹膜数据集。
该数据集中的每个观测值均来自已知物种,因此已经存在一种将数据分组的明显方法。目前,我们将忽略物种信息,仅使用原始测量值对数据进行聚类。完成后,我们可以将所得簇与实际物种进行比较,以查看这三种虹膜是否具有鲜明的特征。

聚类距离计算方法

具体需要哪一种距离方案可以根据自己的数据决定,常用的距离方案如下:

‘sqeuclidean’

‘cityblock’

‘cosine’

‘correlation’

‘hamming’

非监督的深度学习方法 非监督分类有哪些方法_非监督的深度学习方法


对于大部分应用,correlation、cos、mahal效果可能会表现的更好,这三种距离方案能够克服变量尺度影响。

K-Means Clustering

使用K均值聚类对Fisher虹膜数据进行聚类,使用kmeans函数将对象利用迭代算法进行聚类,以便每个对象到其聚类质心的距离之和最小。通过根据费舍尔虹膜数据,它将根据虹膜标本的萼片和花瓣测量值找到虹膜标本中的自然分组。使用K-means聚类时,必须指定要创建的聚类数。

加载数据,先将聚类数设置为2进行调用,并使用平方的欧几里得距离。要了解生成的聚类的分离程度,可以绘制轮廓图。轮廓图显示了一个群集中的每个点与相邻群集中的点的接近程度的度量。

load fisheriris
[cidx2,cmeans2] = kmeans(meas,2,'dist','sqeuclidean');
[silh2,h] = silhouette(meas,cidx2,'sqeuclidean');

非监督的深度学习方法 非监督分类有哪些方法_非监督分类_02


从轮廓图中可以看到,两个群集中的大多数点的轮廓值都较大,大于0.8,这表明这些点与相邻聚类之间的分隔良好。但是,每个聚类还包含一些轮廓值较低的点,表明它们与其他聚类的点相邻。

事实表明,这些数据中的第四个测量值(花瓣宽度)与第三个测量值(花瓣长度)高度相关,因此前三个测量值的3-D图可以很好地表示数据,而无需求助于四个维度。如果对数据进行绘制,则对所创建的每个聚类使用不同的符号表示,则可以将轮廓值较小的点标识为与其他聚类的点接近的那些点。

ptsymb = {'bs','r^','md','go','c+'};
for i = 1:2
    clust = find(cidx2==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
plot3(cmeans2(:,1),cmeans2(:,2),cmeans2(:,3),'ko');
plot3(cmeans2(:,1),cmeans2(:,2),cmeans2(:,3),'kx');
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

非监督的深度学习方法 非监督分类有哪些方法_聚类分析_03


每个聚类的质心使用带圆圈的X绘制。可以看到较高的聚类如此离散,因为,即使这些点与它们自己的聚类中的大部分点具有一定间隙,也比下面聚类更靠近其质心。由于K均值聚类仅考虑距离而不考虑密度,因此,产生这种结果。

可以通过增加聚类数量,以查看是否kmeans可以在数据中找到更多的分组结构。

[cidx3,cmeans3] = kmeans(meas,3,'Display','iter');

在每次迭代时,该kmeans算法(请参阅算法)在聚类中重新分配点以减少点到质心的距离之和,然后为新的聚类分配重新计算聚类质心。注意,距离的总和和重新分配的次数在每次迭代中都会减少,直到算法达到最小值为止。
默认情况下,kmeans使用随机选择的一组初始质心位置开始聚类过程。该kmeans算法可以收敛到局部最小解。kmeans有时得出的解决方案取决于起点。因此,可以使用Replicates参数来设置重复次数。kmeans 然后返回所有重复项中距离总和最小的解。

[cidx3,cmeans3,sumd3] = kmeans(meas,3,'replicates',5,'display','final');
[silh3,h] = silhouette(meas,cidx3,'sqeuclidean');

figure
for i = 1:3
    clust = find(cidx3==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
plot3(cmeans3(:,1),cmeans3(:,2),cmeans3(:,3),'ko');
plot3(cmeans3(:,1),cmeans3(:,2),cmeans3(:,3),'kx');
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

[mean(silh2) mean(silh3)]

非监督的深度学习方法 非监督分类有哪些方法_非监督分类_04


非监督的深度学习方法 非监督分类有哪些方法_聚类_05


可以看到kmeans已经从两个聚类解决方案中进一步区分了上层聚类,并且这两个聚类彼此非常接近。对于两个聚类的方案,平均轮廓值较大,这表明从纯粹创建聚类的角度来看,两个聚类是一个更好的方案。下图是欧氏距离进行分类的精度。

非监督的深度学习方法 非监督分类有哪些方法_非监督分类_06

也可以通过不同的距离方法对这些数据进行聚类。余弦距离对这些数据可能更有意义,因为它会忽略测量的绝对大小,而只考虑它们的相对大小。因此,具有不同大小但花瓣和萼片形状相似的两朵花的欧氏距离可能不接近,而余弦距离却很接近。

[cidxCos,cmeansCos] = kmeans(meas,3,'dist','cos','replicates',5,'display','final');
figure
[silhCos,h] = silhouette(meas,cidxCos,'cos');
[mean(silh2) mean(silh3) mean(silhCos)]

figure
for i = 1:3
    clust = find(cidxCos==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

非监督的深度学习方法 非监督分类有哪些方法_聚类_07

非监督的深度学习方法 非监督分类有哪些方法_聚类分析_08


从轮廓图中可以看出,cos距离与使用欧氏距离发现的聚类相比,这些聚类的分离似乎仅稍好一些。

非监督的深度学习方法 非监督分类有哪些方法_ci_09


下图为correlation的kmeans聚类精度。

非监督的深度学习方法 非监督分类有哪些方法_ci_10

clc; clear all; close all;

rng(6,'twister')

% 载入数据
load fisheriris
[cidx2,cmeans2] = kmeans(meas,2,'dist','sqeuclidean');
% 聚类轮廓
[silh2,h] = silhouette(meas,cidx2,'sqeuclidean');

figure
ptsymb = {'bs','r^','md','go','c+'};
for i = 1:2
    clust = find(cidx2==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
plot3(cmeans2(:,1),cmeans2(:,2),cmeans2(:,3),'ko');
plot3(cmeans2(:,1),cmeans2(:,2),cmeans2(:,3),'kx');
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

[cidx3,cmeans3] = kmeans(meas,3,'Display','iter');

% 重复5次,返回最优解
[cidx3,cmeans3,sumd3] = kmeans(meas,3,'replicates',5,'display','final');
figure
[silh3,h] = silhouette(meas,cidx3,'sqeuclidean');

figure
for i = 1:3
    clust = find(cidx3==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
plot3(cmeans3(:,1),cmeans3(:,2),cmeans3(:,3),'ko');
plot3(cmeans3(:,1),cmeans3(:,2),cmeans3(:,3),'kx');
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

[mean(silh2) mean(silh3)]

[cidxCos,cmeansCos] = kmeans(meas,3,'dist','cos','replicates',5);
figure
[silhCos,h] = silhouette(meas,cidxCos,'cos');
[mean(silh2) mean(silh3) mean(silhCos)]

figure
for i = 1:3
    clust = find(cidxCos==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

figure
lnsymb = {'b-','r-','m-'};
names = {'SL','SW','PL','PW'};
meas0 = meas ./ repmat(sqrt(sum(meas.^2,2)),1,4);
ymin = min(min(meas0));
ymax = max(max(meas0));
for i = 1:3
    subplot(1,3,i);
    plot(meas0(cidxCos==i,:)',lnsymb{i});
    hold on;
    plot(cmeansCos(i,:)','k-','LineWidth',2);
    hold off;
    title(sprintf('Cluster %d',i));
    xlim([.9, 4.1]);
    ylim([ymin, ymax]);
    h_gca = gca;
    h_gca.XTick = 1:4;
    h_gca.XTickLabel = names;
end

figure
subplot(1,1,1);
for i = 1:3
    clust = find(cidxCos==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on
sidx = grp2idx(species);
miss = find(cidxCos ~= sidx);
% plot3(meas(miss,1),meas(miss,2),meas(miss,3),'k*');
legend({'setosa','versicolor','virginica'});
hold off

Hierarchical Clustering

分层聚类通过创建聚类树或树状图,将数据按各种规模进行分组。该树不是一组单独的聚类,而是一个多层次的层次结构,其中,一个级别的聚类作为下一个级别的聚类连接在一起。这使您可以决定最适合您的应用的聚类规模。

K-Means聚类生成虹膜数据的单个分区,如果还想研究数据中不同级别的分组可以通过Hierarchical Clustering来实现。首先,使用虹膜数据中观察值之间的距离创建聚类树,首先使用欧氏距离。

clc; clear all; close all;
% 载入数据
load fisheriris

eucD = pdist(meas,'euclidean');
clustTreeEuc = linkage(eucD,'average');

cophenet(clustTreeEuc,eucD)

[h,nodes] = dendrogram(clustTreeEuc,0);
h_gca = gca;
h_gca.TickDir = 'out';
h_gca.TickLength = [.002 0];
h_gca.XTickLabel = [];


cosD = pdist(meas,'cosine');
clustTreeCos = linkage(cosD,'average');
cophenet(clustTreeCos,cosD)

figure
[h,nodes] = dendrogram(clustTreeCos,0);
h_gca = gca;
h_gca.TickDir = 'out';
h_gca.TickLength = [.002 0];
h_gca.XTickLabel = [];

[h,nodes] = dendrogram(clustTreeCos,12);

[sum(ismember(nodes,[11 12 9 10])) sum(ismember(nodes,[6 7 8])) ...
                  sum(ismember(nodes,[1 2 4 3])) sum(nodes==5)]
figure              
hidx = cluster(clustTreeCos,'criterion','distance','cutoff',.006);
ptsymb = {'bs','r^','md','go','c+'};
for i = 1:5
    clust = find(hidx==i);
    plot3(meas(clust,1),meas(clust,2),meas(clust,3),ptsymb{i});
    hold on
end
hold off
xlabel('Sepal Length');
ylabel('Sepal Width');
zlabel('Petal Length');
view(-137,10);
grid on

figure
clustTreeSng = linkage(eucD,'single');
[h,nodes] = dendrogram(clustTreeSng,0);
h_gca = gca;
h_gca.TickDir = 'out';
h_gca.TickLength = [.002 0];
h_gca.XTickLabel = [];

非监督的深度学习方法 非监督分类有哪些方法_非监督分类_11


要可视化聚类的的层次结构,树状图。

该树中的根节点比其余节点高得多,与K-Means聚类中看到的结果相似:有两个大聚类。在这两个聚类的每一个分组中,可以看到,出现了更低级别的组。有许多不同级别的组,大小不同,区分程度也不同。

根据K-Means聚类的结果,余弦也可能是距离度量的不错选择。最终的层次树完全不同,这表明在虹膜数据中查看组结构的方式非常不同。

非监督的深度学习方法 非监督分类有哪些方法_非监督分类_12


树状图显示,虹膜标本分为两个非常不同的组。相对于余弦距离,组内差异相对于组间差异要比欧氏距离小得多。这正是对这些数据的期望值,因为余弦距离计算出与原点处于同一“方向”的对象的成对距离为零。

非监督的深度学习方法 非监督分类有哪些方法_非监督的深度学习方法_13

Gaussian Mixture Data Using Hard Clustering

模拟混合高斯分布的数据

clc; clear all; close all;

% 模拟混合高斯分布的数据
rng('default')  % For reproducibility
mu1 = [1 2];
sigma1 = [3 .2; .2 2];
mu2 = [-1 -2];
sigma2 = [2 0; 0 1];
X = [mvnrnd(mu1,sigma1,200); mvnrnd(mu2,sigma2,100)];
n = size(X,1);

figure
scatter(X(:,1),X(:,2),10,'ko')

% 将高斯混合模型拟合到模拟数据
options = statset('Display','final'); 
gm = fitgmdist(X,2,'Options',options)

hold on
gmPDF = @(x,y) arrayfun(@(x0,y0) pdf(gm,[x0,y0]),x,y);
fcontour(gmPDF,[-8,6])
title('Scatter Plot and Fitted GMM Contour')
hold off

% 使用拟合的GMM对数据进行聚类
idx = cluster(gm,X);
cluster1 = (idx == 1); % |1| for cluster 1 membership
cluster2 = (idx == 2); % |2| for cluster 2 membership

figure
gscatter(X(:,1),X(:,2),idx,'rb','+o')
legend('Cluster 1','Cluster 2','Location','best')

% 估计聚类成员后验概率
P = posterior(gm,X); 

figure
scatter(X(cluster1,1),X(cluster1,2),10,P(cluster1,1),'+')
hold on
scatter(X(cluster2,1),X(cluster2,2),10,P(cluster2,1),'o')
hold off
clrmap = jet(80);
colormap(clrmap(9:72,:))
ylabel(colorbar,'Component 1 Posterior Probability')
legend('Cluster 1','Cluster 2','Location','best')
title('Scatter Plot and Cluster 1 Posterior Probabilities')


Mu = [mu1; mu2]; 
Sigma = cat(3,sigma1,sigma2); 
p = [0.75 0.25]; % Mixing proportions

gmTrue = gmdistribution(Mu,Sigma,p);
X0 = random(gmTrue,75);

[idx0,~,P0] = cluster(gm,X0);

figure
fcontour(gmPDF,[min(X0(:,1)) max(X0(:,1)) min(X0(:,2)) max(X0(:,2))])
hold on
gscatter(X0(:,1),X0(:,2),idx0,'rb','+o')
legend('Fitted GMM Contour','Cluster 1','Cluster 2','Location','best')
title('New Data Cluster Assignments')
hold off

非监督的深度学习方法 非监督分类有哪些方法_ci_14


非监督的深度学习方法 非监督分类有哪些方法_非监督的深度学习方法_15