Alex_McAvoy

想要成为渔夫的猎手

层次聚类

【概述】

层次聚类(Hierarchical Clustering)假设类别之间存在层次结构,将样本聚类到层次化的簇中,由于每个样本只属于一个簇,因此层次聚类属于硬聚类

其是通过计算不同类别的数据点间的相似度,来创建一棵有层次的嵌套聚类树,在聚类完成后,可在任意层次进行切分,以得到指定数目的簇

层次聚类距离和规则的相似度容易定义,限制较小,而且不需要预先指定聚类的簇数,同时可以发现簇间的层次关系,但是其计算复杂度较高,奇异值会造成较大影响,算法最终可能会聚类成链状

【基本原理】

按照层次分解是自下而上,还是自上而下,层次聚类方法可分为以下两种:

  • 自下而上的凝聚(Agglomerative)方法:将数据集的每个样本点都看成一个簇,然后找出距离最小的两个簇进行合并,不断重复到预期簇或者其他终止条件
  • 自上而下的分裂(Divisive)方法:将数据集的样本点当作一整个簇,然后找出簇中距离最远的两个簇进行分裂,不断重复到预期簇或者其他终止条件

凝聚方法的代表算法是凝聚嵌套(Agglomerative Nesting,AGNES)算法,分裂方法的代表算法是分裂分析(Divisive Analysis,DIANA)算法,两者的聚类图示如下

综上,可以发现层次聚类需要预先确定如下三个要素:

  1. 距离
  2. 合并/分裂规则
  3. 停止条件

根据以上三个要素的不同组合,就可以构造出不同的层次聚类方法

一般来说,距离可以是欧氏距离、相关系数、余弦距离等;合并/分裂规则通常是簇间距离最小/最大,而簇间距离可以是最短距离、最长距离、中心距离、平均距离等;停止条件可以是簇的个数达到阈值、簇的直径超过阈值等

【sklearn 实现】

sklearn 中的鸢尾花数据集为例,选取其后两个特征来实现利用 AGNES 聚类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering
from scipy.spatial.distance import cdist
from matplotlib.colors import ListedColormap

# 特征提取
def deal_data():
iris = load_iris() # sklearn的鸢尾花数据集
# iris分为三类,前50行一类,51-100行一类,101-150行一类
X = iris.data[:, [2, 3]] # 选用后两个特征作为样本特征
return X

# 数据标准化
def standard_scaler(X):
sc = StandardScaler() # 初始化一个sc对象去对数据集作变换
scaler = sc.fit(X) # 归一化,存有计算出的均值和方差
X_std = scaler.transform(X) # 利用 scaler 进行标准化
return X_std

# 模型训练
def train_model(features, k):
# 建立聚类器
model = AgglomerativeClustering(linkage='ward', n_clusters=k)
# 聚类
model.fit(features)
return model

# 可视化
def visualization(X, y):
# 创建 color map
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])

# 全数据集,不同类别样本点的特征作为坐标(x,y),用不同颜色画散点图
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=cmap(idx), marker=markers[idx], label=cl)

plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()


if __name__ == "__main__":
# 数据处理
X = deal_data()

# 数据标准化
X_std = standard_scaler(X)

# 模型训练
k = 3
model = train_model(X_std, k)

# 获取聚类标签
label_pred = model.labels_

# 可视化
visualization(X_std, label_pred)
感谢您对我的支持,让我继续努力分享有用的技术与知识点!