哈喽,我是小白~
今儿和大家来聊聊层次聚类的内容~
首先来说,聚类算法是一种无监督学习算法,用于将一组数据按照它们的相似性划分成不同的组(称为“簇”)。它不会依赖预先定义的标签,而是自动根据数据本身的特性发现这些组。
聚类就像把一堆东西分类整理,比如按照颜色、大小、形状把玩具分成不同的篮子。
如果需要本文PDF版本的同学,文末获取~
另外,文末有总结性的干货~
一起来看下具体细化内容~
层次聚类是聚类算法的一种,它会一步步地将数据点聚合到一起,形成一棵“聚类树”(称为树状图,dendrogram)。根据需求,可以在不同的层级选择划分结果。
层次聚类 是什么?
层次聚类有两种主要方式:
1. 凝聚式(自底向上):每个数据点开始作为一个独立的簇,逐步将最近的簇合并,直到只剩一个大簇。 2. 分裂式(自顶向下):从一个大簇开始,将其逐步拆分成更小的簇。
通俗案例:聚餐座位分配
场景:假设你是一家餐馆老板,餐厅里来了6位顾客,他们互相认识的程度(即亲密关系)如下:
A和B非常熟(距离=1) A和C有点熟(距离=3) B和C也有点熟(距离=3) A和D不太熟(距离=6) B和D完全不熟(距离=9) 其他两两之间关系如下表:
人 | A | B | C | D | E | F |
---|---|---|---|---|---|---|
A | 0 | 1 | 3 | 6 | 9 | 9 |
B | 1 | 0 | 3 | 9 | 9 | 9 |
C | 3 | 3 | 0 | 9 | 9 | 9 |
D | 6 | 9 | 9 | 0 | 2 | 3 |
E | 9 | 9 | 9 | 2 | 0 | 1 |
F | 9 | 9 | 9 | 3 | 1 | 0 |
目标:把这些人分成若干组,关系更近的坐在一起。
手动示例
1. 初始状态
每个人都是一个独立的簇:
2. 找最近的两个人
从距离矩阵中,找到最近的两个人:
A和B之间的距离是1,是最小的。
于是合并成一个簇:
3. 更新距离矩阵
更新簇和其他人的距离。常见方法是最小距离法,即取簇中任意两点的最小距离:
到C:最小距离是3。 到D:最小距离是6。 到E和F:最小距离是9。
更新后的距离矩阵:
簇 | {A,B} | C | D | E | F |
---|---|---|---|---|---|
{A,B} | 0 | 3 | 6 | 9 | 9 |
C | 3 | 0 | 9 | 9 | 9 |
D | 6 | 9 | 0 | 2 | 3 |
E | 9 | 9 | 2 | 0 | 1 |
F | 9 | 9 | 3 | 1 | 0 |
4. 重复步骤
再次寻找最近的两个:
E和F的距离是1。
合并成一个簇:
更新距离矩阵:
到D:最小距离是2。
继续:
和C的距离是3。 和D的距离是2。
最终可构造树状图,将人群分成更大的簇直到合并成一个。
总结
层次聚类像是搭积木,根据“距离”逐步合并,最终形成一个分类树。你可以在任何层级“剪开”,得到需要的簇。例如:
剪成2簇: 剪成3簇:
公式解析
层次聚类的核心在于定义簇之间的相似性(或距离),并逐步合并最近的簇。以下是具体推导过程。
1. 问题定义
给定数据集 ,其中 ,我们需要将数据划分成 个簇,使得:
同簇的数据点尽可能相似。 不同簇的数据点尽可能不同。
基本目标:通过一系列的合并操作生成一个树状结构(树状图,dendrogram)。
2. 距离的定义
在聚类中,核心是定义两点或两簇之间的距离。常见的距离计算方法包括:
点之间的距离:
欧几里得距离:
曼哈顿距离:
簇之间的距离:
假设 和 是两个簇,簇中的点集合分别是 和 。常见定义方式有: 1. 最小距离法(Single Linkage):
适合找“紧密连接”的簇。
2. 最大距离法(Complete Linkage):
更强调“整体分离”。
3. 平均距离法(Average Linkage):
考虑两簇之间所有点的平均距离。
4. 质心距离法(Centroid Linkage):
其中,质心 $ \mu_1 = \frac1}{ \sum_{x_i \in C_1} x_i $,质心距离计算较快,但可能不适合非凸形状。
3. 层次聚类算法步骤
输入
数据点集合 ,距离度量 ,簇间距离定义(如最小距离)。
输出
生成的树状图或任意层次的簇划分。
算法流程
1. 初始化: 每个点单独成为一个簇,记为 。
2. 计算距离矩阵: 计算所有簇之间的初始距离,构造距离矩阵 ,其中 。
3. 合并簇:
找到距离矩阵中最小值对应的簇 。 合并 成新簇 。 更新距离矩阵: 根据选择的距离度量方式(如最小距离),重新计算 。
4. 重复步骤3: 直到簇数量减少到1或达到预期层次。
5. 输出: 生成一棵树状图。
4. 数学公式推导
(1) 距离矩阵更新公式
假设当前簇为 ,合并 后形成新簇 ,剩下的簇为 。
新簇 到其他簇 的距离 更新公式取决于距离度量:
最小距离法:
最大距离法:
平均距离法:
(加权平均)。
(2) 复杂度分析
1. 初始距离矩阵计算:
需要计算两两点之间的距离。
2. 合并操作: 在每次合并中更新距离矩阵,涉及 次操作,共 次合并:
因此,层次聚类的时间复杂度为 ,对大规模数据集计算效率较低。
5. 示例推导
输入数据: 。
步骤:
1. 初始化距离矩阵(欧几里得距离):
2. 合并最近的点:
合并 和 ,生成新簇 。 更新距离矩阵,重复。
最终生成的树状图可根据需要划分层次。
优缺点和适用场景
优点
1. 可解释性强:层次聚类通过生成树状图(Dendrogram)展现数据的分层结构,直观显示数据的分组关系。便于分析簇的形成过程和相似性。
2. 无需预设簇数量:与 -均值聚类等方法不同,不需要事先指定簇的数量,适用于对未知数据的探索。
3. 适合发现分层结构:如果数据具有自然的层次或嵌套关系(如家族谱系、生物分类),层次聚类可以很好地捕捉这种结构。
4. 对噪声点更鲁棒:相比密度聚类,层次聚类对小规模的噪声点影响较小,尤其是“单链”或“全链”方法。
5. 灵活的距离定义:支持多种簇间距离计算方式(单链、全链、平均等),能够根据任务需求调整方法。
缺点
1. 时间复杂度高:典型的时间复杂度为 ,存储复杂度为 ,对大规模数据不适用。
2. 合并不可逆:一旦将两个点或簇合并,无法撤回。初始合并错误可能影响最终结果。
3. 对距离度量敏感:不同的距离度量方法会显著影响结果,选择不当可能导致误差。
4. 无法处理非凸簇:由于基于距离,层次聚类难以处理非凸形状的簇(如环形、蛇形)。
5. 缺乏中心:层次聚类无法提供簇的“中心”点或代表性样本,不适合用来直接生成摘要信息。
适用场景
数据量较小(通常 )。 对数据分层结构或嵌套关系感兴趣。 无需明确的簇数量,或者簇数量未知。 数据的特性适合距离度量(如空间分布、生物特性等)。
完整案例
基于市场细分(消费者行为聚类),我们下面来实现具体细节:
1. 生成模拟消费者数据:包含年龄、收入、购买频率等。 2. 应用层次聚类算法:生成聚类结果。 3. 生成两个图形:
聚类结果的二维投影(使用PCA降维):通过颜色区分不同的簇。 树状图(Dendrogram):展示层次聚类的分层结构。
代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 设置随机种子,生成消费者数据
np.random.seed(42)
n_samples = 10000
# 模拟消费者数据:年龄、收入、购买频率
age = np.random.randint(18, 70, n_samples)
income = np.random.normal(50000, 15000, n_samples).astype(int)
purchase_frequency = np.random.randint(1, 20, n_samples)
# 创建数据框
data = pd.DataFrame({
'Age': age,
'Income': income,
'PurchaseFrequency': purchase_frequency
})
# 数据标准化
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
# 层次聚类
linkage_matrix = linkage(data_scaled, method='ward') # Ward方法最常用
# 从层次聚类中提取实际的聚类标签
n_clusters = 5 # 假设分为5个聚类
labels = fcluster(linkage_matrix, t=n_clusters, criterion='maxclust') # 提取聚类标签
# 图形1: 聚类结果的二维投影
# 使用PCA将数据降维至2D
pca = PCA(n_components=2)
data_pca = pca.fit_transform(data_scaled)
plt.figure(figsize=(12, 8))
plt.scatter(data_pca[:, 0], data_pca[:, 1], c=labels, cmap='Spectral', s=50, alpha=0.7)
plt.title('Cluster Visualization (PCA Projection)', fontsize=18)
plt.xlabel('PCA Component 1', fontsize=12)
plt.ylabel('PCA Component 2', fontsize=12)
plt.colorbar(label='Cluster ID', shrink=0.8)
plt.grid(True)
plt.show()
# 图形2: 树状图(Dendrogram)
plt.figure(figsize=(16, 10))
dendrogram(linkage_matrix, truncate_mode='lastp', p=10, leaf_rotation=90, leaf_font_size=12, show_contracted=True)
plt.title('Dendrogram for Hierarchical Clustering', fontsize=18)
plt.xlabel('Cluster Size', fontsize=12)
plt.ylabel('Distance (Ward\'s Method)', fontsize=12)
plt.show()
PCA投影后的聚类结果:数据被降维至二维平面,使用颜色标识不同簇。图中展示了层次聚类的分组效果。
树状图(Dendrogram):展示了层次聚类的分层结构,显示不同簇的合并过程。可以通过剪切树状图来决定分组数量。
最后