可视化:RStudio 聚类分析 - 层次聚类

337 阅读3分钟

本文已参加「新人创作礼」活动,一起开启掘金创作之路。

这次带来的是 RStudio 的聚类分析 - 层次聚类。

高维空间中的距离

对于高维空间中的点(或者向量), 我们经常需要计算他们之间的远近关系, 这就涉及到如何定义高维空间中的远近关系.

下面是一些常用的描述点与点之间远近关系的度量:

  • Minkowski(Manhattan, Euclidean, Maximum, …)
  • Mahalanobis
  • Canberra
  • cosine
  • correlation

其中前面3类属于距离类的度量, 后面2类属于相似关系的度量.

对于距离类的度量, 一般要求满足下面四个条件:

image.png

Minkowski

Minkowski距离是欧式距离在高维空间中的一个推广, 它的定义如下:

image.png

# 练习
# 数据集: iris (前四个变量)
# 求出在每一种度量定义(用至少4种度量)下的距离矩阵
# 并求出每一种定一下的:
# 哪两个样本最接近
# 哪两个样本最不接近

# 以 Manhattan 距离为例
d1 = dist(iris[,1:4], method="manhattan")
m1 = as.matrix(d1)
m1[1:10,1:10]
min(m1); max(m1)
which(m1 == max(m1)) # 找出位置(注意得到的是向量中的位置, 而非矩阵中的位置)
nc = 3419 %/% 150; nr = 3419 %% 150 # 找出行列位置
m1[nr, nc+1]

which(m1 == min(m1)) # 找出位置(注意得到的是向量中的位置, 而非矩阵中的位置)
# 思考为什么会有这么多?  # 应该怎么做
diag(m1) = 999
which(m1 == min(m1)) # 找出位置(注意得到的是向量中的位置, 而非矩阵中的位置)
nc = 15293 %/% 150; nr = 15293 %% 150 # 找出行列位置
m1[nr, nc+1]


# 以 cosine (向量的夹角余弦) 距离为例
cosine_dist = function(x,y){
  x = as.vector(x); y = as.vector(y) # 强制转成向量
  cosine_dist = sum(x * y) / sqrt(sum(x^2) * sum(y^2))
  return(as.vector(cosine_dist))
}

d2 = matrix(NA, nrow = 150, ncol = 150)
for(i in 1:150){
  for(j in 1:150){
    d2[i,j] = cosine_dist(iris[i,1:4], iris[j,1:4])
  }
}

聚类分析: Hierarchical Clustering (层次聚类)

层次聚类/系统聚类 将数据集中的每个样本初始化为一个类, 然后找到距离最近的两个类, 将他们合并, 不断重复这个过程, 直到所有样本都合并为一类.

层次聚类的算法中需要用到两个距离:

  1. 样本与样本之间的距离, 参考上一节
  2. 类与类之间的距离, 常用的有:
  • single (最短距离法): 两类之间最近的样本之间的距离
  • complete (最长距离法): 两类之间最远的样本之间的距离
  • median (中间距离法): 为最短距离和最长距离的折中
  • centroid (重心法): 两类的重心之间的距离
  • average (类平均法): 两类样本两两之间的距离的平均值
  • ward (Ward法): 两类样本合并前后的离差平方和

选择好了样本与样本之间的距离类与类之间的距离之后, 就可以进行层次聚类, 步骤如下:

  1. 每一个样本为一类,算出所有类两两之间的距离(使用样本与样本之间的距离)
  2. 找出距离最近的两个类, 合并为一类
  3. 重新计算目前的所有类两两之间的距离(使用类与类之间的距离)
  4. 重复步骤2和步骤3, 直到所有样本都合并成一类

范例:

image.png

层次聚类的R代码

# --- 将iris的随机100个样本进行层次聚类 ---

# 1. 每一个样本为一类,算出所有类两两之间的距离(使用`样本与样本之间的距离`)
dmat = dist(iris[sample(150,100), 1:4], method = "euclidean") # 可以设定"样本与样本之间的距离函数""

# 2. 根据层次聚类算法, 依次合并最近的类
hc = hclust(dmat, method = "single") # 可以设定"类与类之间的距离函数"

# 3. 聚类结果可视化
plot(hc)

# 4. 判断要聚为几类
rhc = rect.hclust(hc, k = 2)

# 5. 查看聚类结果, 每一个样本被归为哪一个类
rhc