首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >非层次聚类:k-medoids

非层次聚类:k-medoids

作者头像
SYSU星空
发布2022-05-05 13:55:10
发布2022-05-05 13:55:10
8890
举报

非层次聚类

往期文章层次聚类与聚类树比较聚类与聚类簇划分介绍了层次聚类的使用,今天为大家介绍非层次聚类的使用。非层次聚类(non- hierarchical clustering)是对一组对象进行简单分组的方法,其分类依据是尽量使得组内对象之间比组间对象之间的相似度更高,在分析之前需要预设小组的数目。非层次聚类需要首先有个预设的结构,比如假设有k个类群,那么将所有对象任意分为k组,然后在这个基础上不断进行替换迭代,来达到最优化的分组结果。

k-中心点划分

k-means算法中选取的是距离均值,那么异常点对其的影响会非常大,很可能这种孤立的点就聚为一类,一个改进的方法就是围绕实际数据的中心点进行划分(partitioning aroundmedoids,PAM),也叫k-medoids clustering。其与k-means算法类似,从所有数据观测点寻找k个代表性的对象或形心点,来反应数据的主体结构,然后将所有观测点分配给每个形心点构建k个分类簇。不断迭代来寻找k个代表对象,来获得最佳的形心点来使得对象间的相异性总和最小。

k-medoids算法是k-means算法的变种,其不一样的地方在于聚类中心的选取。在k-means算法中将聚类中心选取为当前cluster中所有数据点的平均值,也即非真实的数据点;然而k-medoids算法中,将聚类中心也即中心点的选取限制在当前cluster所包含的数据点的集合中,从当前cluster中选取到其他所有点的距离之和最小的点作为中心点。k-means和k-medoids之间的差异就类似于一个数据样本的均值和中位数之间的差异。

cluster包中的pam()函数可以使用原始数据或者距离矩阵进行分析,因此十分方便,还可以通过轮廓宽度值确定最佳的分组数量,而fpc包中的pamk()函数可以自动计算最佳的分类簇数目,实例分析如下所示:

代码语言:javascript
复制
#读取数据
data=read.table(file="otu_table.txt", header=TRUE, check.names=FALSE)
rownames(data)=data[, 1]
data=as.matrix(data[, -1])
#将每个样品的物种数据进行总和标准化(即求相对丰度)
library(vegan)
data=decostand(data, MARGIN=2, "total")*100
otu=t(data)
#计算距离矩阵
otu_dist=vegdist(otu, method="bray", diag=TRUE, upper=TRUE, p=2)
#PAM聚类
library(fpc)
library(cluster)
#确定最佳聚类簇数目
pambest=pamk(otu_dist)
k=pambest$nc
otu_pam=pam(otu_dist, k)
mycol=c(99,81,503,562,76,96,495,52,619,453,71,134,448,548,655,574,36,544,89,120,131,596,147,576,58,429,386,122,87,404,466,124,463,552,147,45,30,54,84,256,100,652,31,610,477,150,50,588,621)
mycol=colors()[mycol]
clusplot(otu_pam, color=TRUE, labels=3, lines=0, cex=1, col.clus=mycol[1:k], col.p=otu_pam$clustering)

clusplot()函数可以对聚类结果进行主成分分析并作图,结果如下所示:

根据pamk()函数计算结果最佳聚类簇数目为10,但主成分聚类图显示的聚类簇数目要小于10,可以看到不同算法的差异。我们也可以针对PAM聚类绘制轮廓宽度图,从而帮助挑选最佳聚类簇数目,如下所示:

代码语言:javascript
复制
#绘制轮廓宽度图
asw=numeric(nrow(otu))
for (i in 2:(length(asw)-1)) {
  asw[i]=pam(otu_dist, i)$silinfo$avg.width
}
k.best=which.max(asw)
plot(1:length(asw), asw, type="h", main="Silhouette of PAM", lwd=2,
     xlab="k(number of clusters", ylab="average silhouette")

结果如下所示:

当k=22时取得最高的轮廓宽度,这与事实是相符的,因为我们所用数据的66个样品采自22个样品点,每个点3个平行样。但总体来看,轮廓宽度值很高,因此不一定挑选k=22,这里只是为pamk()函数判断结果作参考。

不同算法的侧重不同,因此结果会有一些差异。这些算法都可以作为我们的工具库,我们在实际研究中可以选择适合自己数据的算法。

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微生态与微进化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档