您刚接到一项任务,要分析一个大型数据集,并提供深入的聚类分析。您遇到了“层次聚类”这个术语,但它究竟是什么,又是如何工作的?
本文将探讨层次聚类的概念,并给出实际示例,帮助您更好地理解其应用。
什么是层次聚类?
层次聚类是一种 无监督学习 算法,用于将相似的数据点分组为簇。它通过将较小的簇合并为较大的簇(自底向上,凝聚式)或将较大的簇划分为较小的簇(自顶向下,分裂式)来构建多层次的簇层级结构。这会生成一种树状结构,称为树状图(dendrogram)。
树状图是一种可视化表示,用于展示簇的排列及其相互关系。树状图中分支的高度表示簇合并时的距离或不相似度。高度越低表示在较小距离上合并,因而相似度更高。
层次聚类在机器学习中的重要性
当事先不知道簇的数量时,层次聚类尤其有用。它允许 数据分析师 和 数据科学家 通过树状图直观地探索数据结构。
该技术还能发现嵌套簇,广泛应用于基因组学、客户细分和文档组织等领域。
例如,假设我们有一个客户购买记录的数据集。使用层次聚类,我们可以将购买模式相似的客户分组为簇,并识别潜在的市场细分,以制定有针对性的营销策略。
层次聚类 vs K-Means 聚类
在聚类任务中,多数人会在两种主要方法间犹豫:层次聚类或 K-means 聚类 。
它们的区别是什么?我们来看下面的对比以获得更清晰的认识。
K-Means :
在运行前需要定义簇的数量。
对大型数据集效率高、可扩展性好。
假设簇呈球形且大小相近。
层次聚类 :
不需要预先定义簇的数量。
借助树状图更易解释。
在大型数据集上较慢,但更适合探索结构。
对比这两者时,有些方面会让层次聚类更具优势。
以下是层次聚类表现较好的场景:
借助树状图灵活选择簇。
适合小型数据集或需要可视化层级结构的情况。
能够处理复杂的簇形状。
不过,它也存在一些缺点,例如:
您可能会问:什么时候应该使用层次聚类?
层次聚类在以下应用中是绝佳选择:
层次聚类的类型
在层次聚类方法中,您会遇到多种类型,每种都会带来不同的洞察和结果。两种主要类型是凝聚式(自底向上)和分裂式(自顶向下)。
来源: Himanshu Sharma(Medium)
1. 凝聚式(自底向上)
凝聚式聚类从将每个数据点视为一个独立的簇开始,反复合并距离最近的一对簇,直到只剩一个簇,或满足某个停止条件(如达到期望的簇数)。
这种方法也称为自底向上,因为它从底部(单个数据点)开始,逐步构建到顶部(最终簇)。
步骤指南 :
将每个数据点视为单元素簇。
计算所有簇的成对距离。
合并距离最小的两个簇。
更新距离矩阵以反映新的簇集合。
重复步骤 2–4,直到所有点属于同一个簇。
该方法因其简单易实现而被广泛使用。
下面是如何在 Python 中实现的示例:
import numpy as np
from scipy. cluster. hierarchy import linkage, dendrogram, fcluster
import matplotlib. pyplot as plt
data = np. array( [ [ 1 , 2 ] , [ 2 , 3 ] , [ 5 , 8 ] , [ 8 , 8 ] , [ 1 , 0 ] , [ 0 , 1 ] ] )
Z = linkage( data, method= 'ward' )
plt. figure( figsize= ( 8 , 4 ) )
dendrogram( Z)
plt. title( 'Agglomerative Clustering Dendrogram' )
plt. xlabel( 'Data Points' )
plt. ylabel( 'Distance' )
plt. show( )
clusters = fcluster( Z, t= 2 , criterion= 'maxclust' )
print ( "Cluster assignments:" , clusters) 技术支持
2. 分裂式(自顶向下)
分裂式聚类从将所有数据点置于一个簇中开始,并递归地将其划分为更小的簇。该过程持续进行,直到每个数据点都成为单独的簇。
它也被称为自顶向下的方法,因为它从顶部(单一簇)开始,逐步拆分为更小的簇。
步骤指南 :
从包含所有数据点的一个大簇开始。
将该簇拆分为两个差异尽可能大的簇。
对每个得到的簇递归地重新应用拆分过程。
分裂式方法通常因其递归特性而计算开销更大,且准确性在很大程度上取决于拆分策略。凝聚式方法因实现简单且软件支持广泛而更为常见。
注意: 在标准的 Python 库中,分裂式层次聚类不像凝聚式那样易于使用。一种思路是递归使用 k-means 等聚类算法。
下面是模拟递归 k-means 拆分的代码思路:
from sklearn. cluster import KMeans
def divisive_clustering ( data, depth= 2 ) :
if depth == 0 or len ( data) <= 1 :
return [ data]
kmeans = KMeans( n_clusters= 2 , random_state= 42 ) . fit( data)
labels = kmeans. labels_
cluster1 = data[ labels == 0 ]
cluster2 = data[ labels == 1 ]
return divisive_clustering( cluster1, depth - 1 ) + divisive_clustering( cluster2, depth - 1 )
split_clusters = divisive_clustering( data, depth= 2 )
for i, cluster in enumerate ( split_clusters) :
print ( f"Cluster { i+ 1 } size: { len ( cluster) } " ) 技术支持
这段简化代码用递归的 K-means 展示了分裂式聚类的概念性做法。但请注意,标准的分裂方法(如 DIANA)采用不同的拆分准则。
关键概念与术语
层次聚类涉及一些重要的概念与术语。为全面理解该过程,我们将在下文更详细地介绍这些概念。
1. 树状图(Dendrogram)
树状图是一种树形结构,用于可视化层次聚类的过程。树的每一层代表一次合并或拆分操作,分支的高度表示簇被合并时的距离(或不相似度)。
其重要性在于:
允许对不同层级的簇进行可视化检查。
通过在某一高度“切割”树状图,您可以选择最适合数据的簇数量。
2. 连接准则(Linkage)
连接准则决定了在合并过程中如何计算簇与簇之间的距离。
常见的连接准则包括:
单链接(最小)
该准则关注两个簇中最近点之间的距离,可能导致细长、链式的簇。
from scipy. spatial. distance import pdist, squareform
data = np. array( [ [ 1 , 2 ] , [ 2 , 3 ] , [ 5 , 8 ] ] )
distance_matrix = squareform( pdist( data, metric= 'euclidean' ) )
single_linkage_min = np. min ( distance_matrix[ 0 , 1 : ] )
print ( "Single Linkage Distance between Cluster A (point 1) and Cluster B (point 2, 3):" , single_linkage_min) 技术支持
完全链接(最大)
该准则关注两个簇中最远点之间的距离,倾向于产生紧凑、大小均匀的簇。
single_linkage_max = np. max ( distance_matrix[ 0 , 1 : ] )
print ( "Complete Linkage Distance between Cluster A and B:" , single_linkage_max) 技术支持
平均链接(均值)
该准则关注一个簇中所有点到另一个簇中所有点的平均距离,介于单链接与完全链接之间,取得平衡。
average_linkage = np. mean( distance_matrix[ 0 , 1 : ] )
print ( "Average Linkage Distance between Cluster A and B:" , average_linkage) 技术支持
这些简化示例展示了最初如何计算距离。然而在聚类过程中,这些准则(单链接、完全链接、平均链接)是迭代地在整个簇之间应用距离,而不仅是单个点。
Ward 方法
Ward 方法是平均链接的一种变体,最小化所有簇内平方差之和。与其他方法相比,它更倾向于生成大小更均匀的簇,并且常常得到分离良好、近球形的簇。
from scipy. cluster. hierarchy import linkage
linkage_ward = linkage( data, method= 'ward' )
print ( "Ward's Linkage Matrix:\n" , linkage_ward) 技术支持
每种方法都有其优势,应根据数据与用例进行选择。
3. 距离度量
所用的距离度量会显著影响聚类结果。
欧氏距离
欧氏距离 是在多维空间中两点间的直线距离。对几何分布的数据最常用。
曼哈顿距离
曼哈顿距离 , 亦称出租车距离或 L1 距离,是各维度绝对差之和。适用于网格状数据,如城市街区或金融交易。
余弦相似度
余弦相似度 衡量两个非零向量之间夹角的余弦值。当不关心量级(如词频向量)时,此度量非常适合文本数据。
在 Python 中实现层次聚类
本节将演示如何用 Python 实现凝聚式层次聚类。从数据预处理到使用树状图可视化结果,我们将逐步讲解。
依赖库
首先导入所需的库:
import numpy as np
import pandas as pd
from scipy. cluster. hierarchy import dendrogram, linkage, fcluster
from sklearn. preprocessing import StandardScaler
import matplotlib. pyplot as plt技术支持
上面的代码导入了:
numpy 与 pandas:用于数据处理
scipy.cluster.hierarchy:用于聚类与生成树状图
sklearn.preprocessing.StandardScaler:用于特征缩放
matplotlib:用于可视化
示例数据
开始分析之前,我们先创建一个二维点的玩具数据集并进行缩放。对于基于距离的算法,缩放至关重要。
我们的示例数据集如下所示。
data = np. array( [ [ 1 , 2 ] , [ 2 , 3 ] , [ 5 , 8 ] , [ 8 , 8 ] , [ 1 , 0 ] , [ 0 , 1 ] ] )
scaler = StandardScaler( )
data_scaled = scaler. fit_transform( data) 技术支持
以下是缩放后的数据数组。
生成连接矩阵与树状图
我们应用 Ward 方法生成连接矩阵,其中包含层次聚类信息。随后绘制树状图。
linkage_matrix = linkage( data_scaled, method= 'ward' )
plt. figure( figsize= ( 8 , 4 ) )
dendrogram( linkage_matrix)
plt. title( 'Dendrogram' )
plt. xlabel( 'Data Points' )
plt. ylabel( 'Distance' )
plt. show( ) 技术支持
在上述代码中,linkage 构建簇层级结构,dendrogram 用于可视化簇的形成过程。
通过观察合并前最长的竖线位置,我们可以决定在何处“切割”以形成簇。寻找不与其他簇相交的最高竖线处进行切割。
在本例中,您需要切分为 2 个簇。
创建簇
接下来,使用 fcluster 按指定簇数对树状图进行切割:
clusters = fcluster( linkage_matrix, t= 2 , criterion= 'maxclust' )
print ( clusters)
plt. scatter( data_scaled[ : , 0 ] , data_scaled[ : , 1 ] , c= clusters, cmap= 'rainbow' )
plt. title( 'Clusters' )
plt. xlabel( 'Feature 1' )
plt. ylabel( 'Feature 2' )
plt. show( ) 技术支持
这会将每个数据点分配到两个簇中的一个。
有关代码的一些补充说明:
t=2:指定期望的簇数量。
criterion='maxclust':确保获得恰好 t 个簇。
您可以更改 t 以尝试不同的簇数量。
实践示例:客户细分
层次聚类常用于客户细分。我们来看一个实际实现的示例。
1. 数据集概览
我们将模拟一个包含两个特征(年龄与收入)的客户数据集。使用 make_blobs 生成该合成数据。
from sklearn. datasets import make_blobs
X, _ = make_blobs( n_samples= 100 , centers= 3 , n_features= 2 , random_state= 42 ) 技术支持
2. 预处理
接下来我们需要标准化特征,以归一化尺度并提升聚类准确性。
scaler = StandardScaler( )
X_scaled = scaler. fit_transform( X) 技术支持
以下是缩放后的数据:
3. 应用层次聚类
数据处理完毕后,我们绘制树状图以可视化簇的形成。
linkage_matrix = linkage( X_scaled, method= 'ward' )
plt. figure( figsize= ( 10 , 5 ) )
dendrogram( linkage_matrix)
plt. title( 'Customer Dendrogram' )
plt. xlabel( 'Sample Index' )
plt. ylabel( 'Distance' )
plt. show( ) 技术支持
4. 结果解读
根据树状图,我们选择一个高度进行“切割”,创建三个簇:
labels = fcluster( linkage_matrix, t= 3 , criterion= 'maxclust' )
plt. scatter( X_scaled[ : , 0 ] , X_scaled[ : , 1 ] , c= labels, cmap= 'rainbow' )
plt. title( 'Customer Segments' )
plt. xlabel( 'Feature 1' )
plt. ylabel( 'Feature 2' )
plt. show( ) 技术支持
业务启示:
这些簇可能代表注重预算型、中端型和高端型客户群。
支持个性化营销并改进客户关系策略。
层次聚类的优势与局限
在分析中选择层次聚类既有优势也有局限。
以下是一些常见点:
优点
无需预先指定簇数 :可在查看树状图后再行选择。
直观可视化 :树状图有助于理解簇的形成。
灵活性强 :可根据连接方式与距离度量处理多样的簇形状。
缺点
计算量大 :不适合大型数据集。
对噪声与异常值敏感 :少量异常值可能显著扭曲树状图。
不可回溯重分配 :一旦合并无法撤销,可能导致次优聚类。
结论
层次聚类是一种多才多艺且易于解释的聚类技术,尤其适用于探索性数据分析,以及基因组学和客户细分等领域。尽管计算成本较高,其优势在于能够发现嵌套分组,并可通过树状图在事后灵活选择簇的数量。
对于小到中等规模且重视可解释性的数据集,层次聚类仍是数据科学家与分析师的常用方法。
想更深入地学习机器学习的细节?我们的 Python 机器学习基础 学习路径以及 Python 层次聚类入门 教程都是很好的起点。
您刚接到一项任务,要分析一个大型数据集,并提供深入的聚类分析。您遇到了“层次聚类”这个术语,但它究竟是什么,又是如何工作的?
本文将探讨层次聚类的概念,并给出实际示例,帮助您更好地理解其应用。
什么是层次聚类?
层次聚类是一种无监督学习算法,用于将相似的数据点分组为簇。它通过将较小的簇合并为较大的簇(自底向上,凝聚式)或将较大的簇划分为较小的簇(自顶向下,分裂式)来构建多层次的簇层级结构。这会生成一种树状结构,称为树状图(dendrogram)。
树状图是一种可视化表示,用于展示簇的排列及其相互关系。树状图中分支的高度表示簇合并时的距离或不相似度。高度越低表示在较小距离上合并,因而相似度更高。
层次聚类在机器学习中的重要性
当事先不知道簇的数量时,层次聚类尤其有用。它允许数据分析师和数据科学家通过树状图直观地探索数据结构。
该技术还能发现嵌套簇,广泛应用于基因组学、客户细分和文档组织等领域。
例如,假设我们有一个客户购买记录的数据集。使用层次聚类,我们可以将购买模式相似的客户分组为簇,并识别潜在的市场细分,以制定有针对性的营销策略。
层次聚类 vs K-Means 聚类
在聚类任务中,多数人会在两种主要方法间犹豫:层次聚类或K-means 聚类。
它们的区别是什么?我们来看下面的对比以获得更清晰的认识。
对比这两者时,有些方面会让层次聚类更具优势。
以下是层次聚类表现较好的场景:
不过,它也存在一些缺点,例如:
您可能会问:什么时候应该使用层次聚类?
层次聚类在以下应用中是绝佳选择:
层次聚类的类型
在层次聚类方法中,您会遇到多种类型,每种都会带来不同的洞察和结果。两种主要类型是凝聚式(自底向上)和分裂式(自顶向下)。
来源:Himanshu Sharma(Medium)
1. 凝聚式(自底向上)
凝聚式聚类从将每个数据点视为一个独立的簇开始,反复合并距离最近的一对簇,直到只剩一个簇,或满足某个停止条件(如达到期望的簇数)。
这种方法也称为自底向上,因为它从底部(单个数据点)开始,逐步构建到顶部(最终簇)。
步骤指南:
该方法因其简单易实现而被广泛使用。
下面是如何在 Python 中实现的示例:
2. 分裂式(自顶向下)
分裂式聚类从将所有数据点置于一个簇中开始,并递归地将其划分为更小的簇。该过程持续进行,直到每个数据点都成为单独的簇。
它也被称为自顶向下的方法,因为它从顶部(单一簇)开始,逐步拆分为更小的簇。
步骤指南:
分裂式方法通常因其递归特性而计算开销更大,且准确性在很大程度上取决于拆分策略。凝聚式方法因实现简单且软件支持广泛而更为常见。
注意:在标准的 Python 库中,分裂式层次聚类不像凝聚式那样易于使用。一种思路是递归使用 k-means 等聚类算法。
下面是模拟递归 k-means 拆分的代码思路:
这段简化代码用递归的 K-means 展示了分裂式聚类的概念性做法。但请注意,标准的分裂方法(如 DIANA)采用不同的拆分准则。
关键概念与术语
层次聚类涉及一些重要的概念与术语。为全面理解该过程,我们将在下文更详细地介绍这些概念。
1. 树状图(Dendrogram)
树状图是一种树形结构,用于可视化层次聚类的过程。树的每一层代表一次合并或拆分操作,分支的高度表示簇被合并时的距离(或不相似度)。
其重要性在于:
2. 连接准则(Linkage)
连接准则决定了在合并过程中如何计算簇与簇之间的距离。
常见的连接准则包括:
单链接(最小)
该准则关注两个簇中最近点之间的距离,可能导致细长、链式的簇。
完全链接(最大)
该准则关注两个簇中最远点之间的距离,倾向于产生紧凑、大小均匀的簇。
平均链接(均值)
该准则关注一个簇中所有点到另一个簇中所有点的平均距离,介于单链接与完全链接之间,取得平衡。
这些简化示例展示了最初如何计算距离。然而在聚类过程中,这些准则(单链接、完全链接、平均链接)是迭代地在整个簇之间应用距离,而不仅是单个点。
Ward 方法
Ward 方法是平均链接的一种变体,最小化所有簇内平方差之和。与其他方法相比,它更倾向于生成大小更均匀的簇,并且常常得到分离良好、近球形的簇。
每种方法都有其优势,应根据数据与用例进行选择。
3. 距离度量
所用的距离度量会显著影响聚类结果。
欧氏距离
欧氏距离是在多维空间中两点间的直线距离。对几何分布的数据最常用。
曼哈顿距离
曼哈顿距离, 亦称出租车距离或 L1 距离,是各维度绝对差之和。适用于网格状数据,如城市街区或金融交易。
余弦相似度
余弦相似度衡量两个非零向量之间夹角的余弦值。当不关心量级(如词频向量)时,此度量非常适合文本数据。
在 Python 中实现层次聚类
本节将演示如何用 Python 实现凝聚式层次聚类。从数据预处理到使用树状图可视化结果,我们将逐步讲解。
依赖库
首先导入所需的库:
上面的代码导入了:
numpy与pandas:用于数据处理scipy.cluster.hierarchy:用于聚类与生成树状图sklearn.preprocessing.StandardScaler:用于特征缩放matplotlib:用于可视化示例数据
开始分析之前,我们先创建一个二维点的玩具数据集并进行缩放。对于基于距离的算法,缩放至关重要。
我们的示例数据集如下所示。
以下是缩放后的数据数组。
生成连接矩阵与树状图
我们应用 Ward 方法生成连接矩阵,其中包含层次聚类信息。随后绘制树状图。
在上述代码中,
linkage构建簇层级结构,dendrogram用于可视化簇的形成过程。通过观察合并前最长的竖线位置,我们可以决定在何处“切割”以形成簇。寻找不与其他簇相交的最高竖线处进行切割。
在本例中,您需要切分为 2 个簇。
创建簇
接下来,使用
fcluster按指定簇数对树状图进行切割:这会将每个数据点分配到两个簇中的一个。
有关代码的一些补充说明:
t=2:指定期望的簇数量。criterion='maxclust':确保获得恰好t个簇。您可以更改
t以尝试不同的簇数量。实践示例:客户细分
层次聚类常用于客户细分。我们来看一个实际实现的示例。
1. 数据集概览
我们将模拟一个包含两个特征(年龄与收入)的客户数据集。使用
make_blobs生成该合成数据。2. 预处理
接下来我们需要标准化特征,以归一化尺度并提升聚类准确性。
以下是缩放后的数据:
3. 应用层次聚类
数据处理完毕后,我们绘制树状图以可视化簇的形成。
4. 结果解读
根据树状图,我们选择一个高度进行“切割”,创建三个簇:
业务启示:
层次聚类的优势与局限
在分析中选择层次聚类既有优势也有局限。
以下是一些常见点:
优点
缺点
结论
层次聚类是一种多才多艺且易于解释的聚类技术,尤其适用于探索性数据分析,以及基因组学和客户细分等领域。尽管计算成本较高,其优势在于能够发现嵌套分组,并可通过树状图在事后灵活选择簇的数量。
对于小到中等规模且重视可解释性的数据集,层次聚类仍是数据科学家与分析师的常用方法。
想更深入地学习机器学习的细节?我们的Python 机器学习基础学习路径以及Python 层次聚类入门教程都是很好的起点。