一文讀懂層次聚類(Python程式碼)
首先要說,聚類屬於機器學習的無監督學習,而且也分很多種方法,例如大家熟知的有K-means。層次聚類也是聚類中的一種,也很常用。以下我先簡單回顧K-means的基本原理,然後慢慢引出層次聚類的定義和分層步驟,這樣更有助於大家理解。
層次聚類和K-means有什麼不同?
K-means 工作原理可以簡單概述為:
- 決定簇數(k)
- 從資料中隨機選取k 個點作為質心
- 將所有點分配到最近的聚類質心
- 計算新形成的簇的質心
- 重複步驟3 和4
這是一個迭代過程,直到新形成的簇的質心不變,或達到最大迭代次數。
但是K-means 是存在一些缺點的,我們必須在演算法開始前就決定簇數K 的數量,但實際上我們並不知道應該有多少個簇,所以一般都是根據自己的理解先設定一個值,這可能導致我們的理解和實際情況存在一些偏差。
層次聚類完全不同,它不需要我們開始的時候指定簇數,而是先完整的形成整個層次聚類後,透過決定合適的距離,自動就可以找到對應的簇數和聚類。
什麼是層次聚類?
下面我們由淺及深的介紹什麼是層次聚類,先來一個簡單的例子。
假設我們有以下幾點,我們想要將它們分組:
我們可以將這些點中的每一個分配給一個單獨的簇,就是4個簇(4種顏色):
然後基於這些簇的相似性(距離),將最相似的(距離最近的)點組合在一起並重複這個過程,直到只剩下一個群集:
上面本質上就是在建構一個層次結構。先了解到這裡,後面我們詳細介紹它的分層步驟。
層次聚類的類型
主要有兩種類型的層次聚類:
- 凝聚層次聚類
- 分裂層次聚類
凝聚層次聚類
先讓所有點分別成為一個單獨的簇,然後透過相似性不斷組合,直到最後只有一個簇為止,這就是凝聚層次聚類的過程,和我們上面剛剛說的一致。
分裂層次聚類
分裂層次聚類正好反過來,它是從單一集群開始逐步分裂,直到無法分裂,即每個點都是一個簇。
所以無論是10、100、1000 個資料點都不重要,這些點在開始的時候都屬於同一個叢集:
現在,在每次迭代中拆分簇中相隔最遠的兩點,並重複這個過程,直到每個簇只包含一個點:
上面的過程就是分裂層次聚類。
執行層次聚類的步驟
上面已經說了層次聚類的大概過程,那關鍵的來了,如何確定點和點的相似性呢?
這是聚類中最重要的問題之一了,一般計算相似度的方法是:計算這些簇的質心之間的距離。距離最小的點稱為相似點,我們可以合併它們,也可以稱為基於距離的演算法。
另外在層次聚類中,還有一個稱為鄰近矩陣的概念,它儲存了每個點之間的距離。以下我們透過一個例子來理解如何計算相似度、鄰近矩陣、以及層次聚類的具體步驟。
案例介紹
假設一位老師想要將學生分成不同的組別。現在有每個學生在作業中的分數,想根據這些分數將他們分成幾組。關於擁有多少組,這裡沒有固定的目標。由於老師不知道應該將哪種類型的學生分配到哪個組,因此不能作為監督學習問題來解決。下面,我們將嘗試應用層次聚類將學生分成不同的群組。
下面是5名學生的成績:
建立鄰近矩陣
首先,我們要建立一個鄰近矩陣,它儲存了每個點兩兩之間的距離,因此可以得到一個形狀為n X n 的方陣。
這個案例中,可以得到以下5 x 5 的鄰近矩陣:
#矩陣裡有兩點要注意下:
- 矩陣的對角元素總是0,因為點與其自身的距離總是0
- 使用歐幾裡得距離公式來計算非對角元素的距離
例如,我們要計算點1 和2 之間的距離,計算公式為:
#同理,依此計算方法完成後填入鄰近矩陣其餘元素。
執行層次聚類
這裡使用凝聚層次聚類來實作。
步驟1:首先,我們將所有點分配成單一簇:
#這裡不同的顏色代表不同的簇,我們資料中的5 個點,即有5 個不同的簇。
步驟2:接下來,我們需要找出鄰近矩陣中的最小距離並合併距離最小的點。然後我們更新鄰近矩陣:
最小距離是3,因此我們將合併點1 和2:
讓我們看看更新的群集並相應地更新鄰近矩陣:
更新之後,我們取了1、2 兩個點中位數(7, 10) 最大的來替換這個簇的值。當然除了最大值之外,我們還可以取最小值或平均值。然後,我們將再次計算這些簇的鄰近矩陣:
第 3 步:重複第 2 步,直到只剩下一個簇。
重複所有的步驟後,我們將得到如下所示的合併的聚類:
#這就是凝聚層次聚類的工作原理。但問題是我們仍然不知道該分幾組?是2、3、還是4組呢?
下面開始介紹如何選擇聚類數。
如何選擇聚類數?
為了得到層次聚類的群集數,我們使用了一個概念,叫作樹狀圖。
透過樹狀圖,我們可以更方便的選出聚類的簇數。
回到上面的例子。當我們合併兩個簇時,樹狀圖會相應地記錄這些簇之間的距離並以圖形形式表示。下面這個是樹狀圖的原始狀態,橫座標記錄了每個點的標記,縱軸記錄了點和點之間的距離:
透過樹狀圖,我們可以清楚地形象化層次聚類的步驟。樹狀圖中垂直線的距離越遠代表簇之間的距離越大。
有了這個樹狀圖,我們決定簇類別數就方便多了。
現在我們可以設定一個閾值距離,繪製一條水平線。例如我們將閾值設為12,並繪製一條水平線,如下:
#從交點中可以看到,聚類的數量就是與閾值水平線與垂直線相交的數量(紅線與2 條垂直線相交,我們將有2 個簇)。與橫座標相對應的,一個簇將有一個樣本集合為 (1,2,4),另一個群集將有一個樣本集合 (3,5)。
這樣,我們就透過樹狀圖解決了分層聚類中要決定聚類的數量。
Python程式碼實戰案例
上面是理論基礎,有點數學基礎看得懂。以下介紹下在如何用程式碼Python來實現這個過程。這裡拿一個客戶細分的數據來展示一下。
資料集和程式碼在我的GitHub倉庫裡:
https://github.com/xiaoyusmd/PythonDataScience
#如果覺得有幫助,還請給個star!
這個資料是來自UCI 機器學習函式庫。我們的目的是根據批發分銷商的客戶在不同產品類別(如牛奶、雜貨、地區等)上的年度支出,將他們細分。
首先對資料進行一個標準化,為了讓所有資料在同一個維度便於計算,然後應用層次聚類來細分客戶。
from sklearn.preprocessing import normalize data_scaled = normalize(data) data_scaled = pd.DataFrame(data_scaled, columns=data.columns) import scipy.cluster.hierarchy as shc plt.figure(figsize=(10, 7)) plt.title("Dendrograms") dend = shc.dendrogram(shc.linkage(data_scaled, method='ward'))
x 軸包含了所有樣本,y 軸代表這些樣本之間的距離。距離最大的垂直線是藍線,假如我們決定要以閾值6 切割樹狀圖:
plt.figure(figsize=(10, 7)) plt.title("Dendrograms") dend = shc.dendrogram(shc.linkage(data_scaled, method='ward')) plt.axhline(y=6, color='r', linestyle='--')
現在我們有兩個簇了,我們要對這2個簇應用層次聚類:
from sklearn.cluster import AgglomerativeClustering cluster = AgglomerativeClustering(n_clusters=2, affinity='euclidean', linkage='ward') cluster.fit_predict(data_scaled)
由於我們定義了2 個簇,因此我們可以在輸出中看到0 和1 的值。 0 代表屬於第一個簇的點,1 代表屬於第二個簇的點。
plt.figure(figsize=(10, 7)) plt.scatter(data_scaled['Milk'], data_scaled['Grocery'], c=cluster.labels_)
到這裡我們就成功的完成了聚類。
以上是一文讀懂層次聚類(Python程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。
