本文已参加「新人创作礼」活动,一起开启掘金创作之路。
这次带来的是 RStudio 的聚类分析 - 层次聚类。
高维空间中的距离
对于高维空间中的点(或者向量), 我们经常需要计算他们之间的远近关系, 这就涉及到如何定义高维空间中的远近关系.
下面是一些常用的描述点与点之间远近关系的度量:
- Minkowski(Manhattan, Euclidean, Maximum, …)
- Mahalanobis
- Canberra
- cosine
- correlation
其中前面3类属于距离类的度量, 后面2类属于相似关系的度量.
对于距离类的度量, 一般要求满足下面四个条件:
Minkowski
Minkowski距离是欧式距离在高维空间中的一个推广, 它的定义如下:
# 练习
# 数据集: 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 (层次聚类)
层次聚类/系统聚类 将数据集中的每个样本初始化为一个类, 然后找到距离最近的两个类, 将他们合并, 不断重复这个过程, 直到所有样本都合并为一类.
层次聚类的算法中需要用到两个距离:
- 样本与样本之间的距离, 参考上一节
- 类与类之间的距离, 常用的有:
single(最短距离法): 两类之间最近的样本之间的距离complete(最长距离法): 两类之间最远的样本之间的距离median(中间距离法): 为最短距离和最长距离的折中centroid(重心法): 两类的重心之间的距离average(类平均法): 两类样本两两之间的距离的平均值ward(Ward法): 两类样本合并前后的离差平方和
选择好了样本与样本之间的距离和类与类之间的距离之后, 就可以进行层次聚类, 步骤如下:
- 每一个样本为一类,算出所有类两两之间的距离(使用
样本与样本之间的距离) - 找出距离最近的两个类, 合并为一类
- 重新计算目前的所有类两两之间的距离(使用
类与类之间的距离) - 重复步骤2和步骤3, 直到所有样本都合并成一类
范例:
层次聚类的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