目录
层次聚类概述
层次聚类(Hierarchical Clustering)是一种无监督学习的聚类分析方法,用于将数据集中的样本或观测值划分为不同的群集或簇。它通过计算样本之间的相似性或距离来进行聚类,并且可以根据相似性的程度来构建层次结构。
通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中,不同类别的原始数据点是树的最低层,树的顶层是一个聚类的根节点。创建聚类树有自下而上合并和自上而下分裂两种方法。
论数据集应该聚类成多少个簇,通常是在讨论我们在什么尺度上关注这个数据集。层次聚类算法相比划分聚类算法的优点之一是可以在不同的尺度上(层次)展示数据集的聚类情况。
层次聚类有两种主要的方法:凝聚聚类和分裂聚类。
-
凝聚聚类(Agglomerative Clustering)是一种自底向上的聚类方法,它从单个样本开始,逐渐合并相似的样本或簇,直到形成最终的聚类结果。凝聚聚类的步骤如下:
- 计算样本之间的相似性或距离。
- 将每个样本作为一个单独的簇。
- 不断合并最相似的簇,直到达到预设的停止条件(如设定簇的数量或某个相似性阈值)。
凝聚聚类的结果是一棵二叉树,称为聚类树或树状图,其中每个节点表示一个样本或簇,较低层次的节点表示较小的簇,较高层次的节点表示更大的簇。
-
分裂聚类(Divisive Clustering)是一种自顶向下的聚类方法,它从整个样本集开始,逐渐划分为更小的簇,直到每个簇只包含一个样本。分裂聚类的步骤如下:
- 计算样本之间的相似性或距离。
- 将整个样本集视为一个簇。
- 选择一个合适的划分方法,将当前簇划分为较小的子簇。
- 对每个子簇递归地应用划分方法,直到每个簇只包含一个样本或达到预设的停止条件。
自底向上的合并算法
层次聚类的合并算法通过计算两类数据点间的相似性,对所有数据点中最为相似的两个数据点进行组合,并反复迭代这一过程。简单的说层次聚类的合并算法是通过计算每一个类别的数据点与所有数据点之间的距离来确定它们之间的相似性,距离越小,相似度越高。并将距离最近的两个数据点或类别进行组合,生成聚类树。
相似度计算
层次聚类使用欧式距离来计算不同类别数据点间的距离(相似度)。
实例
分别计算欧式距离值(矩阵)
将数据点B与数据点C进行组合后,重新计算各类别数据点间的距离矩阵。数据点间的距离计算方式与之前的方法一样。这里需要说明的是组合数据点(B,C)与其他数据点间的计算方法。当我们计算(B,C)到A的距离时,需要分别计算B到A和C到A的距离均值。
经过计算数据点D到数据点E的距离在所有的距离值中最小,为1.20。这表示在当前的所有数据点中(包含组合数据点),D和E的相似度最高。因此我们将数据点D和数据点E进行组合。并再次计算其他数据点间的距离。
后面的工作就是不断的重复计算数据点与数据点,数据点与组合数据点间的距离。这个步骤应该由程序来完成。这里由于数据量较小,我们手工计算并列出每一步的距离计算和数据点组合的结果。
两个组合数据点间的距离
计算两个组合数据点间距离的方法有三种,分别为Single Linkage,Complete Linkage和Average Linkage。在开始计算之前,我们先来介绍下这三种计算方法以及各自的优缺点。
-
Single Linkage:方法是将两个组合数据点中距离最近的两个数据点间的距离作为这两个组合数据点的距离。这种方法容易受到极端值的影响。两个很相似的组合数据点可能由于其中的某个极端的数据点距离较近而组合在一起。
-
Complete Linkage:Complete Linkage的计算方法与Single Linkage相反,将两个组合数据点中距离最远的两个数据点间的距离作为这两个组合数据点的距离。Complete Linkage的问题也与Single Linkage相反,两个不相似的组合数据点可能由于其中的极端值距离较远而无法组合在一起。
-
Average Linkage:Average Linkage的计算方法是计算两个组合数据点中的每个数据点与其他所有数据点的距离。将所有距离的均值作为两个组合数据点间的距离。这种方法计算量比较大,但结果比前两种方法更合理。
我们使用Average Linkage计算组合数据点间的距离。下面是计算组合数据点(A,F)到(B,C)的距离,这里分别计算了(A,F)和(B,C)两两间距离的均值。
层次聚类实例
import pandas as pd
seeds_df = pd.read_csv('./datasets/seeds-less-rows.csv')
seeds_df.head()
seeds_df.grain_variety.value_counts()
varieties = list(seeds_df.pop('grain_variety'))
samples = seeds_df.values
#距离计算的 还有树状图
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt
#进行层次聚类
mergings = linkage(samples, method='complete')
#树状图结果
fig = plt.figure(figsize=(10,6))
dendrogram(mergings,
labels=varieties,
leaf_rotation=90,
leaf_font_size=6,
)
plt.show()
#得到标签结果
#maximum height自己指定
from scipy.cluster.hierarchy import fcluster
labels = fcluster(mergings, 6, criterion='distance')
df = pd.DataFrame({'labels': labels, 'varieties': varieties})
ct = pd.crosstab(df['labels'], df['varieties'])
#不同距离的选择会产生不同的结果
import pandas as pd
scores_df = pd.read_csv('./datasets/eurovision-2016-televoting.csv', index_col=0)
country_names = list(scores_df.index)
scores_df.head()
#缺失值填充,没有的就先按满分算吧
scores_df = scores_df.fillna(12)
from sklearn.preprocessing import normalize
samples = normalize(scores_df.values)
samples
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt
mergings = linkage(samples, method='single')
fig = plt.figure(figsize=(10,6))
dendrogram(mergings,
labels=country_names,
leaf_rotation=90,
leaf_font_size=6,
)
plt.show()
mergings = linkage(samples, method='complete')
fig = plt.figure(figsize=(10,6))
dendrogram(mergings,
labels=country_names,
leaf_rotation=90,
leaf_font_size=6,
)
plt.show()
K-MEANS 算法
K-Means算法是一种无监督学习算法,用于将数据集划分为K个互不重叠的簇(cluster)。
基本概念
1.要得到簇的个数,需指定K值
2.质心:均值,即向量各维度取平均
3.距离的度量:常用欧氏距离和余弦相似度(需先标准化)
4.优化目标
工作流程
优势:简单、快速、适合常规数据集
劣势:K值难确定、对初始值的稳定性效果极差需要多做几次实验求平均值、复杂度与样本呈线性关系、很难发现任意(比较奇怪)形状的簇。
K-Means算法的目标是最小化簇内数据点与各自簇中心的距离之和(也被称为“簇内平方和”或“SSE”)。它是一种迭代的过程,不保证找到全局最优解,因此初始聚类中心的选择会对结果产生影响。
K-Means算法实例
import pandas as pd
df = pd.read_csv('./datasets/ch1ex1.csv')
points = df.values
df.head()
#散点图观察
import matplotlib.pyplot as plt
xs = points[:,0]
ys = points[:,1]
plt.scatter(xs, ys)
plt.show()
#聚类操作
df = pd.read_csv('./datasets/ch1ex1.csv')
points = df.values
from sklearn.cluster import KMeans
model = KMeans(n_clusters=3)
model.fit(points)
labels = model.predict(points)
labels
#聚类中心
centroids = model.cluster_centers_
centroids_x = centroids[:,0]
centroids_y = centroids[:,1]
plt.scatter(xs, ys, c=labels)
plt.scatter(centroids_x, centroids_y, marker='X', s=200)
plt.show()
K值对结果的影响
import pandas as pd
seeds_df = pd.read_csv('./datasets/seeds.csv')
varieties = list(seeds_df['grain_variety'])
del seeds_df['grain_variety']
seeds_df.head()
samples = seeds_df.values
from sklearn.cluster import KMeans
ks = range(1, 6)
inertias = []
for k in ks:
# Create a KMeans instance with k clusters: model
model = KMeans(n_clusters=k)
# Fit model to samples
model.fit(samples)
# Append the inertia to the list of inertias
inertias.append(model.inertia_)
import matplotlib.pyplot as plt
# Plot ks vs inertias
plt.plot(ks, inertias, '-o')
plt.xlabel('number of clusters, k')
plt.ylabel('inertia')
plt.xticks(ks)
plt.show()
DBSCAN 算法
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种无监督学习算法(传销发展下线算法),用于将数据点划分为不同的密度相连的簇(cluster),并且可以识别噪声数据点。
算法步骤
-
初始化:选择一个未访问的数据点。
-
密度可达(Density-Reachable)和密度相连(Density-Connected):以该数据点为中心,以一个给定的半径(ε)来判断与其距离在半径范围内的数据点是否足够密集,如果密度足够大,那么这些数据点被认为是与该数据点密度可达。如果一个数据点与另一个密度可达的数据点相互之间密度可达,那么它们被认为是密度相连的。
-
核心点(Core Point)和边界点(Border Point):如果一个数据点周围半径范围内的数据点数目大于等于一个给定的阈值(MinPts),那么它被认为是一个核心点。否则,它可能是一个边界点。
-
扩展簇:从一个核心点出发,通过密度可达和密度相连的规则找到所有与之相关的数据点,并将它们分配到同一个簇中。重复该过程,直到无法再找到新的密度相连点。
-
单独点(Noise Points):未归类到任何簇中的数据点被认为是噪声点。
DBSCAN算法的主要优点是可以自动识别任意形状和大小的簇,并且能够有效处理噪声数据。它不需要预先指定簇的数目,并且对初始参数的选择相对不敏感。然而,DBSCAN算法的性能在处理高维数据和不同密度的簇时可能会下降。
在使用DBSCAN时,需要调整两个关键参数:半径(ε)和邻域中的最小数据点数(MinPts)。适当选择这些参数对于获得良好的聚类结果至关重要,并且需要根据具体情况进行实验和调试。
基本步骤
工作流程
参数选择
- 半径ϵ:可以根据K距离来设定:找突变点
- K距离:给定数据集P={p(i); i=0,1,…n},计算点P(i)到集合D的子集S中所有点之间的距离,距离按照从小到大的顺序排序,d(k)就被称为k-距离。
- MinPts: k-距离中k的值,一般取的小一些,多次尝试
优势:
- 不需要指定簇个数
- 可以发现任意形状的簇
- 擅长找到离群点(检测任务)
- 两个参数就够了
劣势:
- 高维数据有些困难(可以做降维)
- 参数难以选择(参数对结果的影响非常大)
- Sklearn中效率很慢(数据削减策略)
可视化小工具:https://www.naftaliharris.com/blog/visualizing-dbscan