目录

聚类相关理论

动态聚类vs系统聚类        

基本思想

基本操作步骤_系统聚类

基本操作步骤_动态聚类

重要距离

R语言代码实现_层次聚类

R语言代码实现_kmeans聚类

R语言代码实现_KNN聚类

聚类相关理论

        聚类分析是研究分类问题的多元统计方法。主要分为层次聚类(即系统聚类)和动态聚类。

        合理的聚类的关键:使得同一类别内的观测尽可能地“相似”,但不同类别之间有明显区分。

动态聚类vs系统聚类        

        系统聚类法是一种比较成功的聚类方法。然而当样本点数量十分庞大时,则是一件非常繁重的工作,且聚类的计算速度也比较慢。比如在市场抽样调查中,有4万人就其对衣着的偏好作了回答,希望能迅速将他们分为几类。这时,采用系统聚类法就很困难,而动态聚类法就会显得方便,适用。动态聚类使用于大型数据。

基本思想

        系统聚类:先将n个样品各自看成一类,然后规定样品之间的“距离”和类与类之间的距离。选择距离最近的两类合并成一个新类,计算新类和其它类(各当前类)的距离,再将距离最近的两类合并。这样,每次合并减少一类,直至所有的样品都归成一类为止

        动态聚类:选取若干个样品作为凝聚点,计算每个样品和凝聚点的距离,进行初始分类,然后根据初始分类计算其重心,将重心作为新的凝聚点再进行第二次分类,一直到所有样品不再调整为止。

基本操作步骤_系统聚类

        1. 计算n个样品两两间的距离

        2.构造n个类,每个类只包含一个样品。

        3. 合并距离最近的两类为一新类。

        4. 计算新类与各当前类的距离。

        5. 重复步骤3、4,合并距离最近的两类为新类,直到所有的类并为一类为止。

        6. 画聚类谱系图。

        7. 决定类的个数和类。

基本操作步骤_动态聚类

        1.选择凝聚点

        2.初始分类:以每个凝聚点为类别中心,将其他观测按照距离最近原则归入凝聚点类别。

        3.调整分类:得到初始分类,计算各类的重心,以这些重心作为新的凝聚点,重新进行分类,重复步骤2、3,直到分类的结果与上一步的分类结果相同,表明分类已经合理为止。

重要距离

        相似度的度量:明氏距离(街区距离、欧氏距离、切比雪夫距离)、标准化欧式距离、马氏距离。

        类的合并方法(类与类之间的距离):最短距离法(也叫简单连接法)、最长距离(也叫完全连接法)、中间距离(也叫平均连接法)、重心法(重心连接法) 、类平均法、离差平方和(Ward法)。

R语言代码实现_层次聚类

        dist几种距离:"euclidean"欧氏距离, "maximum", "manhattan", "canberra"坎贝拉距离, "binary"二进制距离 or "minkowski"闵可夫斯基距离。

#距离矩阵的生成
data(iris)
head(iris)
rownames(iris)=paste0("x_",1:150)

#生成距离矩阵
d = dist(iris[,1:4],method = "euclidean") 
class(d)  
#d
md = as.matrix(d) 
#md

        系统聚类的核心函数 hclust(d, method = "complete", members = NULL)

        其中 d:为距离矩阵 ;method: 表示类的合并方法

  • single最短距离法: 一个类中的点和另一个类中的点的最小距离
  • complete最长距离法: 一个类中的点和另一个类中的点的最大距离
  • median中间距离法: 一个类中的点和另一个类中的点的平均距离
  • mcquitty相似分析法
  • average平均距离法:测量两类每对观测间的平均距离
  • centroid重心法:两类间的距离定义为两类重心之间的距离
  • ward离差平方和法:基于方差分析思想,如果分类合理,则同类样品间离差平方和应当较小,类与类间离差平方和应当较大
#系统聚类
iris.hc1 <- hclust(d,"single")
print(iris.hc1)
plot(iris.hc1,hang = -1)
#plot(iris.hc1,hang = -1,cex=0.9)

iris.hc2 <- hclust(d,"complete")
print(iris.hc2)
plot(iris.hc2,hang = -1)

iris.hc3 <- hclust(d,"ward.D")
print(iris.hc3)
plot(iris.hc3,hang = -1)

par(mfrow=c(1,3))
plot(iris.hc1,hang = -1)
plot(iris.hc2,hang = -1)
plot(iris.hc3,hang = -1)

#将聚类结果划分
par(mfrow=c(1,1))
plot(iris.hc1,hang = -1)
#rect.hclust为聚类分析结果画框
rect.hclust(iris.hc1,k=3, border = "red")
re1 <- rect.hclust(iris.hc1,k=3)
re1
plot(iris.hc1,hang = -1)
rect.hclust(iris.hc1, h=0.75,which=c(1,3))
rect.hclust(iris.hc1, h=0.75,which=c(1,3), border =c("green","red"))
re2 <- rect.hclust(iris.hc1, h=0.75,which=c(1,3), border = 2:3)
re2

# 返回值的标签,根据分类数
iris.id1 <- cutree(iris.hc1,k=3);iris.id1 
#iris.id1 <- cutree(iris.hc1,h=0.31);iris.id1
#iris.id1 <- cutree(iris.hc1,k=2:5);iris.id1 
table(iris.id1)

#返回值的标签,根据分类数
iris.id2 <- cutree(iris.hc2,k=3);iris.id2
table(iris.id2)

#查看与已有标签对比,参考聚类效果
table(iris$Species)
table(iris.id1,iris$Species)
table(iris.id2,iris$Species)

#查看原始数据分布情况
plot(iris$Sepal.Length,iris$Sepal.Width)
plot(iris$Sepal.Length,iris$Sepal.Width,col=iris$Species)
plot(iris[,1:4],col=iris$Species)
#如果觉得横坐标标签太多了,可以去掉
plot(iris.hc1,labels = FALSE,hang = -1)

R语言代码实现_kmeans聚类

        核心函数 kmeans(x, centers, iter.max = 10, nstart = 1,algorithm = c("Hartigan-Wong", "Lloyd", "Forgy", "MacQueen"), trace=FALSE)

        其中 x:数据矩阵 ;centers: 类别数或各类初始中心;iter.max 最大迭代次数,nstart:随机起点数。

#kmeans 聚类
km1 = kmeans(iris[,1:4],3)
km1
km1$cluster
km1$centers

km2 = kmeans(scale(iris[,1:4]),3,nstart = 25)
km2
table(km2$cluster,iris$Species)
table(km1$cluster,iris$Species)

R语言代码实现_KNN聚类

        核心函数KNN(x, k, sort = TRUE, search = "kdtree", bucketSize = 10, splitRule = "suggest", approx = 0);

install.packages("dbscan");
library(dbscan);
#去掉种属列
iris2 <- iris[, -5];
head(iris2);

#查询最近邻的5个点
nn <- kNN(iris2, k=5);
nn;

#查询nn的属性列表
attributes(nn);
head(nn$id); ##索引值
head(nn$dist); ##距离值

#设置索引
idx<-33;
#打印与33,最近邻的5个点的索引
nn$id[idx,];

#画图
cols = ifelse(1:nrow(iris2) %in% nn$id[idx,],"red", "black")
cols[idx]<-'blue'
plot(iris2,pch = 19, col = cols)
plot(nn, iris2)
plot(kNN(nn, k = 2), iris2)