層次聚類:無需“猜”K值,如何讓數據自己畫出“家族圖譜”?

層次聚類:無需“猜”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?(xai??xbi?)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=1n?xai??xbi?
  • “人話”解讀: 想象你在一個像曼哈頓那樣的棋盤式街區,你不能斜著穿過大樓,只能沿著街道走。從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?∥∥xb?xa??xb??=i=1n?xai2??i=1n?xbi2??i=1n?xai?xbi??
  • 轉換為距離: 余弦距離通常定義為 1?Cosine?Similarity1 - \text{Cosine Similarity}1?Cosine?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,bBmin?d(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,bBmax?d(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∣∣B1?aA?bB?d(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 什么是輪廓 輪廓是一系列相連的點組成的曲線,代表了物體的基本外形。輪廓是連續的,邊緣不一定連續。輪廓是一個閉合的、封閉的形狀。 輪廓的作用: 形狀分析 目…