k-means聚类算法及案例分析(如何确定聚类数:轮廓系数、中心划分法(PAM))


k-means聚类算法的R语言实现

 

K-means算法假设要把样本集分为c个类别,算法描述如下:(1)随机选择c个类的初始中心;

 

(2)在第n次迭代中,对任意一个样本,求其到每一个中心的距离,将该样本归到距离最近的中心所在的类;

 

3)更新该类的中心值,一般利用均值、中位点等方法;

 

(4)对于所有的c个聚类中心,利用(2)( 3 )的迭代法更新后,如果中心点的值不再变化,则迭代结束,否则继续迭代,当达到最大迭代次数时,中心点仍未收敛的,取最后的中心点为中心。

 

     kmeans 函数几个参数的具体作用:centers 设置聚类数;iter.max 设置最大迭代次数;nstart 随机设置初始中心点的次数,也可以理解为重复做kmeans的次数,众所周知,kmeans对初始中心非常敏感,nstart10表示做10kmeans,每次初始中心点随机生成一次,也可以理解为确定初始中心点时重复 kmeans的次数,每次迭代完成后返回最优解,当nstart 等于1时,等于只做了一次 kmeans,由于初始中心点不同,所以每次结果都不一样(可以设置随机种子克服)nstart一般设置在20~25之间,基本保证能返回最优解,每次的聚类结果也大体相同,除非你的数据量很大。

 

 

#步骤1 数据集准备及描述

n=100

g=6

set.seed(g)

d<-data.frame(x=unlist(lapply(1:g,function(i) rnorm(n/g,runif(1)*i^2))),

              y=unlist(lapply(1:g,function(i) rnorm(n/g,runif(1)*i^2)))) #生成数据集

解释:#unlist 给定一个列表结构 x,unlist 将其简化为生成一个包含 x 中出现的所有原子分量的向量。

            # lapply返回一个与 X 长度相同的列表,其中每个元素都是将 FUN 应用于 X 的相应元素的结果。

            #runif()函数用于生成从0到1区间范围内的服从正态分布的随机数,每次生成的值都不一样。runif(20) 表示生成20个0到1之间的随机数

            #rnorm(n/g,runif(1)*i^2) 表示总共生成n/g个随机数,且每个随机数的大小为runif(1)*i^2

           #lapply(1:g,function(i) rnorm(n/g,runif(1)*i^2)) 表示总共生成与(1:g)*(n/g)长度相同的列表,且列表中的数字为runif(1)*i^2,其中i的取值为1:g。

           #x=unlist(lapply(1:g,function(i) rnorm(n/g,runif(1)*i^2))) 标识把列表简化为向量

dim(d)

 

class(d)

 

#步骤2 计算簇类数k

library(cluster)

library(fpc)

pamk.best<-pamk(d)  #判断是否存在多个聚类

 

par(mfrow=c(1,2))  #设置画布展示,1行2张图

cat("number of clusters estimated by optimum average silhouette width:",pamk.best$nc,"\n") #cat表示连接

plot(pam(d,pamk.best$nc),main="")  #pam(x,k)将数据x划分为k个聚类

#这两个组成部分解释了100%的点变异性

 

#此图表示最佳平均轮廓宽度簇类数估计,从簇类数估计看,簇类设置为4类为最佳

 

#步骤3 聚类结果展示及其可视化

par(mfrow=c(1,1))

c1<-kmeans(d,pamk.best$nc)

c1

 

plot(d,col=c1$cluster)+points(c1$centers,col=3:6,pch=12,cex=1)

#plot(d,col=c1$cluster) 画出聚类结果

#points(c1$centers,col=3:6,pch=12,cex=1) 画出每个聚类的中心,且设置颜色col,设置参数控制符号(图中的四方格)pch,设置控制符号和文字的大小cex

 

案例1:k-means聚类算法在NCI60数据集上的应用

#NCI60数据集由64个细胞系的6830个基因表达数据构成,每个细胞系都有一个标签变量记录了其癌细胞的类型

library(ISLR)

nci.labs<-NCI60$labs

nci.data<-NCI60$data

#在进行 PCA 和聚类分析时,由于是无指导约学习,不使用癌细胞的类型特征,在 PCA和聚类分析之后,可以用这些特征检验无指导学习的结果与癌细胞类型的匹配度。

dim(nci.data)

 

nci.labs[1:4] #查看癌细胞系的类型

 

table(nci.labs) #列出癌细胞的类型

 

set.seed(2)

km.out<-kmeans(sd.data, 4, nstart=20) #k均值聚类法

km.clusters<-km.out$cluster

table(km.clusters,hc.clusters)

 

案例2:k-means聚类算法在iris数据集上的应用

#鸢尾花数据集

require("stats")

model<-kmeans(x=subset(iris,select = -Species),centers = 3)

table(iris$Species,model$cluster,dnn=c("Actual","predicted"))

  

#如何确定聚类数

  聚类就像切西瓜,切几瓣真的很随意,但是我们也可以使用一些方法评估一下应该聚几类,比如轮廓系数,它结合了内聚度和分离度两种因素,即同时考察了组内相似性和组间差异性,可见轮廓系数的值介于[-1,1],越趋近于1代表内聚度和分离度都相对较优

#(1)轮廓系数

library(cluster)

asw<-numeric(20) #生成一个序列

for(k in 2:20){  #测试聚类2-20的可能性

  asw[[k]]<-pam(subset(iris,select = -Species),k)$silinfo$avg.width

}

k.best<-which.max(asw) #找出最大的聚类数

cat("通过轮廓系数(silhouette)估计的最佳聚类数:",k.best,"\n") #输出最佳聚类数

 

#2)中心划分法(PAM)

library(fpc)

library(cluster)

pamk.best<-pamk(subset(iris,select = -Species))

cat("通过中心化分法估计的最佳聚类数:",pamk.best$nc,"\n") #输出最佳聚类数


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM