這個章節的主要目標是探討並比較不同的聚類演算法。此章節中使用Iris資料集練習五種主要聚類演算法:KMeans、MiniBatchKMeans、MeanShift、DBSCAN和AgglomerativeClustering,並熟悉這些演算法的基本實現和應用。
在Exercise則更進一步,以Olivetti Face資料集和20 Newsgroups文本資料集作為實驗對象,對每種聚類演算法進行了深入的參數優化和性能評估。並使用Silhouette Score作為評估指標,調整各演算法的關鍵參數,如KMeans的n_clusters、MeanShift的bandwith、DBSCAN的eps和min_samples值等,並通過視覺化圖表直觀呈現參數變化對聚類效果的影響。
OS: Windows 11 23H2
CPU: Intel Core i7-13700K
GPU: NVIDIA GeForce RTX 4070 SUPER 12G
RAM: DDR5 64G 5600MT/s
Python Package Manager: uv
Python Version: 3.10.16
Python Package: numpy, pandas, sklearn, rich, seaborn, matplotlib
IDE: Visual Studio Code
為方便查看運行結果,故額外使用rich函式庫建立兩個Function格式化印出指定內容。
19.1 Clustering Using K-Means
Code:
Explanation:
這段程式碼使用KMeans演算法對Iris資料集進行聚類分析。首先載入Iris資料集後,使用StandardScaler進行標準化處理。接著,透過設定參數n_clusters為3,來建立一個具有3個聚類的KMeans模型並訓練。然後再使用.labels_方法計算聚類預測結果並與原始類別進行比較,最後對一個新的測試觀測值進行預測,並最後輸出結果,包括群集中心和群集數量。
Discussion:
K-Means演算法的優點是實現簡單且計算效率高,能處理大型資料集。然而,它有幾個限制:對初始化中心點敏感、必須預先指定群集數量,且較適合處理凸形和等大小的群集,對非球形分佈的資料表現不佳。
Result:
19.2 Speeding Up K-Means Clustering
Code:
Explanation:
這段程式碼使用MiniBatchKMeans演算法對Iris 資料集進行聚類分析。與標準KMeans相比,此方法採用小批次(可透過設定參數batch_size來指定批次大小)處理資料。首先載入資料並使用StandardScaler方法標準化特徵,然後使用MiniBatchKMeans將資料分為3個群集(設定n_clusters參數為3)。最後計算預測標籤,進行新資料預測,並顯示結果、群集中心和群集數量。
Discussion:
MiniBatchKMeans的主要優點是運算速度快,特別適合大型資料集,因為它僅使用資料的小批次子集進行訓練。然而,由於只使用資料子集,其結果可能不如標準KMeans精確,且仍然繼承了KMeans的限制,如需預先指定群集數量和對初始化敏感等問題。
Result:
19.3 Clustering Using Mean Shift
Code:
Explanation:
這段程式碼使用MeanShift演算法對Iris資料集進行聚類分析。首先載入資料並使用StandardScaler方法標準化特徵,然後使用MeanShift算法自動尋找數據中的群集。透過設定參數n_jobs為 -1 以使用所有可用CPU核心加速計算。接著計算預測群集標籤,並與真實類別比較,預測新的觀測值屬於哪個群集,最後顯示結果、群集中心和群集數量。
Discussion:
MeanShift的最大優點是不需要預先指定群集數量,而是自動尋找資料中的自然群集。它也能識別非球形群集,處理不規則形狀的資料分佈。然而,此算法在大型資料集上計算成本較高,執行較慢,且對bandwidth參數的選擇較敏感,可能影響最終群集的數量和形狀。
Result:
19.4 Clustering Using DBSCAN
Code:
Explanation:
這段程式碼使用DBSCAN演算法對Iris資料集進行聚類分析。首先載入資料並使用StandardScaler方法標準化特徵,然後使用DBSCAN算法進行聚類。DBSCAN不需預先指定群集數量,而是通過點的密度關係自動找出群集。同時設定參數n_jobs為 -1 來使用所有可用CPU核心加速計算。接著顯示每個資料點所屬的群集標籤,其中 -1 表示被識別為噪音的點。
Discussion:
DBSCAN的優點是能自動發現任意形狀的群集,不需預先指定群集數量,且能夠識別噪音點。它特別適合處理有密度變化的資料集。然而,此算法對參數(eps和min_samples)較敏感,在不同密度的群集上表現不佳,且在高維資料上效能可能下降。
Result:
19.5 Clustering Using Hierarchical Merging
Code:
Explanation:
這段程式碼使用AgglomerativeClustering演算法對Iris資料集進行聚類分析。首先載入資料並使用StandardScaler方法標準化特徵,然後使用AgglomerativeClustering將資料分為3個群集(透過設定參數n_clusters為3)。AgglomerativeClustering採用自下而上的方法,初始將每個資料點視為獨立群集,然後逐步合併最相似的群集,直到達到指定的群集數量。最後程式顯示每個資料點所屬的群集標籤。
Discussion:
AgglomerativeClustering的優點是能產生具有解釋性的樹狀結構(樹狀圖),讓使用者可視化觀察不同層次的群集關係,且不需對資料分布做嚴格假設。然而,此方法計算複雜度高,對大型資料集效率較低,且一旦合併完成,無法重新分配資料點,因此早期的合併錯誤會影響最終結果。
Result:
Settings
這邊使用scikit-learn的real-world datasets中的20 Newsgroups Vectorized(大型)與Olivetti Face(小型)作為兩個不同數量級的對比資料集,對此章節中所有的聚類模型調整各項參數進行訓練與比較差異。
20 Newsgroups Vectorized 是一個廣泛用於文本分類任務的標準資料集,包含約18,000篇新聞組帖子,分佈於20個不同主題類別。此資料集在機器學習社群中常被用作基準測試數據。它已被預處理並向量化,使用TF-IDF (詞頻-逆文檔頻率)轉換為數值特徵向量,便於直接應用於機器學習模型,省去了文本預處理步驟。這些向量非常稀疏,平均每個樣本在超過30,000維的空間中只有約159個非零特徵(少於0.5%的非零元素),這反映了自然語言處理中常見的高維稀疏特性。
Olivetti Face 是一個經典的人臉識別資料集,收集了40位不同人士各10張灰階人臉照片,總共400張圖像。每張圖像尺寸為64×64像素,以人臉為中心。這些照片在不同時間、不同光照條件以及不同面部表情(開眼/閉眼、微笑/不微笑)和面部細節(有眼鏡/無眼鏡)下拍攝。資料集中的「目標」是從0到39的整數,表示照片中人物的身份。由於每個類別僅有10個樣本,這個相對較小的資料集在無監督或半監督學習方面更具研究價值,被廣泛應用於人臉識別、圖像重建和降維技術等研究中。
Explanation:
首先透過sklearn提供的fetch_olivetti_faces與fetch_20newsgroups_vectorized方法載入兩個資料集,對於Olivetti Faces資料集使用StandardScaler方法進行標準化,而由於20 Newsgroups原本的資料集為文字,非向量,故改為使用20 Newsgroups Vectorized以減去處理文字的步驟,並且由於20 Newsgroups Vectorized資料集為稀疏矩陣,故使用MaxAbsScaler方法對資料集進行標準化
Code:
KMeans
Explanation:
接著對KMeans演算法使用兩種不同的資料集進行訓練與測試在不同n_clusters下的Silhouette Score如何。
Silhouette Score是一種用於評估聚類結果品質的數值指標,它可以衡量每個數據點與自身所在聚類的相似程度(凝聚性)以及與其他聚類的區分程度(分離性)。Silhouette Score的值範圍在 -1 到 +1 之間,值接近 +1 表示該點非常適合其所屬聚類且與其他聚類明顯分離,值接近 0 表示該點位於聚類邊界附近,而負值則表示該點可能被錯誤分類。一般而言,平均輪廓係數大於0.7被視為強聚類結構,大於0.5被視為合理聚類結構,大於0.25則被視為較弱的聚類結構。
Code:
Result:
Discussion:
根據左圖結果顯示,Olivetti Faces資料集的Silhouette Score整體呈現正值,最高點出現在n_clusters=2時,達到約0.1824的高分,隨後雖然有所下降,但仍維持在正值區間波動。這表明Olivetti Faces資料集具有相對明確的自然分群結構,即使增加叢集數量,模型仍能找到合理的分群界限。特別值得注意的是,在n_clusters約為40、60、70-80時出現局部高點,這可能反映了資料中存在階層式的分組結構,這與人臉資料集的特性相符,因為人臉可能按照多種不同特徵(如年齡、性別、表情等)進行分類。
相比之下,右圖的20 Newsgroups資料集的Silhouette Score表現則相差許多。雖然在n_clusters=2時勉強保持正值(約0.0062),但隨著叢集數量增加,輪廓係數迅速降至負值,並在整個測試範圍內都維持負值。這種表現顯示文本資料的複雜性遠高於圖像資料,文本間的語義連結與主題重疊使得簡單的歐氏距離無法有效區分新聞組的自然邊界。更有趣的是,圖表顯示在n_cluster約為55時有一個明顯的降階,這可能表明在此點後,模型開始強行將本應屬於同一類別的文本分入不同叢集,進一步破壞了分群的自然性。
MiniBatch KMeans
Explanation:
接下來對MiniBatchKMeans演算法使用兩種不同資料集進行訓練與評估,這邊除了測試n_clusters參數以外,還額外測試了batch_size參數對於結果的影響。
這邊對於20 Newsgroups資料集還需要額外使用TruncatedSVD方法進行降維的處理,以更好的處理稀疏矩陣造成的問題。
Code:
Result:
Discussion:
在左方兩圖的Olivetti Face資料集的表現上,可觀察到n_clusters參數對輪廓係數有顯著影響。當n_clusters=2時,模型達到最佳Silhouette Score 0.2086,隨著叢集數增加,Silhouette Score雖然呈現波動但仍維持在正值範圍內(約0.05至0.12之間)。這表示Olivetti Face資料集具有多層次的分群結構,雖然最自然的分割是二分法,但其他叢集數量同樣能找到有意義的分組。而在batch_size方面,當n_clusters固定為3時,一旦batch_size達到300,Silhouette Score就達到最高值0.1073並在此後保持穩定。這一穩定性說明在處理結構相對規律的圖像資料時,MiniBatchKMeans一旦達到足夠的批次大小,其性能便不再顯著改善。
對比之下,右方兩圖的20 Newsgroups資料集呈現出截然不同的特性。從n_clusters角度看,最佳表現同樣出現在較小的叢集數(n_clusters = 3,Silhouette Score為0.1356),但隨著叢集數增加,性能明顯下降,部分高叢集數區域甚至出現負值。這反映了新聞文本的語義重疊性,當強制分為過多類別時,類別間界線變得模糊不清。而在batch_size測試中,20 Newsgroups展現出高度的不穩定性,Silhouette Score在不同批次大小間大幅波動,並在batch_size=6300處突然達到0.5301高峰,此後又迅速下降並在更大批次時趨於零。此種不穩定性揭示了處理高維文本資料時批次大小的選擇極為關鍵,過小的批次無法捕捉全局特徵,而過大的批次則可能造成過度擬合特定結構。
MeanShift
Explanation:
接下來針對MeanShift演算法使用兩種不同的資料集進行訓練與評估,而這次測試的參數是bandwith,首先使用estimate_bandwith找出預設的bandwith後,再與自訂範圍進行比較差異。
這邊特別對於model.predict的結果進行比較,由於計算Silhouette Score最少需要兩個類別,若結果少於兩個類別則會報錯,故直接將少於兩個類別的score分數定為-1。
Code:
Result:
Discussion:
在左上圖的Olivetti Face資料集中,bandwith參數展現出較為平穩的性能曲線。可以觀察到,當bandwith值低於60時,Silhouette Score大多維持在接近零或輕微正值的範圍,並在bandwith值42.58時達到最佳表現0.1095。值得注意的是,這個最優bandwith值明顯小於基本bandwith 79.24,意味著預設參數可能不是最佳選擇。而當bandwith值超過65後,模型性能急劇下降,Silhouette Score迅速跌至-1.0,表明在處理圖像數據時,過大的bandwith會導致嚴重的過度平滑,使得聚類結果完全失效。這種相對溫和的曲線形狀反映了圖像數據中像素分佈的連續性特性,在一定範圍內對bandwith變化具有一定的容忍度。
相比之下,右上圖的20 Newsgroups文本資料集對bandwith參數表現出截然不同的敏感性。圖表顯示,在低bandwith值(小於1.0)區域,Silhouette Score為負值,表示過小的bandwith無法有效捕捉文本語義結構。當bandwith值從1.0開始增加時,性能呈現劇烈提升,並在bandwith值2.07處達到最高點0.6734。這一數值顯著高於Olivetti資料集的最佳表現。有趣的是,其最優bandwith值略高於基本平均bandwith 1.52,並且一旦超過最優值,Silhouette Score便穩定在高位,不再顯著變化。這種曲線特徵揭示了文本資料具有更為離散的分佈特性,需要精確的bandwith設定才能正確識別語義群集,且存在一個明確的閾值,超過該閾值後便能穩定捕捉文本的自然分組。
DBSCAN
Explanation:
接下來使用DBSCAN演算法對兩種不同的資料集進行訓練與評估,這次調整的參數為eps與min_samples。由於DBSCAN演算法並無內建.predict方法,故必須連同eval_data也一同進行.fit後,才能使用.lables_方法獲取對應的labels進行計算Silhouette Score。
Code:
Result:
Discussion:
在Olivetti Face資料集中,DBSCAN的eps參數展現出極為嚴格的有效區間特性。從左上圖可見,只有當eps值落在約40至65之間時,模型才能產生正向的Silhouette Score,且在eps=42.68處達到最佳表現0.2439。一旦eps值低於35或高於70,Silhouette Score便驟降至-1.0,表明聚類完全失效。這種懸崖式的效應反映了圖像資料中像素距離的特殊分佈特性。同時,左下圖顯示min_samples參數對此資料集的影響同樣關鍵,只有當min_samples=2時才能獲得較高的Silhouette Score 0.1977,一旦超過此值,模型表現立即崩潰。這種對極小min_samples值的偏好可能源於人臉資料集中存在許多小型但高度相似的群組,增加密度要求會導致這些自然群組被忽略。整體而言,Olivetti資料集需要精確調校的eps值和極低的min_samples值才能達到有效聚類。
相較之下,20 Newsgroups文本資料集對DBSCAN模型的參數展現出截然不同的敏感性模式。右上圖顯示eps參數在此資料集上存在兩個表現良好的區間(約0.32附近和1.1附近),其中eps=0.32時達到0.8099 Silhouette Score,遠高於Olivetti資料集的最佳表現。更值得注意的是,這個最佳eps值比Olivetti資料集的最佳值小了兩個數量級,反映出文本向量空間中距離度量的根本差異。對於min_samples參數,右下圖展示了一個漸進式的性能曲線,隨著min_samples從1增加至12,Silhouette Score逐步提升至0.3547的峰值,而後急劇下降。這種對中等min_samples值的偏好表明20 Newsgroups資料集包含規模較大的自然主題群組,需要足夠的點密度來確立群組邊界,但過高的門檻又會導致群組碎片化。
Agglomerative Clustering
Explanation:
最後是針對AgglomerativeClustering演算法使用兩種不同的資料集進行訓練與評估,測試的參數使用n_cluster。
Code:
Result:
Discussion:
Olivetti Face資料集在AgglomerativeClustering模型下展現出階層性結構優勢。從左圖可見,當n_clusters=2時,Silhouette Score達到最高點0.1978,顯示資料在二分法下具有最佳的自然分群。隨著叢集數增加,性能呈現有趣的波動趨勢:先下降至約0.115,然後在n_clusters=20左右重新攀升,並在25-50的範圍內維持相對穩定的高Silhouette Score(約0.175)。這種曲線特徵暗示Olivetti資料集具有多層次的階層結構,能同時支持粗粒度(2個叢集)和中等粒度(20-50個叢集)的分析,且不同粒度捕捉了不同層面的特徵相似性。值得注意的是,即使在n_clusters接近100時,輪廓係數仍為正值,僅降至約0.01,證明階層聚類對於此類高維度但結構化的圖像資料有良好的適應性。
相比之下,右圖的20 Newsgroups文本資料集呈現截然不同的表現。最佳Silhouette Score僅為0.0774,出現在n_clusters=5時,遠低於Olivetti資料集的最佳表現。更重要的是,一旦n_clusters超過10,Silhouette Score便迅速下滑至0.02以下,並在整個測試範圍內持續徘徊在極低水平。這種急劇下降且缺乏明顯復甦的特性表明,文本資料的語義關係難以通過簡單的階層結構準確捕捉,特別是當被強制分入較多叢集時。儘管Silhouette Score始終保持正值,但其低數值意味著分群品質不高,叢集間界限模糊。這一現象可能源於20 Newsgroups文本的高維稀疏性與主題重疊性,使得傳統的階層聚類難以識別其中的自然分組。
Difficulties Encountered and Solutions
1. 載入20 Newsgroups資料集的問題
Difficulties:載入20 Newsgroups資料集並使用StandardScaler進行標準化時,若沒有設定參數with_mean為False的話,會造成出錯。
Solution:由於20 Newsgroups資料集的內容較不適合使用StandardScaler,故直接改為使用MaxAbsScaler,其能夠更好適用於20 Newsgroups資料集的稀疏矩陣,且同時可解決上述問題。
2. 訓練Mean Shift Model的問題
Difficulties:使用20 Newsgroups資料集訓練MeanShift模型時,由於20 Newsgroups資料集為稀疏矩陣,若沒有額外處理,則會出現以下錯誤訊息。
Solution:對20 Newsgroups資料集使用TruncatedSVD方法可將數據集進行降維以解決問題。
References
[1] Machine Learning with Python Cookbook-2nd, by Kyle Gallatin and Chris Albon, O'Reilly, 2023, ISBN: 9781098135720
[2] 機器學習入門:使用Scikit-Learn與TensorFlow, 黃建庭, 碁峰, 2021, ISBN: 9786263240285
[3] 精通機器學習:使用Scikit-Learn, Keras與TensorFlow(第三版), Aurélien Géron, 歐萊禮, 2024, ISBN: 9786263246676
[4] scikit-learn 機器學習實戰, 鄧立國 郭雅秋 陳子堯 鄧淇文, 清華大學, 2022, ISBN: 9787302604396
[5] Python資料科學學習手冊(第二版), Jake VanderPlas , 歐萊禮, 2023, ISBN: 9786263246843