层次聚类:无需“猜”K值,如何让数据自己画出“家族图谱”?

👋 大家好,我是小瑞瑞!欢迎回到我的专栏!

在上一期,我们学会了强大的K-Means算法,但它也给我们留下了一个“灵魂拷问”:K值到底该选几? 虽然我们有“肘部法则”和“轮廓系数”作为参考,但终究还是带有一些“猜测”的成分。

那么,有没有一种聚类算法,能够让我们不再纠结于预设K值,而是像一位耐心的历史学家,**自动地揭示出数据从“个体”到“家族”,再到“国家”的完整“合并史”**呢?

答案是肯定的!这就是我们今天的主角——层次聚类(Hierarchical Clustering)

本文将带你深入理解这种优雅的聚类方法。它不会直接给你一个“最终答案”,而是会为你绘制一幅被称为**“树状图(Dendrogram)”**的、信息量极其丰富的“家族图谱”。你将学会如何阅读这幅图谱,并像一位君主一样,在任意“高度”上对你的“疆域”进行划分,获得你想要的任何数量的簇。

🚀 本文你将彻底征服:

  1. 【哲思篇】: 理解“自底向上”的凝聚型聚类思想,与K-Means的本质区别。
  2. 【解剖篇】: 深度剖析层次聚类的两大核心——距离度量与链接准则。
  3. 【核心武器】: 学会如何“阅读”并“使用”树状图,掌握“横切”的艺术。
  4. 【代码实现】: 使用Python的SciPy库,从零实现一个完整的层次聚类分析。
  5. 【实战与可视化】: 对真实数据集进行聚类,并绘制出精美的树状图。

准备好了吗?让我们一起进入这个充满“层次之美”的聚类新世界!


第一章:【哲思篇】—— 从“划分”到“谱系”:层次聚类的世界观

在开启任何算法的学习之前,我们必须先建立起宏观的“世界观”。本章,我们将回答三个根本性问题:什么是层次聚类?它和K-Means有什么本质不同?它的核心智慧又是什么?

1. 算法背景与简介:聚类分析的“历史学家”

