文档:https://ww2.mathworks.cn/help/stats/examples/cluster-analysis.html
更多:https://ww2.mathworks.cn/discovery/cluster-analysis.html
代码:
%此示例中使用的一些函数调用 MATLAB® 内置随机数生成函数。要得到与此示例完全相同的结果,请执行以下命令,将随机数生成器设置为已知状态。
%如果您不设置状态,结果可能会略有不同,例如,簇可能会以不同的顺序编号。另外,有可能产生次优聚类解(本示例也讨论了次优解,以及避免次优解的方法)。
rng(14,'twister');
%首先,加载数据并调用 kmeans,将所需的簇数设置为 2,并使用平方欧几里德距离。要了解生成的簇区分数据的效果,可以绘制轮廓图。轮廓图显示一个簇中的每个点与相邻簇中的点的接近程度。
figure;
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');
%默认情况下,kmeans 使用随机选择的一组初始质心位置开始聚类过程。
[cidx3,cmeans3,sumd3] = kmeans(meas,3,'replicates',5,'display','final');
%kmeans 最终返回的解是所有重复中距离总和最小的解。第三个输出参数包含每个簇中对于该最佳解的距离总和。
sum(sumd3)
%该三簇解的轮廓图显示,有一个簇区分效果很好,但另外两个簇的区别不是很明显。
figure;
[silh3,h] = silhouette(meas,cidx3,'sqeuclidean');
%同样,可以绘制原始数据以查看 kmeans 如何将点分配给簇。
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');
%从轮廓图中可以看出,这些簇的区分效果好像只比使用平方欧几里德距离时稍好一点。
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
%数据中每个观测值所属的品种,所以可以将 kmeans 发现的簇与实际品种进行比较,以了解这三个品种是否具有明显不同的物理特性。
%实际上,如下图所示,使用余弦距离创建的簇与实际品种分组的不同之处只有五朵花。这五个点(用星形标记绘制)都靠近上方两个簇的边缘交界处。
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
%首先,使用鸢尾花数据中观测值之间的距离创建一个聚类树。先使用欧几里德距离。
eucD = pdist(meas,'euclidean');
clustTreeEuc = linkage(eucD,'average');
%共性相关是验证聚类树与原始距离是否一致的一种方法。较大的值表明树对距离的拟合良好,即观测值之间的两两连接与它们实际上的两两距离是相关的。此树对距离的拟合看起来相当好。
cophenet(clustTreeEuc,eucD)
%要可视化聚类的层次结构,可以绘制树状图。
figure;
[h,nodes] = dendrogram(clustTreeEuc,0);
h_gca = gca;
h_gca.TickDir = 'out';
h_gca.TickLength = [.002 0];
h_gca.XTickLabel = [];
%树中的根节点远远高于其余节点,证实了您在 K 均值聚类中所看到的:两个很大的、区别明显的观测值组。在每个组中可以看到,随着距离尺度越来越小,较低级别的组逐渐出现。有许多级别不同、大小不同、区别度不同的组。
%根据 K 均值聚类的结果,我们也不妨使用余弦来测度距离。由此生成的层次结构树很不一样,让我们能够以一种完全不同的方式观察鸢尾花数据的组结构。
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 = [];
figure;
[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);
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 = [];