层次聚类(Hierarchical Clustering是一种历史悠久且思想深刻的无监督学习算法。与K-Means那种试图一次性将数据“一分为K”的**划分式聚类(Partitioning Clustering)**不同,层次聚类旨在构建一个嵌套的、层次化的聚类结构,这个结构完整地展现了数据从“个体”到“整体”的全过程。

它主要分为两种截然相反的流派:

  • 凝聚型(Agglomerative): “自底向上”的方法。开始时,每一个样本点都是一个独立的簇,然后算法会逐步地、迭代地将最相似(距离最近)的两个簇进行合并,直到最终所有样本点都在一个簇中。这是最常用、也是本文的重点。
  • 分裂型(Divisive): “自顶向下”的方法。开始时,所有样本点都在一个大簇中,然后算法会逐步地将最不相似的簇进行分裂,直到每个样本点都自成一簇。

如果说K-Means是一位**“快刀斩乱麻”的将军**,旨在快速划分领地;那么层次聚类就是一位**“追根溯源”的历史学家**,它不急于给出结论,而是为你 meticulous-ly 描绘出整个“民族”的形成史。

2. 核心思想:从“个体”到“家族”的演化史诗

💡 小瑞瑞的“家族联姻”比喻:
想象一下,一片土地上生活着N个独立的个体(样本点),每个人都自成一家。

  1. 【自由恋爱】: 算法首先会进行一次“人口普查”,计算出任意两个个体之间的“亲近程度”(距离)。然后,整个土地上最亲近的两个人,比如张三和李四,决定组成第一个小家庭(簇)
  2. 【家族联姻】: 接下来,算法会再次审视所有的“单身汉”和已有的“小家庭”,找出整个土地上关系最近的两个单位进行合并。这可能是王五和赵六组成了另一个小家庭,也可能是“张李”家族与隔壁的“王”姓个体进行了联姻,组成了一个更大的“张李王”家族。
  3. 【部落联盟】: 这个“联姻”的过程不断持续,小家族合并成大家族,大家族结成部落,部落最终形成一个统一的“国家”(包含所有样本点的根簇)。

层次聚类,就是用数学语言,精确地记录下这部从“个体”到“国家”的、完整的“联姻史”和“家族图谱”。

3. 层次聚类 vs. K-Means:两种世界观的对决
对比维度K-Means (划分式)层次聚类 (层次化)
核心思想划分:将数据分割成K个簇谱系:构建一个嵌套的簇结构
K值要求必须预先指定无需预先指定
输出结果一个唯一的簇分配方案一个完整的树状图(Dendrogram)
计算复杂度近似线性 O(nKTd)O(nKTd)O(nKTd)适合大规模数据至少 O(n2log⁡n)O(n^2\log n)O(n2logn)不适合大规模数据
对簇形状偏好球形可以发现更任意形状的簇(取决于链接准则)
算法过程迭代优化,结果可能因初始值而异确定性的,结果唯一(给定距离和链接方法)
小瑞瑞说“给我K个桶,我帮你把豆子放进去”“给我一堆豆子,我帮你画出它们的完整家谱”

通过这个对比,我们能清晰地看到层次聚类的最大魅力:它提供了一种探索性的、多粒度的视角,而不仅仅是一个固定的划分结果。这在很多需要探索数据内在结构的场景下,是极其宝贵的。


第二章:【解剖篇】—— 层次聚类的“联姻法则”:距离与链接的艺术

在上一章,我们通过“家族联姻”的比喻,直观地感受了凝聚型层次聚类的“自底向上”过程。但这个过程并非随意的,它每一步都遵循着极其严谨的数学法则。要实现这部波澜壮阔的“合并史”,算法必须在每一步都精准地回答两个核心问题:

  1. “我该跟谁结婚?” —— 如何衡量任意两个“个体”(样本点)之间的“亲近程度”?这就是距离度量
  2. “我们家族该跟哪个家族联姻?” —— 当我们要合并两个“家族”(簇)时,如何衡量这两个大家族之间的“亲近程度”?这就是链接准则

本章,我们就来深度解剖这两套“联姻法则”。

2.1 距离度量 (Distance Metric):定义“亲近”的数学标尺

距离度量,是衡量两个n维样本点 xa=(xa1,…,xan)x_a = (x_{a1}, \dots, x_{an})xa=(xa1,,xan)xb=(xb1,…,xbn)x_b = (x_{b1}, \dots, x_{bn})xb=(xb1,,xbn) 之间不相似度的数学方法。选择不同的“标尺”,会影响我们对“亲近”的定义。

2.1.1 欧几里得距离 (Euclidean Distance) - 最常用
  • 定义: 即我们初中就学过的,两点之间的直线距离
  • 公式:
    d(xa,xb)=∑i=1n(xai−xbi)2 d(x_a, x_b) = \sqrt{\sum_{i=1}^{n} (x_{ai} - x_{bi})^2} d(xa,xb)=i=1n(xaixbi)2
  • “人话”解读: 它衡量的是两个样本点在特征空间中的绝对距离。这是最直观、应用最广泛的距离度量。
  • 注意事项: 欧几里得距离对**特征的尺度(量纲)**非常敏感。例如,如果一个特征是“收入”(单位:元),另一个是“年龄”(单位:岁),那么“收入”这个特征将在距离计算中占据绝对主导地位。因此,在使用欧氏距离之前,**对数据进行标准化(Standardization)**通常是一个必要的预处理步骤。
2.1.2 曼哈顿距离 (Manhattan Distance) - “城市街区”的距离
  • 定义: 又称“城市街区距离”,它计算的是两点在标准坐标系上各个坐标轴差值的绝对值之和
  • 公式:
    d(xa,xb)=∑i=1n∣xai−xbi∣ d(x_a, x_b) = \sum_{i=1}^{n} |x_{ai} - x_{bi}| d(xa,xb)=i=1nxaixbi
  • “人话”解读: 想象你在一个像曼哈顿那样的棋盘式街区,你不能斜着穿过大楼,只能沿着街道走。从A点到B点,你需要走过的横向和纵向街道长度之和,就是曼哈顿距离。
2.1.3 余弦相似度 (Cosine Similarity) & 余弦距离
  • 定义: 它衡量的是两个向量在方向上的相似性,而不是大小。余弦相似度的值域为[-1, 1],值越接近1,方向越一致。
  • 公式:
    Similarity(xa,xb)=cos⁡(θ)=xa⋅xb∥xa∥∥xb∥=∑i=1nxaixbi∑i=1nxai2∑i=1nxbi2 \text{Similarity}(x_a, x_b) = \cos(\theta) = \frac{x_a \cdot x_b}{\|x_a\| \|x_b\|} = \frac{\sum_{i=1}^{n} x_{ai} x_{bi}}{\sqrt{\sum_{i=1}^{n} x_{ai}^2} \sqrt{\sum_{i=1}^{n} x_{bi}^2}} Similarity(xa,xb)=cos(θ)=xa∥∥xbxaxb=i=1nxai2i=1nxbi2i=1nxaixbi
  • 转换为距离: 余弦距离通常定义为 1−Cosine Similarity1 - \text{Cosine Similarity}1Cosine Similarity
  • “人话”解读: 余弦相似度不关心两个向量的长度(绝对大小),只关心它们的指向
  • 应用场景:文本分析领域是绝对的主流。比如,两篇文章,即使长度(总词数)相差很大,但如果它们讨论的核心词汇(词向量方向)非常相似,那么它们的余弦相似度也会很高。
2.2 链接准则 (Linkage Criteria):定义“家族”关系的四种视角

这是层次聚类的灵魂,它定义了如何计算**两个簇(Clusters)**之间的距离。不同的链接准则,代表了不同的“联姻”策略,会产生截然不同的“家族图谱”(树状图)。

假设我们要计算簇 A 和簇 B 之间的距离:

在这里插入图片描述
“从上图我们可以清晰地看到:
Single Linkage(a) 像一个‘自由恋爱’的撮合者,只看最好的一对。
Complete Linkage(b) 则像一个保守的‘大家长’,必须所有人都满意才行。
Average Linkage© 如同一次‘民主民意调查’,听取所有人的意见。
而Ward’s Method(d) 则是一位高瞻远瞩的‘战略家’,他考虑的是这次合并对整个‘社会’的稳定性(总方差)带来的影响。
理解了这四种不同的视角,你就能在面对不同数据时,选择最合适的‘联姻’策略了。”

2.2.1 Single Linkage (最小链接 / 最近邻)
  • 联姻策略:最乐观、最不挑剔”的联姻策略。只要两个家族中,有一对“年轻人”(样本点)情投意合(距离最近),那么这两个家族就可以联姻。
  • 数学定义: 簇A和簇B的距离,由A中某个点与B中某个点的最小距离来定义。
    d(A,B)=min⁡a∈A,b∈Bd(a,b) d(A, B) = \min_{a \in A, b \in B} d(a, b) d(A,B)=aA,bBmind(a,b)
  • 特点: 容易受到异常值的影响,倾向于产生“链式”的、细长的簇,善于处理非椭圆形状的簇。
2.2.2 Complete Linkage (最大链接 / 最远邻)
  • 联姻策略:最保守、最挑剔”的联姻策略。只有当两个家族中,关系最疏远(距离最远)的那两个人,他们的距离都足够近时,这两个家族才同意联姻。
  • 数学定义: 簇A和簇B的距离,由A中某个点与B中某个点的最大距离来定义。
    d(A,B)=max⁡a∈A,b∈Bd(a,b) d(A, B) = \max_{a \in A, b \in B} d(a, b) d(A,B)=aA,bBmaxd(a,b)
  • 特点: 对异常值不那么敏感,倾向于产生大小相似的、紧凑的球形簇。
2.2.3 Average Linkage (平均链接)
  • 联姻策略:民主投票、全面考察”的策略。需要计算两个家族之间,所有可能的“个体配对”的距离,然后取一个平均值,来代表两个家族的整体关系。
  • 数学定义: 簇A和簇B的距离,是A中所有点到B中所有点的所有两两距离的平均值
    d(A,B)=1∣A∣∣B∣∑a∈A∑b∈Bd(a,b) d(A, B) = \frac{1}{|A||B|} \sum_{a \in A} \sum_{b \in B} d(a, b) d(A,B)=A∣∣B1aAbBd(a,b)
  • 特点: 效果介于Single和Complete之间,是一种比较稳健、折衷的选择。
2.2.4 Ward’s Method (离差平方和法) - 最常用且推荐
  • 联姻策略:社会效益最大化”的策略。它不再只看两个家族自身,而是站在整个“社会”(所有簇)的角度来思考问题。它会尝试所有可能的合并方案,并选择那个使得整个社会的“内部矛盾”(总簇内方差)增加得最小的合并方案。
  • 数学定义: 它计算的是,如果将簇A和簇B合并,那么新的大簇的簇内误差平方和(SSE)会增加多少。选择使这个增量最小的合并。
  • 特点:
    • 倾向于产生大小相似、结构紧凑的球形簇。
    • 对噪声的鲁棒性较好。
    • 在实践中,Ward’s method通常能得到最令人满意的聚类结果
    • 注意: Ward’s method必须使用欧几里得距离

💡 小瑞瑞说:
选择哪种链接准则,没有绝对的标准答案,它取决于你对数据内在结构的假设。但在大多数情况下,Ward's method开始尝试,通常是一个非常好的起点


第三章:【核心武器篇】—— 树状图(Dendrogram)的“阅读”与“使用”艺术

在K-Means的世界里,我们最终得到的是一个固定的“国家版图”。而在层次聚类的世界里,我们得到的是一件更珍贵、更有深度的宝物——一张完整记录了从“个体”到“统一”全过程的**“家族图谱”,在学术上,我们称之为树状图(Dendrogram)**。

本章,我们将学会如何像一位智慧的“史官”,去阅读和解读这幅图谱,并像一位果决的“君主”,在图谱上“横切一刀”,划分出我们想要的“疆域”(簇)。

3.1 如何“阅读”树状图:解构一部“合并史”

层次聚类的最终输出,不是一个简单的标签列表,而是一张信息量极其丰富的树状图。下面这张图,就是我们对一组模拟数据进行层次聚类后得到的典型结果。

在这里插入图片描述

让我们来解构这张图的每一个元素:

  • 横轴 (X-axis):数据样本 (Samples)

    • 解读: 横轴代表了我们数据集中的每一个独立样本点。每个叶节点(在最底部、没有分叉的节点)都对应着一个原始的数据点。括号里的数字(n)表示这个分支下包含了n个原始样本点。
  • 纵轴 (Y-axis):距离 / 不相似度 (Distance / Dissimilarity)

    • 解读: 纵轴是理解这张图的关键!它衡量了簇与簇之间的“不相似程度”。
    • U形链接线的高度: 每一条U形的横线,都代表了一次合并操作。这条横线的纵坐标值,就表示了此次合并的两个簇之间的距离(这个距离的计算方式,由我们上一章选择的链接准则所决定)。
    • 核心洞察: U形线越高,代表此次合并越“勉强”,因为被合并的两个簇彼此之间相距甚远,非常不相似。
  • 分支与节点 (Branches & Nodes):

    • 解读: 整张图就像一棵倒置的树。从最顶部的“根节点”出发,不断向下分支,最终到达每一个“叶节点”。这个结构,完整地展示了数据是如何从一个包含所有样本的“超级大簇”,一步步分裂(或者反过来看,是从个体一步步合并)的。它揭示了数据内在的层次结构
3.2 如何“使用”树状图:“横切”的艺术与K值确定

K-Means最大的痛点是需要预设K值,而层次聚类的美妙之处在于,它将决定K值的权力,交还给了我们。我们通过“切割”树状图来完成这个决策。

  • “横切”的艺术:
    1. 想象一把尺子: 水平地放在树状图上。
    2. 从上到下移动尺子: 观察尺子与多少条独立的垂直线相交。
    3. 交叉点的数量 = 簇的数量 (K): 尺子与K条垂直线相交,就意味着你将数据分成了K个簇。

让我们来看图中的两条“切割线”:

  • 绿色的虚线(y=30):

    • 当我们的“切割阈值”设定在距离30时,这条线只与2条独立的垂直分支相交。
    • 结论: 如果在此处切割,我们将得到 K=2 个簇。这两个簇内部的凝聚度非常高(因为它们都在很低的距离上就完成了合并)。
  • 红色的虚线(y=15):

    • 当我们将阈值降低到15时,这条线与3条独立的垂直分支相交。
    • 结论: 如果在此处切割,我们将得到 K=3 个簇。这是在K=2的基础上,将其中一个较大的簇进一步细分的结果。
3.3 寻找最佳“切点”:一个基于启发式规则的科学决策

“我可以自由切割,但到底切在哪里最好呢?” —— 这是一个非常好的问题。虽然没有绝对的数学公式,但有一个非常强大且直观的启发式规则:

黄金法则:寻找最长的“未被切割”的垂直线

观察树状图中所有的垂直线。找到那段最长的、连续的垂直线。然后,将你的“横切线”设置在这段长线的上方。

  • 为什么?
    • 回顾一下,垂直线的长度代表了两次连续合并之间的距离差
    • 一段很长的垂直线意味着,在这次合并(长线的顶端)发生之前,系统在很长一段“距离”内(长线的长度)都没有进行任何合并。这说明,长线下方的那些簇本身已经非常稳定和紧凑了。
    • 而长线顶端的那次合并,则是一次“代价巨大”的、将两个非常不相似的簇强行合并在一起的操作。
    • 因此,我们最理想的切割点,就应该在这次“代价巨大”的合并发生之前,从而保留那些最自然的、最稳定的簇结构。

在我们的示例图中:
连接两个最大分支的那条垂直线(大约从y=18到y=45)是最长的。因此,将切割线设在其下方(如红色的y=15),从而得到K=3(或者K=2),通常是一个比得到K=5K=6更合理的选择。

💡 小瑞瑞说:
树状图不仅是一个结果,更是一个强大的交互式诊断工具。它将一个复杂的、多维的聚类问题,降维到了一个你可以直观理解和操作的二维平面上。它让你不再受限于一个固定的K值,而是可以根据业务需求和对数据结构的洞察,自由地在不同的“聚类粒度”(国家、省、市)上进行探索。


第四章:【代码实现篇】—— SciPy:你的“家族图谱”绘制专家

理论的精妙,终须在代码的实践中绽放光芒。与scikit-learn主要关注划分式聚类不同,进行层次聚类(Hierarchical Clustering)并绘制精美的树状图(Dendrogram),我们通常会请出另一位“科学计算巨匠”——**SciPy**库。

本章,我们将学习如何驾驭SciPy中强大的cluster.hierarchy模块,并将其封装成一个完整的、从数据处理到可视化呈现的“工作流模板”。

4.1 我们的“武器库”:核心Python库与模块

在开始之前,请确保你已经安装了我们的“数据科学四件套”:

  • numpy: 用于进行高效的数值计算。
  • matplotlib: 用于数据可视化。
  • scikit-learn: 我们将主要使用它的数据预处理功能(如StandardScaler)和数据集生成工具。
  • scipy: 科学计算的核心库。我们将聚焦于:
    • scipy.cluster.hierarchy.linkage:计算层次聚类的链接矩阵,这是算法的核心。
    • scipy.cluster.hierarchy.dendrogram:将链接矩阵可视化为树状图。

如果你尚未安装,可以通过以下命令一键安装:

pip install numpy matplotlib scikit-learn scipy
4.2 “层次聚类工作流”:一个函数的封装艺术

为了让整个流程清晰可控、可复用,我们将所有步骤——从数据生成/预处理到最终的树状图绘制——全部封装在一个名为hierarchical_clustering_workflow的函数中。

完整的Python实现代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster# --- 1. 环境设置 ---
# 设置matplotlib以正确显示中文和负号
try:plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False
except Exception as e:print(f"中文字体设置失败,将使用默认字体: {e}")def hierarchical_clustering_workflow(data, method='ward', metric='euclidean', p=30, truncate_mode='lastp', show_contracted=True):"""一个完整的、自动化的层次聚类工作流。该函数会自动进行聚类计算,并绘制精美的树状图。参数:data (np.array): 输入的数据,格式为 (n_samples, n_features)。method (str): 链接准则。常用:'ward', 'single', 'complete', 'average'。metric (str): 距离度量。常用:'euclidean', 'cityblock' (曼哈顿), 'cosine'。p (int): 树状图剪枝参数,用于控制显示的叶节点数量。truncate_mode (str): 剪枝模式。'lastp'表示显示最后p次合并。show_contracted (bool): 是否在剪枝后的节点上标注其包含的原始样本数量。返回:np.array: linkage矩阵,包含了所有合并信息。"""print("--- 步骤1: 数据预处理 (标准化) ---")# 对数据进行标准化,消除量纲影响,对于距离计算非常重要scaler = StandardScaler()scaled_data = scaler.fit_transform(data)print("[成功] 数据标准化完成!")print("\n--- 步骤2: 计算链接矩阵 ---")# linkage函数是层次聚类的核心,它计算并返回了所有合并步骤的信息# Z是一个(n-1) x 4的矩阵,n是样本数# 每一行记录了一次合并:[簇1索引, 簇2索引, 距离, 新簇样本数]Z = linkage(scaled_data, method=method, metric=metric)print(f"[成功] 使用 '{method}' 链接准则计算链接矩阵完成!")print("\n--- 步骤3: 绘制树状图 (Dendrogram) ---")plt.figure(figsize=(16, 9), dpi=150)plt.title(f'层次聚类树状图 (链接准则: {method.capitalize()})', fontsize=22, fontweight='bold')plt.xlabel('数据样本索引或簇 (括号内为该簇的样本数)', fontsize=14)plt.ylabel('距离 (Distance)', fontsize=14)# dendrogram函数将链接矩阵可视化dendrogram(Z,truncate_mode=truncate_mode,  # 剪枝模式p=p,                      # 显示最后p个合并的簇leaf_rotation=90.,        # 叶节点标签旋转角度leaf_font_size=12.,      # 叶节点标签字体大小show_contracted=show_contracted, # 显示被折叠的簇的样本数color_threshold=None,     # 可以设置一个阈值来用不同颜色显示簇)# 添加“横切线”来演示如何确定K值# 我们可以根据链接矩阵Z来智能地添加切割线# 例如,在倒数第3和第4次合并的距离之间切割,可以得到3个簇try:cut_threshold = (Z[-3, 2] + Z[-2, 2]) / 2 # 取倒数第2和第3次合并的中间距离plt.axhline(y=cut_threshold, c='red', lw=2, linestyle='--', label=f'横切线 (K=3)')plt.text(plt.xlim()[1]*0.8, cut_threshold + 0.1, 'K=3 切割示例', color='red', fontsize=12)except IndexError:pass # 如果样本太少,可能会出错plt.legend()plt.grid(axis='y', linestyle=':', alpha=0.7)plt.tight_layout()plt.show()print("[成功] 树状图绘制完成!")return Z# --- 主程序入口,用于演示和测试 ---
if __name__ == '__main__':# 1. 生成一组用于测试的、有明显聚类结构的数据X_test, y_true = make_blobs(n_samples=150, centers=4, n_features=2, random_state=42, cluster_std=1.0)# 2. 调用我们的自动化工作流# 我们使用效果通常最好的'ward'方法linkage_matrix = hierarchical_clustering_workflow(X_test, method='ward', p=12)# 3. (可选) 从链接矩阵中获取固定数量的簇标签# fcluster函数可以根据不同的标准从链接矩阵中“切割”出簇# criterion='maxclust', t=4 表示我们想要得到4个簇labels = fcluster(linkage_matrix, t=4, criterion='maxclust')print("\n--- 从树状图中切割出4个簇 ---")print("每个样本的簇标签:", labels)
代码逐行分析 (Code Analysis)
  1. hierarchical_clustering_workflow(...) 函数定义:

    • 我们将所有操作封装在一个函数里,输入data和一些绘图/算法参数,就能自动完成分析和可视化。
  2. 步骤1:数据预处理

    • StandardScaler():这是scikit-learn提供的标准化工具。它会把数据的每一列(特征)都处理成均值为0,方差为1的标准正态分布。这一步对于基于距离的算法(包括层次聚类和K-Means)至关重要,可以防止某些特征因为数值范围过大而主导了距离的计算。
  3. 步骤2:计算链接矩阵 (linkage函数)

    • 这是SciPy中执行层次聚类的核心函数。 它输入标准化后的数据和我们选择的链接准则 (method)距离度量 (metric)
    • 它返回的Z是一个形状为(n-1, 4)的矩阵,n是样本数。这个矩阵就是我们“家族合并史”的数字记录本
    • Z的每一行都记录了一次合并操作:[簇A的索引, 簇B的索引, A和B的距离, 合并后新簇的样本数]
  4. 步骤3:绘制树状图 (dendrogram函数)

    • 这是SciPy中负责可视化的核心函数。 它唯一的必要输入就是上一步生成的链接矩阵Z
    • 关键参数解读:
      • truncate_mode='lastp', p=12:这是一个非常实用的**“剪枝”功能。当样本数量非常多时(比如几百上千),完整的树状图底部会挤成一团,完全无法看清。这个参数组合告诉dendrogram:“我不想看最开始那些零散的、个体间的合并,请只给我展示最后12次**最重要的、簇与簇之间的合并过程。”
      • show_contracted=True:配合剪枝功能,在被“折叠”起来的叶节点上,用括号标注出它内部实际包含了多少个原始样本点。
      • color_threshold:一个高级参数,可以设定一个距离阈值,dendrogram会自动为阈值下的不同分支染上不同的颜色,非常漂亮。
  5. fcluster函数:

    • if __name__ == '__main__':部分,我们展示了如何使用fcluster函数。这个函数的作用就是执行“横切”操作。我们输入链接矩阵Z,并告诉它我们想要得到t=4个簇,它就能返回每个原始样本点对应的簇标签[1, 2, 3, 4, ...],这与K-Means的输出格式是一样的。

💡 小瑞瑞说:
这段代码不仅教你如何“画”出树状图,更重要的是,它揭示了层次聚类的内在逻辑:linkage负责计算“合并史”,dendrogram负责将历史“可视化”,而fcluster则负责根据历史来“做决策”。掌握了这三个函数的配合使用,你就掌握了SciPy中层次聚类的全部精髓。


第五章:【实-战与可视化篇】—— 案件重演:让数据自己画出“家谱”

理论的星辰大海,终须在实践的土地上扎根。现在,让我们将前面章节的所有知识融会贯通,扮演一名真正的数据考古学家,对一份“身份不明”的数据集进行一次完整的层次聚类分析。

我们的目标,就是利用上一章打造的hierarchical_clustering_workflow自动化工作流,为这份数据绘制出独一无二的“家族图谱”,并从这幅图谱中,解读出其内在的、不为人知的层次结构。

5.1 案情介绍:一份神秘的二维数据集

我们的“考古现场”,是一份包含了150个样本点的二维数据集。我们只知道每个样本点的两个特征(Feature 1 和 Feature 2),但对其类别一无所知。我们将使用scikit-learnmake_blobs函数来生成这份模拟数据。

# (接上一章代码)
# --- 主程序入口,用于演示和测试 ---
if __name__ == '__main__':# 1. 生成“考古现场”:一组包含4个真实簇的模拟数据X_test, y_true = make_blobs(n_samples=150, centers=4, n_features=2, random_state=42, cluster_std=1.0)# 2. 调用我们的自动化工作流# 我们使用效果通常最好的'ward'链接准则# 并设置p=12,只观察最后12次重要的合并linkage_matrix = hierarchical_clustering_workflow(X_test, method='ward', p=12)

第一步:现场勘查 —— 原始数据可视化

在进行任何复杂的分析之前,先对数据进行可视化,是数据考古学家的“第一直觉”。

    # (在主程序入口添加可视化代码)plt.figure(figsize=(10, 8))plt.scatter(X_test[:, 0], X_test[:, 1], s=50, alpha=0.7, c='gray', edgecolors='k')plt.title('考古现场:一份神秘的未标记数据集', fontsize=18)plt.xlabel('特征 1 (Feature 1)', fontsize=14)plt.ylabel('特征 2 (Feature 2)', fontsize=14)plt.grid(True, linestyle=':', alpha=0.6)plt.show()

在这里插入图片描述

考古学家的初步勘查报告:

  • 直观感受: 数据点并非完全随机地散布,而是呈现出明显的**“部落”**聚集现象。
  • 初步推断: 用肉眼观察,我们可以大致分辨出3到4个“部落遗址”的大致方位。我们的任务,就是用层次聚类来精确地还原这些部落的形成历史和最终疆域。
5.2 绘制“家族图谱”:树状图的生成与解读

现在,我们正式调用我们的自动化工作流hierarchical_clustering_workflow,让它为我们绘制出这份数据的“家族图谱”。

可视化结果:层次聚类树状图 (Dendrogram)

在这里插入图片描述

考古学家的“图谱”深度解读:
这张图就是我们这次“考古”行动最核心的发现!它像一部无声的史诗,记录了150个“远古人类”(样本点)是如何通过一步步的“联姻”和“部落合并”,最终形成一个统一“文明”的。

  • 1. 横轴 (X-axis) - 部落分支:

    • 解读: 横轴代表了不同的“家族分支”。因为我们设置了truncate_mode='lastp', p=12,所以这张图只展示了最后12次最重要的合并
    • 括号中的数字 (n) 代表了这个分支(叶节点)在被“剪枝”之前,其内部实际包含了n个原始的、最底层的样本点。例如,最左侧的(16)代表这是一个由16个最相似的样本点组成的“小家族”。
  • 2. 纵轴 (Y-axis) - 距离(合并成本):

    • 解读: 纵轴是这张图的灵魂!它衡量了每一次合并的“代价”或“难度”。U形线的高度越高,说明被合并的两个“家族”彼此越疏远、越不相似。
    • 寻找“历史大事件”: 我们可以清晰地看到,在距离大约y=20y=50之间,有一段非常长的、光秃秃的垂直线。这在“历史”上意味着什么?
      • 意味着在距离小于20时,发生了大量密集的、自然的“小家族联姻”。
      • 而在距离大于20之后,很长一段时间内都没有发生任何合并,说明此时已经形成了几个非常稳定、独立、且彼此差异巨大的大部落。
      • 最后在距离约50处发生的那次合并(图中最高的U形线),是一次代价极高的“统一战争”,它将两个非常不同的“大国”强行合并在了一起。
  • 3. “横切”决策 - 划分最终“国家”:

    • 红色的虚线: 这条线被我们智能地设置在了那段最长的垂直线的下方。
    • 解读: 在这个高度进行“切割”,我们恰好切断了4条独立的垂直分支。
    • 最终结论: 这张“家族图谱”以一种极具说服力的方式告诉我们,将这份数据划分为K=4个簇,是最能反映其内在自然结构的决策!
5.3 验证结论:获取簇标签并可视化

树状图给了我们“宏观”的指导,我们还可以使用fcluster函数来获取“微观”的分配结果,并将其可视化,与我们最初的直觉进行对比。

# (接上一章代码)
# 从链接矩阵中,根据距离阈值或簇数量来“切割”
from scipy.cluster.hierarchy import fcluster# 我们可以根据我们从图上观察到的最佳切割距离来切割
# 也可以直接指定想要的簇数量
labels = fcluster(linkage_matrix, t=4, criterion='maxclust')# 可视化最终的聚类结果
plt.figure(figsize=(12, 10))
plt.scatter(X_test[:, 0], X_test[:, 1], c=labels, cmap='viridis', s=50, edgecolors='k')
plt.title('层次聚类最终结果 (K=4)', fontsize=18)
# ... (省略其他绘图代码)
plt.show()

在这里插入图片描述

考古发掘最终报告:

  • 结果分析: 最终的可视化结果,清晰地将数据划分为了4个颜色各异的簇。
  • 结论印证: 这个结果与我们最初对原始数据的直观判断,以及从树状图中科学推断出的K=4的结论,完美地相互印证
  • K-Means vs. 层次聚类: 虽然对于这个数据集,K-Means可能也能得到类似的结果,但层次聚类的优势在于,它提供了一个完整的、可解释的、多粒度的“决策过程”(树状图),而不仅仅是一个单一的、固定的“最终答案”。

通过这场“数据考古”,我们不仅成功地为这份神秘数据划分了“部落”,更重要的是,我们学会了如何阅读和理解那张记录着“文明演化史”的、充满智慧的“家族图谱”。


第六章:【检验与拓展篇】—— 层次聚类的“权衡”艺术与“朋友圈”

恭喜你!到目前为止,你已经完整地掌握了层次聚类的建模全流程,并成功地为一份数据绘制了“家族图谱”。但这就像一位历史学家写完了一部史书,真正的成长在于复盘与反思,以及了解还有哪些不同的“史观”(算法)。

本章,我们将对层次聚类进行一次全面的“压力测试”,看看它的优点与代价,并探索其“家族”中的其他成员和“竞争对手”。

6.1 模型的优劣势对比:层次聚类的“双刃剑”

层次聚类以其优雅的思想和丰富的输出赢得了赞誉,但这份“优雅”也伴随着相应的“代价”。

优势 (Pros) - 闪光点劣势 (Cons) - 现实的枷锁
无需预设K值
这是其最核心的优势。它提供了一个完整的聚类层次结构,让用户可以根据业务需求和对树状图的理解,自由探索并选择最合适的簇数量。
计算与存储开销巨大
这是其最致命的弱点。凝聚型层次聚类需要预先计算一个包含所有样本点之间两两距离的 n×nn \times nn×n 距离矩阵,其空间复杂度为 O(n2)O(n^2)O(n2)。算法的时间复杂度至少为 O(n2log⁡n)O(n^2\log n)O(n2logn),对于大规模数据集(如超过几千个样本)几乎是不可行的。
结果直观,可解释性强
输出的**树状图(Dendrogram)**本身就是一种强大的可视化分析工具,它清晰地展示了数据点是如何一步步合并的,以及合并的“代价”是什么。
结果的不可逆性 (Greedy Nature)
凝聚型算法一旦将两个簇合并,这个决策在后续步骤中就永远无法撤销。这意味着,早期的一个“错误”的合并决策,可能会对后续的整个聚类结构产生深远且无法修正的影响。
可以发现任意形状的簇
与K-Means的“球形”偏好不同,通过选择合适的链接准则(尤其是single-linkage),层次聚类有能力发现非凸形的、更复杂的簇结构。
对链接准则和距离度量敏感
最终的聚类结果高度依赖于你选择的链接准则(Ward, Complete, Average, Single)和距离度量(Euclidean, Manhattan等)。不同的组合可能会产生截然不同的树状图,需要用户具备一定的先验知识来做出选择。
确定性算法
给定相同的数据、距离度量和链接准则,每次运行的结果都是完全一样的,不存在K-Means那样的随机初始化问题。
可读性问题
当样本数量稍多时(如超过100个),完整的树状图底部会变得极其拥挤,难以阅读。虽然可以通过“剪枝”来缓解,但这也会损失底层细节信息。

💡 小瑞瑞的判决书:

层次聚类是一位博学而严谨的历史学家,它能为你 meticulously-ly 描绘出一部详尽的“家族史”。它特别适合于中小规模数据集探索性分析,尤其是当你对数据内在的层次结构和自然的簇数量感兴趣时。但面对成千上万人的“人口普查”任务,这位老教授可能会因为计算量过大而“力不从心”。


第七章:【应用与终章】—— 层次聚类的“用武之地”与未来的“星辰大海”

7.1 应用领域与场景:层次聚类的真实世界

层次聚类的独特优势,使其在许多需要探索和理解数据内在结构的领域大放异彩。

  • 🧬 生物信息学与基因组学 (Hierarchical Clustering的“经典主场”)

    • 基因表达分析: 在分析基因芯片数据时,研究人员使用层次聚类将具有相似表达模式的基因或样本(病人)聚合在一起。生成的树状图和热图(Heatmap)是该领域论文中最经典的图片之一,能直观地发现不同疾病状态下的基因共表达模块。
    • 物种演化分析: 构建系统发育树(Phylogenetic Tree),其思想与层次聚类如出一辙,都是通过衡量物种间的“遗传距离”来构建一棵“进化树”。
  • 📊 市场营销与客户分群

    • 探索性客户分群: 在不确定应该将客户分为几类时,可以先用层次聚类生成一个树状图,通过观察图谱来判断客户群体是否存在自然的、不同粒度的层次结构(例如,“高价值客户”群体内部,是否还可以细分为“高频高额”和“低频高额”两个子群体)。
  • 📄 自然语言处理:文本层次化组织

    • 新闻主题发现: 对大量新闻文档进行层次聚类,可以得到一个从“体育 -> 球类 -> 足球”这样的主题层次结构,比扁平的聚类结果信息更丰富。
  • 🌍 社会科学

    • 社会网络分析: 分析社交网络中的社群结构,发现从“个人 -> 小团体 -> 大社群”的层次关系。
7.2 拓展与延申:超越标准层次聚类的未来之路

标准凝聚型层次聚类 O(n2)O(n^2)O(n2) 的复杂度限制了其在大数据时代的应用。为了克服这些挑战,算法也在不断进化:

  • BIRCH算法 (Balanced Iterative Reducing and Clustering using Hierarchies):
    一种专门为大规模数据集设计的层次聚类算法。它通过构建一个被称为**“聚类特征树 (CF Tree)”**的摘要数据结构,在一次扫描数据的过程中就完成了聚类,大大降低了内存和时间开销。
  • HDBSCAN (Hierarchical DBSCAN):
    一个极其强大的算法,它完美地融合了层次聚类和我们之前提到的DBSCAN的思想。它不仅能像DBSCAN一样发现任意形状的簇并识别噪声,还能像层次聚类一样,生成一个包含所有可能簇划分的层次结构,并从中智能地提取出最稳定的聚类结果,真正做到了“鱼与熊掌兼得”。
7.3 终章:你的分析工具箱,已装备“透视显微镜”

层次聚类,以其独特的“自底向上”的构建过程和信息丰富的树状图输出,为你打开了一扇全新的数据探索之门。它教会我们,数据中的“群组”关系,有时并非是扁平的、非黑即白的划分,而是一个充满丰富细节和嵌套关系的有机谱系

现在,你不仅掌握了它的原理和实现,更理解了它背后的权衡与艺术。这台能洞察数据内在层次的“透视显微镜”,必将让你的无监督学习能力,迈上一个新的台阶。

🏆 最后的最后,一个留给你的思考题,也是对全文的回响:

你认为,在K-Means和层次聚类之间,是否存在一种“混合策略”?例如,我们是否可以先用层次聚类对一小部分抽样数据进行分析,以确定一个合理的K值,然后再将这个K值应用于对全体数据进行的、更高效的K-Means聚类?你认为这种策略的优缺点是什么?

在评论区留下你的深度思考,让我们一起在探索数据的道路上,永不止步!

我是小瑞瑞,如果这篇“家族图谱”之旅让你对聚类分析有了全新的认识,别忘了点赞👍、收藏⭐、加关注!我们下一篇,将在更精彩的世界里相遇!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91512.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91512.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91512.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构:链表(Linked List)

目录 结构推导 回到最原始的问题 —— 我们如何存数据? 第二步:我们来看看数组的限制 第三步:那我们该怎么做呢? 第四步:我们推导链表的数据结构 结构讲解 什么是链表? 什么是节点? …

[RK3566-Android11] U盘频繁快速插拔识别问题

问题描述 做老化测试时,在使用U盘频繁快速插拔的情况下,SDCard目录会突然被Kill掉,然后又重新挂载上,这会导致系统及APP的数据因为读写异常,从而界面卡死正常U盘插拔不应该导致内部存储卸载解决方案: SDK根…

【Golang】Go语言Map数据类型

Go语言Map数据类型 文章目录Go语言Map数据类型一、Map1.1.1、map定义1.1.2、map的基本使用1.1.3、判断某个键是否存在1.1.4、map的遍历1.1.5、使用delete()函数删除键值对1.1.6、按照指定顺序遍历map1.1.7、元素为map类型的切片1.1.8、值为切片类型的map一、Map map是一种无序…

Orange的运维学习日记--23.Linux计划任务详解

Orange的运维学习日记–23.Linux计划任务详解 文章目录Orange的运维学习日记--23.Linux计划任务详解一次性计划任务atd 服务at 命令基本语法交互式示例脚本文件示例timespec 格式示例查看与管理任务查看当前队列查看任务详细内容删除任务用户权限控制用户周期性计划任务查看任务…

Ubuntu 24.04.2 LTS 安装mysql8.0.36保姆级教程(从安装到远程连接)

目录 前言 一、系统准备 二、安装 MySQL 8.0.36 1. 查看可用版本 2.如果没有对应版本则需要手动下载mysql-apt-config(有则跳过) 2.1下图是mysql-apt-config各版本对应的mysql版本 2.2下载mysql apt repository 2.3安装 MySQL APT Repository 包 …

【LLM】讲清楚MLA原理

需要你对MHA、MQA、GQA有足够了解,相信本文能帮助你对MLA有新的认识。 本文内容都来自https://www.youtube.com/watch?v0VLAoVGf_74,如果阅读本文出现问题,建议直接去看一遍。 按照Deepseek设定一些参数值:输入token长度n10&…

谷歌采用 Ligero 构建其 ZK 技术栈

1. 引言 前序博客有: Ligero 和 Ligetron 中的 MPC 和 ZKLigetron:Nim Network开发的针对AI的zkVMLigetron:基于MPC-In-The-Head范式的zkVM简介 在隐私保护身份验证领域迈出重要一步,谷歌最近宣布 将零知识证明(ZKP…

Flutter渲染引擎:Impeller和Skia

一、Impeller 渲染引擎的发布时间Impeller 是 Flutter 团队为解决 Skia 引擎在移动端(尤其是 iOS 平台)的性能问题而开发的全新渲染引擎,其发展历程如下:首次公开:2021 年 Google I/O 大会上首次提及,作为 …

网络编程-加密算法

目录 一.网络编程基础 1. 概述 2. IP地址 3. 域名 4. 网络模型 5. 常用协议 6. 小结 二.TCP编程 1. 什么是Socket? 2. 服务器端 3. 客户端 4. Socket流 5. 小结 三.UDP编程 1. 概述 2. 服务器端 3. 客户端 4. 小结 案例: 四.加密算法 …

【网络工程师软考版】网络安全

任何形式的网络服务都会导致安全方面的风险,问题是如何将风险降到最低程度,目前的网络安全措施有数据加密、数字签名、身份认证、防火墙、特征过滤等。所涉内容:1、网络安全基础2、加密技术与哈希算法3、数字签名4、数字证书5、VPN技术6、防火…

深入浅出设计模式——创建型模式之建造者模式 Builder

文章目录建造者模式简介建造者模式结构建造者模式代码实例定义产品类House定义建造者定义抽象建造者AbstractBuilder定义具体建造者定义指挥者客户端代码示例运行结果建造者模式总结代码仓库建一栋房子总共分几步?建造者模式告诉你答案!“把大象装冰箱&a…

OpenVLA: 论文阅读 -- 开源视觉-语言-行动模型

更多内容:XiaoJ的知识星球 目录OpenVLA:开源视觉-语言-行动模型1. 介绍2. 相关工作1)视觉条件语言模型(Visually-Conditioned Language Models)2)通用型机器人策略(Generalist Robot Policies&a…

JavaWeb(苍穹外卖)--学习笔记15(分页查询PageHelper)

前言 终于开始学习做项目了,本篇文章是学习B站黑马程序员苍穹外卖的学习笔记📑。我的学习路线是Java基础语法-JavaWeb-做项目,管理端的功能学习完之后,就进入到了用户端微信小程序的开发,这篇文章来看看分页查询&#…

金融专题|某跨境支付机构:以榫卯企业云平台 VPC 功能保障业务主体安全

作者:SmartX 金融团队 金融机构在信息化建设时面临诸多数据合规要求,例如:不同业务区域之间互相隔离、数据库仅能由关联的应用服务器访问、仅有特定的服务器允许被外网访问等。对此,某跨境支付机构以 SmartX 榫卯企业云平台构建私…

Win10下python环境变量呼出微软应用商店

以下是三种彻底解决 Windows 10 的 CMD 中运行 python 命令弹出应用商店问题的方法​​方法一:调整环境变量优先级​-或者直接删除微软应用商店的环境变量%USERPROFILE%\AppData\Local\Microsoft\WindowsApp​​​操作步骤​​打开系统环境变量设置(右键…

字节跳动“扣子”(Coze)开源:AI智能体生态的技术革命

(以下借助 DeepSeek-R1 辅助整理) 在2025年7月26日的深夜,GitHub上悄然出现的两个仓库——Coze Studio和Coze Loop,在48小时内狂揽超过9,000颗Star。字节跳动以Apache 2.0许可证将自家AI智能体平台的核心技术彻底开源。 “当所有人…

Camx-usecase ID和pipeline的匹配源码解读

组件关系整体流程:camxhal3.cpp:704 open()camxhal3.cpp:1423 configure_streams()chxextensionmodule.cpp:2810 InitializeOverrideSessionchxusecaseutils.cpp:850 GetMatchingUsecase()chxadvancedcamerausecase.cpp:4729 Initialize()chxadvancedcamerausecase.…

日志管理进入「对话式」时代:日志易MCP Server落地实录

01 背景:MCP协议介绍在AI蓬勃发展的当下,大型语言模型(LLM)虽展现出强大潜力,却受困于与外部资源连接的难题。数据分散、接口繁杂,致使AI模型难以灵活对接本地资源与远程服务,极大限制了其响应质…

django-3模型操作

from django.db import modelsclass Book(models.Model):title models.CharField(max_length200) # 书名author models.CharField(max_length100) # 作者publish_date models.DateField() # 出版日期price models.DecimalField(max_digits10, decimal_places2) # 价格s…

【绘制图像轮廓】——图像预处理(OpenCV)

目录 1 什么是轮廓 2 寻找轮廓 2.1 mode参数 2.2 method参数 3 绘制轮廓 1 什么是轮廓 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。轮廓是连续的,边缘不一定连续。轮廓是一个闭合的、封闭的形状。 轮廓的作用: 形状分析 目…