[Python从零到壹] 十三.机器学习之聚类算法四万字总结全网首发(K-Means、BIRCH、树状聚类、MeanShift)
歡迎大家來到“Python從零到壹”,在這里我將分享約200篇Python系列文章,帶大家一起去學習和玩耍,看看Python這個有趣的世界。所有文章都將結合案例、代碼和作者的經驗講解,真心想把自己近十年的編程經驗分享給大家,希望對您有所幫助,文章中不足之處也請海涵。Python系列整體框架包括基礎語法10篇、網絡爬蟲30篇、可視化分析10篇、機器學習20篇、大數據分析20篇、圖像識別30篇、人工智能40篇、Python安全20篇、其他技巧10篇。您的關注、點贊和轉發就是對秀璋最大的支持,知識無價人有情,希望我們都能在人生路上開心快樂、共同成長。
前一篇文章講述了回歸模型的原理知識,包括線性回歸、多項式回歸和邏輯回歸,并詳細介紹Python Sklearn機器學習庫的線性回歸和邏輯回歸算法及案例。本文介紹聚類算法的原理知識級案例,包括K-Means聚類、BIRCH算法、PCA降維聚類、均值漂移聚類、文本聚類等。基礎文章,希望對您有所幫助。
文章目錄
- 一.聚類
- 1.算法模型
- 2.常見聚類算法
- 3.性能評估
- 二.K-Means
- 1.算法描述
- 2.K-Means聚類示例
- 3.Sklearn中K-Means用法介紹
- 4.K-Means分析籃球數據
- 5.K-Means聚類優化
- 6.設置類簇中心
- 三.Birch
- 1.算法描述
- 2.Birch分析氧化物數據
- 四.結合降維處理的聚類分析
- 1.PCA降維
- 2.Sklearn PCA降維
- 3.PCA降維實例
- 五.基于均值漂移的圖像聚類
- 1.MeanShift圖像聚類
- 2.K-Means圖像聚類
- 六.基于文本的樹狀關鍵詞聚類
- 七.總結
下載地址:
- https://github.com/eastmountyxz/Python-zero2one
前文賞析:
第一部分 基礎語法
- [Python從零到壹] 一.為什么我們要學Python及基礎語法詳解
- [Python從零到壹] 二.語法基礎之條件語句、循環語句和函數
- [Python從零到壹] 三.語法基礎之文件操作、CSV文件讀寫及面向對象
第二部分 網絡爬蟲
- [Python從零到壹] 四.網絡爬蟲之入門基礎及正則表達式抓取博客案例
- [Python從零到壹] 五.網絡爬蟲之BeautifulSoup基礎語法萬字詳解
- [Python從零到壹] 六.網絡爬蟲之BeautifulSoup爬取豆瓣TOP250電影詳解
- [Python從零到壹] 七.網絡爬蟲之Requests爬取豆瓣電影TOP250及CSV存儲
- [Python從零到壹] 八.數據庫之MySQL基礎知識及操作萬字詳解
- [Python從零到壹] 九.網絡爬蟲之Selenium基礎技術萬字詳解(定位元素、常用方法、鍵盤鼠標操作)
- [Python從零到壹] 十.網絡爬蟲之Selenium爬取在線百科知識萬字詳解(NLP語料構造必備技能)
第三部分 數據分析和機器學習
- [Python從零到壹] 十一.數據分析之Numpy、Pandas、Matplotlib和Sklearn入門知識萬字詳解(1)
- [Python從零到壹] 十二.機器學習之回歸分析萬字總結全網首發(線性回歸、多項式回歸、邏輯回歸)
- [Python從零到壹] 十三.機器學習之聚類分析萬字總結全網首發(K-Means、BIRCH、層次聚類、樹狀聚類)
作者新開的“娜璋AI安全之家”將專注于Python和安全技術,主要分享Web滲透、系統安全、人工智能、大數據分析、圖像識別、惡意代碼檢測、CVE復現、威脅情報分析等文章。雖然作者是一名技術小白,但會保證每一篇文章都會很用心地撰寫,希望這些基礎性文章對你有所幫助,在Python和安全路上與大家一起進步。
在過去,科學家會根據物種的形狀習性規律等特征將其劃分為不同類型的門類,比如將人種劃分為黃種人、白種人和黑種人,這就是簡單的人工聚類方法。聚類是將數據集中某些方面相似的數據成員劃分在一起,給定簡單的規則,對數據集進行分堆,是一種無監督學習。聚類集合中,處于相同聚類中的數據彼此是相似的,處于不同聚類中的元素彼此是不同的。本章主要介紹聚類概念和常用聚類算法,然后詳細講述Scikit-Learn機器學習包中聚類算法的用法,并通過K-Means聚類、Birch層次聚類及PAC降維三個實例加深讀者印象。
一.聚類
俗話說“物以類聚,人以群分”,聚類(Clustering)就是根據“物以類聚”的原理而得。從廣義上說,聚類是將數據集中在某些方面相似的數據成員放在一起,聚類中處于相同類簇中的數據元素彼此相似,處于不同類簇中的元素彼此分離。
由于在聚類中那些表示數據類別的分組信息或類標是沒有的,即這些數據是沒有標簽的,所有聚類又被稱為無監督學習(Unsupervised Learning)。
1.算法模型
聚類是將本身沒有類別的樣本聚集成不同類型的組,每一組數據對象的集合都叫做簇。聚類的目的是讓屬于同一個類簇的樣本之間彼此相似,而不同類簇的樣本應該分離。圖1表示聚類的算法模型圖。
聚類模型的基本步驟包括:
- 訓練。通過歷史數據訓練得到一個聚類模型,該模型用于后面的預測分析。需要注意的是,有的聚類算法需要預先設定類簇數,如KMeans聚類算法。
- 預測。輸入新的數據集,用訓練得到的聚類模型對新數據集進行預測,即分堆處理,并給每行預測數據計算一個類標值。
- 可視化操作及算法評價。得到預測結果之后,可以通過可視化分析反應聚類算法的好壞,如果聚類結果中相同簇的樣本之間距離越近,不同簇的樣本之間距離越遠,其聚類效果越好。同時采用相關的評價標準對聚類算法進行評估。
常用聚類模型包括:
- K-Means聚類
- 層次聚類
- DBSCAN
- Affinity Propagatio
- MeanShift
2.常見聚類算法
聚類算法在Scikit-Learn機器學習包中,主要調用sklearn.cluster子類實現,下面對常見的聚類算法進行簡單描述,后面主要介紹K-Means算法和Birch算法實例。
(1) K-Means
K-Means聚類算法最早起源于信號處理,是一種最經典的聚類分析方法。它是一種自下而上的聚類方法,采用劃分法實現,其優點是簡單、速度快;缺點是必須提供聚類的數目,并且聚類結果與初始中心的選擇有關,若不知道樣本集要聚成多少個類別,則無法使用K-Means算法。Sklearn包中調用方法如下:
(2) Mini Batch K-Means
Mini Batch K-means是KMeans的一種變換,目的為了減少計算時間。其實現類是MiniBatchKMeans。Sklearn包中調用方法如下:
(3) Birch
Birch是平衡迭代歸約及聚類算法,全稱為Balanced Iterative Reducing and Clustering using Hierarchies,是一種常用的層次聚類算法。該算法通過聚類特征(Clustering Feature,CF)和聚類特征樹(Clustering Feature Tree,CFT)兩個概念描述聚類。聚類特征樹用來概括聚類的有用信息,由于其占用空間小并且可以存放在內存中,從而提高了算法的聚類速度,產生了較高的聚類質量,Birch算法適用于大型數據集。
Sklearn包中調用方法如下:
from sklearn.cluster import Birch X = [[1],[2],[3],[4],[3],[2]] clf = Birch(n_clusters=2) clf.fit(X) y_pred = clf.fit_predict(X) print(clf) print(y_pred) #輸出:[1 1 0 0 0 1]上述代碼調用Birch算法聚成兩類,并對X數據進行訓練,共6個點(1、2、3、4、3、2),然后預測其聚類后的類標,輸出為0或1兩類結果,其中點1、2、2輸出類標為1,點3、4、3輸出類標為0。這是一個較好的聚類結果,因為值較大的點(3、4)聚集為一類,值較小的點(1、2)聚集為另一類。這里只是進行了簡單描述,后面將講述具體的算法及實例。
(4) Mean Shift
Mean Shift是均值偏移或均值漂移聚類算法,最早是1975年Fukunaga等人在一篇關于概率密度梯度函數的估計論文中提出。它是一種無參估計算法,沿著概率梯度的上升方向尋找分布的峰值。Mean Shift算法先算出當前點的偏移均值,移動該點到其偏移均值,然后以此為新的起始點,繼續移動,直到滿足一定的條件結束。
(5) DBSCAN
DBSCAN是一個典型的基于密度的聚類算法,它與劃分聚類方法、層次聚類方法不同,它將簇定義為密度相連的點的最大集合,能夠把具有足夠高密度的區域劃分為簇,并可在噪聲的空間數據庫中發現任意形狀的聚類。與K-Means方法相比,DBSCAN不需要事先知道要形成的簇類的數目,它可以發現任意形狀的簇類,同時該算法能夠識別出噪聲點,對于數據集中樣本的順序不敏感。但也存在一定缺點:DBSCAN聚類算法不能很好反映高維數據。
3.性能評估
聚類根據文檔的相似性把一個文檔集合中的文檔分成若干類,但是究竟分成多少類,這個要取決于文檔集合里文檔自身的性質。圖3是Scikit-Learn官網中DBSCAN聚類示例結果,該聚類算法應該把文檔集合分成3類,而不是2類或4類,這就涉及到了聚類算法評價。
聚類算法的評價應該考慮:聚類之間是否較好地相互分離、同一類簇中的點是否都靠近的中心點、聚類算法是否正確識別數據的類簇或標記。聚類算法的常見評價指標包括純度(Purity)、F值(F-measure)、熵值(Entropy)和RI,其中F值最為常用。
(1) F值(F-measure)
F值(F-measure或F-score)的計算包括兩個指標:精確率(Precision)和召回率(Recall)。精確率定義為檢索出相關文檔數與檢索出的文檔總數的比率,衡量的是檢索系統的查準率;召回率定義為檢索出的相關文檔數和文檔庫中所有相關文檔數的比率,衡量的是檢索系統的查全率。公式如下:
其中,參數N表示實驗結果中正確識別出的聚類類簇數,S表示實驗結果中實際識別出的聚類類簇數,T表示數據集中所有真實存在的聚類相關類簇數。
精確率和召回率兩個評估指標在特定的情況下是相互制約的,因而很難使用單一的評價指標來衡量實驗的效果。F-值是準確率和召回率的調和平均值,它可作為衡量實驗結果的最終評價指標,F值更接近兩個數中較小的那個。F值指的計算公式如下公式所示:
(2) 純度(Purity)
Purity方法是極為簡單的一種聚類評價方法,它表示正確聚類的文檔數占總文檔數的比例。公式如下:
其中,參數m表示整個聚類劃分涉及的成員個數;聚類i的純度定義為Pi;K表示聚類的類簇數目。舉個示例,假設聚類成3堆,其中x表示一類數據集,o表示一類數據集,◇表示一類數據集,如圖4所示。
純度為正確聚類的文檔數占總文檔數的比例,即:purity=(5+4+3)/17=0.71。其中第一堆聚集正確5個x,第二堆正確聚集4個o,第三隊正確聚集3個◇。Purity方法優點在于計算過程簡便,值在0~1之間,完全錯誤的聚類方法值為0,完全正確的聚類方法值為1;其缺點是無法對聚類方法給出正確的評價,尤其是每個文檔單獨聚集成一類的情況。
(3) 蘭德指數(RI)
蘭德指數(Rand Index,簡稱RI)是一種用排列組合原理來對聚類進行評價的手段,公式如下:
其中參數TP表示被聚在一類的兩個文檔被正確分類,TN表示不應該被聚在一類的兩個文檔被正確分開,FP表示不應該放在一類的文檔被錯誤的放在了一類,FN表示不應該分開的文檔被錯誤的分開。
RI越大表示聚類效果準確性越高,同時每個類內的純度越高,更多評價方法請讀者結合實際數據集進行分析。
二.K-Means
K-Means聚類是最常用的聚類算法,最初起源于信號處理,其目標是將數據點劃分為K個類簇,找到每個簇的中心并使其度量最小化。該算法的最大優點是簡單、便于理解,運算速度較快,缺點是只能應用于連續型數據,并且要在聚類前指定聚集的類簇數。
1.算法描述
(1) K-Means聚類算法流程
下面作者采用通俗易懂的方法描述K-Means聚類算法的分析流程,步驟如下:
- 第一步,確定K值,即將數據集聚集成K個類簇或小組。
- 第二步,從數據集中隨機選擇K個數據點作為質心(Centroid)或數據中心。
- 第三步,分別計算每個點到每個質心之間的距離,并將每個點劃分到離最近質心的小組,跟定了那個質心。
- 第四步,當每個質心都聚集了一些點后,重新定義算法選出新的質心。
- 第五步,比較新的質心和老的質心,如果新質心和老質心之間的距離小于某一個閾值,則表示重新計算的質心位置變化不大,收斂穩定,則認為聚類已經達到了期望的結果,算法終止。
- 第六步,如果新的質心和老的質心變化很大,即距離大于閾值,則繼續迭代執行第三步到第五步,直到算法終止。
圖5是對身高和體重進行聚類的算法,將數據集的人群聚集成三類。
2.K-Means聚類示例
下面通過一個例子講解K-Means聚類算法,從而加深讀者的印象。假設存在如下表1所示六個點,需要將其聚類成兩堆。流程如下:
坐標點 X坐標 Y坐標 P1 1 1 P2 2 1 P3 1 3 P4 6 6 P5 8 5 P6 7 8在坐標軸中繪制這6個點的分布如圖6所示。
第一步:隨機選取質心。假設選擇P1和P2點,它們則為聚類的中心。
第二步:計算其他所有點到質心的距離。
計算過程采用勾股定理,如P3點到P1的距離為:
P3點到P2距離為:
P3離P1更近,則選擇跟P1聚集成一堆。同理P4、P5、P6算法如下:
此時聚類分堆情況如下:
- 第一組:P1、P3
- 第二組:P2、P4、P5、P6
第三步:組內從新選擇質心。
這里涉及到距離的計算方法,通過不同的距離計算方法可以對K-Means聚類算法進行優化。這里計算組內每個點X坐標的平均值和Y坐標的平均值,構成新的質心,它可能是一個虛擬的點。
- 第一組新質心:
- 第二組新質心:
第四步:再次計算各點到新質心的距離。此時可以看到P1、P2、P3離PN1質心較近,P4、P5、P6離PN2質心較近。
則聚類分堆情況如下,注意由于新的質心PN1和PN2是虛擬的兩個點,則不需要對PN1和PN2進行分組。。
- 第一組:P1、P2、P3
- 第二組:P4、P5、P6
第五步:同理,按照第三步計算新的質心。
- 第一組新質心:
- 第二組新質心:
第六步:計算點到新的質心距離。
這時可以看到P1、P2、P3離PN1更近,P4、P5、P6離PN2更近,所以第二聚類分堆的結果是:
- 第一組:P1、P2、P3
- 第二組:P4、P5、P6
結論:此時發現,第四步和第六步分組情況都是一樣的,說明聚類已經穩定收斂,聚類結束,其聚類結果P1、P2、P3一組,P4、P5、P6是另一組,這和我們最初預想的結果完全一致,說明聚類效果良好。這就是KMeans聚類示例的完整過程。
3.Sklearn中K-Means用法介紹
在Sklearn機器學習包中,調用cluster聚類子庫的Kmeans()函數即可進行Kmeans聚類運算,該算法要求輸入聚類類簇數。KMeans聚類構造方法如下:
sklearn.cluster.KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300, tol=0.0001, precompute_distances=True, verbose=0, random_state=None, copy_x=True, n_jobs=1)其中,參數解釋如下:
- n_clusters:表示K值,聚類類簇數
- max_iter:表示最大迭代次數,可省略
- n_init:表示用不同初始化質心運算的次數,由于K-Means結果是受初始值影響的局部最優的迭代算法,因此需要多運行幾次算法以選擇一個較好的聚類效果,默認是10,一般不需要更改,如果你的K值較大,則可以適當增大這個值
- Init:是初始值選擇的方式,可以為完全隨機選擇’random’,優化過的’k-means++‘或者自己指定初始化的K個質心,建議使用默認的’k-means++’
下面舉個簡單的實例,分析前面的例子中的6個點,設置聚類類簇數為2(n_clusters=2),調用KMeans(n_clusters=2)函數聚類,通過clf.fit()函數裝載數據訓練模型。代碼如下:
from sklearn.cluster import KMeans X = [[1,1],[2,1],[1,3],[6,6],[8,5],[7,8]] y = [0,0,0,1,1,1] clf = KMeans(n_clusters=2) clf.fit(X,y) print(clf) print(clf.labels_)輸出結果如下:
>>> KMeans(copy_x=True, init='k-means++', max_iter=300, n_clusters=2, n_init=10,n_jobs=1, precompute_distances='auto', random_state=None, tol=0.0001,verbose=0) [0 0 0 1 1 1] >>>clf.labels_表示輸出K-means聚類后的類標。由于聚類類簇設置為2,故類標為0或1,其中X[1,1]、X[2,1]、X[1,3]聚類后屬于0類,X[6,6]、X[8,5]、X[7,8]聚類后屬于1類。
調用Matplotlib擴展包的scatter()函數可以繪制散點圖,代碼的具體含義將在接下來的K-Means分析籃球數據中詳細介紹。代碼如下:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 from sklearn.cluster import KMeans X = [[1,1],[2,1],[1,3],[6,6],[8,5],[7,8]] y = [0,0,0,1,1,1] clf = KMeans(n_clusters=2) clf.fit(X,y) print(clf) print(clf.labels_)import matplotlib.pyplot as plt a = [n[0] for n in X] b = [n[1] for n in X] plt.scatter(a, b, c=clf.labels_) plt.show()輸出結果如圖7所示,其中右上角紅色三個點聚集在一起,左下角藍色三個點聚集在一起,聚類效果明顯。
讀者為了區分,建議將不同類簇的點繪制成不同類型的散點圖,便于對比觀察。
4.K-Means分析籃球數據
(1) 籃球數據集
數據集使用的是籃球運動員數據:KEEL-dateset Basketball dataset,下載地址為:
- http://sci2s.ugr.es/keel/dataset.php?cod=1293
該數據集主要包括5個特征,共96行數據,特征包括運動員身高(height)、每分鐘助攻數(assists_per_minute)、運動員出場時間(time_played)、運動員年齡(age)和每分鐘得分數(points_per_minute)。其特征和值域如圖8所示,比如每分鐘得分數為0.45,一場正常的NBA比賽共48分鐘,則場均能得21.6分。
下載籃球數據集,前20行數據如圖9所示。
(2) K-Means聚類
現在需要通過籃球運動員的數據,判斷該運動員在比賽中屬于什么位置。如果某個運動員得分能力比較強,他可能是得分后衛;如果籃板能力比較強,他可能是中鋒。
下面獲取助攻數和得分數兩列數據的20行,相當于20*2矩陣。主要調用Sklearn機器學習包的KMeans()函數進行聚類,調用Matplotlib擴展包繪制圖形。完整代碼如下:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 from sklearn.cluster import KMeans X = [[0.0888, 0.5885], [0.1399, 0.8291], [0.0747, 0.4974], [0.0983, 0.5772], [0.1276, 0.5703], [0.1671, 0.5835], [0.1906, 0.5276], [0.1061, 0.5523], [0.2446, 0.4007], [0.1670, 0.4770], [0.2485, 0.4313], [0.1227, 0.4909], [0.1240, 0.5668], [0.1461, 0.5113], [0.2315, 0.3788], [0.0494, 0.5590], [0.1107, 0.4799], [0.2521, 0.5735], [0.1007, 0.6318], [0.1067, 0.4326], [0.1956, 0.4280] ] print(X)# Kmeans聚類 clf = KMeans(n_clusters=3) y_pred = clf.fit_predict(X) print(clf) print(y_pred) # 可視化操作 import numpy as np import matplotlib.pyplot as plt x = [n[0] for n in X] y = [n[1] for n in X]plt.scatter(x, y, c=y_pred, marker='x') plt.title("Kmeans-Basketball Data") plt.xlabel("assists_per_minute") plt.ylabel("points_per_minute") plt.legend(["Rank"]) plt.show()運行結果如下圖10所示,從圖中可以看到聚集成三類,頂部紅色點所代表的球員比較厲害,得分和助攻都比較高,可能類似于NBA中喬丹、科比等得分巨星;中間藍色點代表普通球員那一類;右下角綠色表示助攻高得分低的一類球員,可能是控位。代碼中y_pred表示輸出的聚類類標,類簇數設置為3,則類標位0、1、2,它與20個球員數據一一對應。
(3) 代碼詳解
推薦讀者結合作者分享的文件用法進行讀取及聚類。
-
from sklearn.cluster import KMeans
表示在sklearn包中導入KMeans聚類模型,調用 sklearn.cluster.KMeans 這個類。 -
X = [[164,62],[156,50],…]
X是數據集,包括2列20行,對應20個球員的助攻數和得分數。 -
clf = KMeans(n_clusters=3)
表示調用KMeans()函數聚類分析,并將數據集聚集成類簇數為3后的模型賦值給clf。 -
y_pred =clf.fit_predict(X)
調用clf.fit_predict(X)函數對X數據集(20行數據)進行聚類分析,并將預測結果賦值給y_pred變量,每個y_pred對應X的一行數據,聚成3類,類標分別為0、1、2。 -
print(y_pred)
輸出預測結果:[0 2 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1]。 -
import matplotlib.pyplot as plt
導入matplotlib.pyplot擴展包來進行可視化繪圖,as表示重命名為plt,便于后續調用。 -
x = [n[0] for n in X]
y = [n[1] for n in X]
分別獲取獲取第1列和第2列值,并賦值給x和y變量。通過for循環獲取,n[0]表示X第一列,n[1]表示X第2列。 -
plt.scatter(x, y, c=y_pred, marker=‘o’)
調用scatter()函數繪制散點圖,橫軸為x,獲取的第1列數據;縱軸為y,獲取的第2列數據;c=y_pred為預測的聚類結果類標;marker='o’說明用點表示圖形。 -
plt.title(“Kmeans-Basketball Data”)
表示繪制圖形的標題為“Kmeans-Basketball Data”。 -
plt.xlabel(“assists_per_minute”)
-
plt.ylabel(“points_per_minute”)
表示輸出圖形x軸的標題和y軸的標題。 -
plt.legend([“Rank”])
設置右上角圖例。 -
plt.show()
最后調用show()函數將繪制的圖形顯示出來。
5.K-Means聚類優化
上面的代碼存在一個問題是需要優化的,可能細心的讀者已經發現了。那就是前面的代碼定義了X數組(共20行、每行2個特征),再對其進行數據分析,而實際數據集通常存儲在TXT、CSV、XLS等格式文件中,并采用讀取文件的方式進行數據分析的。那么,如何實現讀取文件中數據再進行聚類分析的代碼呢?
接下來,作者將完整的96行籃球數據存儲至TXT文件進行讀取操作,再調用K-Means算法聚類分析,并將聚集的三類數據繪制成想要的顏色和形狀。假設下載的籃球數據集存在在本地data.txt文件中,如下所示。
首先,需要將data.txt數據讀取,然后賦值到data變量數組中,代碼如下。
# -*- coding: utf-8 -*- import osdata = [] for line in open("data.txt", "r").readlines(): line = line.rstrip() #刪除換行 result = ' '.join(line.split()) #刪除多余空格,保存一個空格連接#獲取每行的五個值,如'0 0.0888 201 36.02 28 0.5885',并將字符串轉換為小數 s = [float(x) for x in result.strip().split(' ')] #輸出結果:['0', '0.0888', '201', '36.02', '28', '0.5885'] print(s) #數據存儲至data data.append(s) #輸出完整數據集 print(data) print(type(data))現在輸出的結果如下:
['0 0.0888 201 36.02 28 0.5885', '1 0.1399 198 39.32 30 0.8291', '2 0.0747 198 38.80 26 0.4974', '3 0.0983 191 40.71 30 0.5772', '4 0.1276 196 38.40 28 0.5703',.... ]然后需要獲取數據集中的任意兩列數據進行數據分析,賦值給二維矩陣X,對應可視化圖形的X軸和Y軸,這里調用dict將兩列數據綁定,再將dict類型轉換位list。
#獲取任意列數據 print('第一列 第五列數據') L2 = [n[0] for n in data] #第一列表示球員每分鐘助攻數:assists_per_minute L5 = [n[4] for n in data] #第五列表示球員每分鐘得分數:points_per_minute T = dict(zip(L2,L5)) #兩列數據生成二維數據 type(T)#下述代碼將dict類型轉換為list X = list(map(lambda x,y: (x,y), T.keys(),T.values())) print(type(X)) print(X)輸出結果如下圖所示:
接下來就是調用KMeans(n_clusters=3)函數聚類,聚集的類簇數為3。輸出聚類預測結果,共96行數據,每個y_pred對應X一行數據或一個球員,聚成3類,其類標為0、1、2。其中,clf.fit_predict(X) 表示載入數據集X訓練預測,并且將聚類的結果賦值給y_pred。
from sklearn.cluster import KMeans clf = KMeans(n_clusters=3) y_pred = clf.fit_predict(X) print(clf) print(y_pred)最后是可視化分析代碼,并生成三堆指定的圖形和顏色散點圖。
完整代碼如下:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03#------------------------------------------------------------------------ #第一步 讀取數據 import osdata = [] for line in open("data.txt", "r").readlines(): line = line.rstrip() result = ' '.join(line.split())#將字符串轉換為小數 s = [float(x) for x in result.strip().split(' ')] print(s) data.append(s) print(data) print(type(data))#------------------------------------------------------------------------ #第二步 獲取兩列數據 print('第一列 第五列數據') L2 = [n[0] for n in data] #第一列表示球員每分鐘助攻數:assists_per_minute L5 = [n[4] for n in data] #第五列表示球員每分鐘得分數:points_per_minute T = dict(zip(L2,L5)) #兩列數據生成二維數據 type(T) print(L2)#下述代碼將dict類型轉換為list X = list(map(lambda x,y: (x,y), T.keys(),T.values())) print(type(X)) print(X)#------------------------------------------------------------------------ #第三步 聚類分析 from sklearn.cluster import KMeans clf = KMeans(n_clusters=3) y_pred = clf.fit_predict(X) print(clf) print(y_pred)#------------------------------------------------------------------------ #第四步 繪制圖形 import numpy as np import matplotlib.pyplot as plt #獲取第一列和第二列數據,使用for循環獲取,n[0]表示X第一列 x = [n[0] for n in X] y = [n[1] for n in X]#坐標 x1, y1 = [], [] x2, y2 = [], [] x3, y3 = [], [] #分布獲取類標為0、1、2的數據并賦值給(x1,y1) (x2,y2) (x3,y3) i = 0 while i < len(X): if y_pred[i]==0: x1.append(X[i][0]) y1.append(X[i][1]) elif y_pred[i]==1: x2.append(X[i][0])y2.append(X[i][1]) elif y_pred[i]==2: x3.append(X[i][0]) y3.append(X[i][1]) i = i + 1 #三種顏色 紅 綠 藍,marker='x'表示類型,o表示圓點、*表示星型、x表示點 plot1, = plt.plot(x1, y1, 'or', marker="x") plot2, = plt.plot(x2, y2, 'og', marker="o") plot3, = plt.plot(x3, y3, 'ob', marker="*") plt.title("Kmeans-Basketball Data") #繪制標題 plt.xlabel("assists_per_minute") #繪制x軸 plt.ylabel("points_per_minute") #繪制y軸 plt.legend((plot1, plot2, plot3), ('A', 'B', 'C'), fontsize=10) #設置右上角圖例 plt.show()輸出結果如下圖所示:
6.設置類簇中心
KMeans聚類時,尋找類簇中心或質心的過程尤為重要,那么聚類后的質心是否可以顯示出來呢?答案是可以的,下面這段代碼就是顯示前面對籃球運動員聚類分析的類簇中心并繪制相關圖形。完整代碼如下。
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03#------------------------------------------------------------------------ #第一步 讀取數據 import osdata = [] for line in open("data.txt", "r").readlines(): line = line.rstrip() result = ' '.join(line.split())#將字符串轉換為小數 s = [float(x) for x in result.strip().split(' ')] print(s) data.append(s) print(data) print(type(data))#------------------------------------------------------------------------ #第二步 獲取兩列數據 print('第一列 第五列數據') L2 = [n[0] for n in data] #第一列表示球員每分鐘助攻數:assists_per_minute L5 = [n[4] for n in data] #第五列表示球員每分鐘得分數:points_per_minute T = dict(zip(L2,L5)) #兩列數據生成二維數據 type(T) print(L2)#下述代碼將dict類型轉換為list X = list(map(lambda x,y: (x,y), T.keys(),T.values())) print(type(X)) print(X)#------------------------------------------------------------------------ #第三步 聚類分析 from sklearn.cluster import KMeans clf = KMeans(n_clusters=3) y_pred = clf.fit_predict(X) print(clf) print(y_pred)#------------------------------------------------------------------------ #第四步 繪制圖形 import numpy as np import matplotlib.pyplot as plt #獲取第一列和第二列數據,使用for循環獲取,n[0]表示X第一列 x = [n[0] for n in X] y = [n[1] for n in X]#坐標 x1, y1 = [], [] x2, y2 = [], [] x3, y3 = [], [] #分布獲取類標為0、1、2的數據并賦值給(x1,y1) (x2,y2) (x3,y3) i = 0 while i < len(X): if y_pred[i]==0: x1.append(X[i][0]) y1.append(X[i][1]) elif y_pred[i]==1: x2.append(X[i][0])y2.append(X[i][1]) elif y_pred[i]==2: x3.append(X[i][0]) y3.append(X[i][1]) i = i + 1 #三種顏色 紅 綠 藍,marker='x'表示類型,o表示圓點、*表示星型、x表示點 plot1, = plt.plot(x1, y1, 'or', marker="x") plot2, = plt.plot(x2, y2, 'og', marker="o") plot3, = plt.plot(x3, y3, 'ob', marker="*") plt.title("Kmeans-Basketball Data") #繪制標題 plt.xlabel("assists_per_minute") #繪制x軸 plt.ylabel("points_per_minute") #繪制y軸 plt.legend((plot1, plot2, plot3), ('A', 'B', 'C'), fontsize=10) #設置右上角圖例 #------------------------------------------------------------------------ #第五步 設置類簇中心 centers = clf.cluster_centers_ print(centers) plt.plot(centers[:,0],centers[:,1],'r*',markersize=20) #顯示三個中心點 plt.show()輸出如下圖所示,可以看到三個紅色的五角星為類簇中心。
其中類簇中心的坐標為:
[[ 0.1741069 0.29691724][ 0.13618696 0.56265652][ 0.16596136 0.42713636]]三.Birch
Birch聚類算法稱為平衡迭代歸約及聚類算法,它是一種常用的層次聚類算法。該算法通過聚類特征(Clustering Feature,CF)和聚類特征樹(Clustering Feature Tree,CFT)兩個概念描述聚類。聚類特征樹用來概括聚類的有用信息,由于其占用空間小并且可以存放在內存中,從而提高了算法的聚類速度,產生了較高的聚類質量,并適用于大型數據集。層次聚類算法是講數據樣本組成一顆聚類樹,根據層次分解是以自頂向下(分裂)還是自底向上(合并)方式進一步合并或分裂。
1.算法描述
Birch聚類算法的聚類特征(CF)通過三元組結構描述了聚類類簇的基本信息,其中三元組結構公式如下:
其中,N表示聚類數據點的個數,每個點用一個d維向量表示;表示N個聚類數據點的線性和;SS表示N個聚類數據點的平方和。聚類特征通過線性和表示聚類的質心,通過平方和表示聚類的直徑大小。
Birch算法主要包括以下三個階段:
- 設定初始閾值z并掃描整個數據集D,再根據該閾值建立一棵聚類特征樹T。
- 通過提升閾值z重建該聚類特征樹T,從而得到一棵壓縮的CF樹。
- 利用全局性聚類算法對CF樹進行聚類,改進聚類質量以得到更好的聚類結果。
Birch聚類算法具有處理的數據規模大、算法效率高、更容易計算類簇的直徑和類簇之間的距離等優點。
在Sklearn機器學習包中,調用cluster聚類子庫的Birch()函數即可進行Birch聚類運算,該算法要求輸入聚類類簇數。Birch類構造方法如下:
sklearn.cluster.Birch(branching_factor=50, compute_labels=True, copy=True, n_clusters=3, threshold=0.5)其中,最重要的參數n_clusters=3表示該聚類類簇數為3,即聚集成3堆。下面舉個簡單的實例,使用前面的例子中的6個點進行,設置聚類類簇數為2(n_clusters=2),調用Birch()函數聚類,通過clf.fit()裝載數據訓練模型。代碼如下:
from sklearn.cluster import Birch X = [[1,1],[2,1],[1,3],[6,6],[8,5],[7,8]] y = [0,0,0,1,1,1] clf = Birch(n_clusters=2) clf.fit(X,y) print(clf.labels_)輸出結果如下:
>>> [0 0 0 1 1 1] >>>clf.labels_表示輸出聚類后的類標。由于聚類類簇設置為2,故類標為0或1,其中X[1,1]、X[2,1]、X[1,3]聚類后屬于0類,X[6,6]、X[8,5]、X[7,8]聚類后屬于1類。
2.Birch分析氧化物數據
(1) 數據集
數據來源為UCI的玻璃數據集(Glass Identification Database)。該數據集包括7種類型的玻璃,各個特征是定義它們的氧化物含量(即鈉,鐵,鉀等)。數據集中化學符號包括:Na-鈉、Mg-鎂、Al-鋁、Si-硅、K-鉀、Ca-鈣、Ba-鋇、Fe-鐵。數據集為glass.csv文件,前10行數據(包括列名第一行)如下圖14所示。
數據集共包含9個特征變量,分別為ri、na、mg、al、si、k、ca、ba、fe,1個類別變量glass_type,共有214個樣本。其中類別變量glass_type包括7個值,分別是:1 表示浮動處理的窗口類型、2表示非浮動處理的窗口類型、3表示浮動處理的加工窗口類型、4表示非浮動處理的加工窗口類型(該類型在該數據集中不存在)、5表示集裝箱類型、6表示餐具類型、7表示頭燈類型。
數據集地址:
- http://archive.ics.uci.edu/ml/machine-learning-databases/glass/
(2) 算法實現
首先調用Pandas庫讀取glass.csv文件中的數據,并繪制簡單的散點圖,代碼如下:
首先調用Pandas的read_csv()函數讀取文件,然后調用Matplotlib.pyplot包中的scatter()函數繪制散點圖。scatter(glass.al, glass.ri, c=glass.glass_type)中鋁元素作為x軸,折射率作為y軸進行散點圖繪制,不同類別glass_type繪制為不同顏色的點(共7個類別)。輸出如圖15所示,可以看到各種顏色的點。
下面是調用Birch()函數進行聚類處理,主要步驟包括:
- 調用Pandas擴展包的read_csv導入玻璃數據集,注意獲取兩列數據,需要轉換為二維數組X。
- 從sklearn.cluster包中導入Birch()聚類函數,并設置聚類類簇數。
- 調用clf.fit(X, y)函數訓練模型。
- 用訓練得到的模型進行預測分析,調用predict()函數預測數據集。
- 分別獲取三類數據集對應類的點。
- 調用plot()函數繪制散點圖,不同類別的數據集設置為不同樣式。
完整代碼如下:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import pandas as pd import matplotlib.pyplot as plt from sklearn.cluster import Birch#數據獲取 glass=pd.read_csv("glass.csv") X1 = glass.al X2 = glass.ri T = dict(zip(X1,X2)) #生成二維數組 X = list(map(lambda x,y: (x,y), T.keys(),T.values())) #dict類型轉換為list y = glass.glass_type#聚類 clf = Birch(n_clusters=3) clf.fit(X, y) y_pred = clf.predict(X) print(y_pred)#分別獲取不同類別數據點 x1, y1 = [], [] x2, y2 = [], [] x3, y3 = [], [] i = 0 while i < len(X): if y_pred[i]==0: x1.append(X[i][0]) y1.append(X[i][1]) elif y_pred[i]==1: x2.append(X[i][0]) y2.append(X[i][1]) elif y_pred[i]==2: x3.append(X[i][0]) y3.append(X[i][1]) i = i + 1 #三種顏色 紅 綠 藍,marker='x'表示類型,o表示圓點 *表示星型 x表示點 plot1, = plt.plot(x1, y1, 'or', marker="x") plot2, = plt.plot(x2, y2, 'og', marker="o") plot3, = plt.plot(x3, y3, 'ob', marker="*") plt.xlabel('al') plt.ylabel('ri') plt.show()輸出如下圖所示:
從圖中可以看到,右下角紅色x形點聚集在一起,其al含量較高、ri含量較低;中間綠色o點聚集在一起,其al、ri含量均勻;右部藍色*星形點聚集在一起,其al含量較低、ri含量較高。該Birch算法很好的將數據集劃分為三部分。
但不知道讀者有沒有注意到,在代碼中獲取了兩列數據進行聚類,而數據集中包含多個特征,如ri、na、mg、al、si、k、ca、ba、fe等,真正的聚類分析中,是可以對多個特征進行分析的,這就涉及到了降維技術。
四.結合降維處理的聚類分析
任何回歸、聚類和分類算法的復雜度都依賴于輸入的數量,為了減少存儲量和計算時間,我們需要降低問題的維度,丟棄不相關的特征。同時,當數據可以用較少的維度表示而不丟失信息時,我們可以對數據繪圖,可視化分析它的結構和離群點,數據降維由此產生。
數據降維(Dimensionality Reduction)是指采用一個低緯度的特征來表示高緯度特征,其本質是構造一個映射函數f:X->Y,其中X是原始數據點,用n維向量表示;Y是數據點映射后的r維向量,并且n>r。通過這種映射方法,可以將高維空間中的數據點降低。
特征降維一般有兩類方法:特征選擇(Feature Selection)和特征提取(Feature Extraction)。
-
特征選擇
特征選擇是指從高緯度特征中選擇其中的一個子集來作為新的特征。最佳子集表示以最少的維貢獻最大的正確率,丟棄不重要的維,使用合適的誤差函數產生,特征選擇的方法包括在向前選擇(Forword Selection)和在向后選擇(Backward Selection)。 -
特征提取
特征提取是指將高緯度的特征經過某個函數映射至低緯度作為新的特征。常用的特征抽取方法包括PCA(主成分分析)和LDA(線性判別分析)。圖17表示采用PCA方法將三維圖形尾花數據降維成兩維2D圖形。
1.PCA降維
主成分分析(Principal Component Analysis,簡稱PCA)是一種常用的線性降維數據分析方法,它是在能盡可能保留具有代表性的原特征數據點的情況下,將原特征進行線性變換,從而映射至低緯度空間中。
PCA降維方法通過正交變換將一組可能存在相關性的變量轉換為一組線性不相關的變量,轉換后的這組變量叫做主成分,它可以用于提取數據中的主要特征分量,常用于高維數據的降維。該方法的重點在于:能否在各個變量之間相關關系的基礎上,用較少的新變量代替原來較多的變量,并且這些較少的新變量盡可能多地反映原來較多的變量所提供信息,又能保證新指標之間信息不重疊。
圖18是將二維樣本的散點圖(紅色三角形點)降低成一維直線(黃色圓點)表示。最理想的情況是這個一維新向量所包含的原始數據信息最多,即降維后的直線能盡可能多覆蓋二維圖形中的點,或者所有點到這條直線的距離和最短,這類似于橢圓長軸,該方向上的離散程度最大、方差最大,所包含的信息最多;而橢圓短軸方向上的數據變化很少,對數據的解釋能力較弱。
由于作者數學能力有限,該方法的推算過程及原理推薦讀者下來自行研究學習,也請讀者海涵。
2.Sklearn PCA降維
下面介紹Sklearn機器學習包中PCA降維方法的應用。
- 導入擴展包
from sklearn.decomposition import PCA - 調用降維函數
pca = PCA(n_components=2)
其中參數n_components=2表示降低為2維,下述代碼是調用PCA降維方法進行降維操作,將一條直線(二維矩陣)X變量降低為一個點并輸出。
輸出如下所示,包括PCA算法原型及降維成2維的結果。
其結果表示通過PCA降維方法將六個點或一條直線降低成為一個點,并盡可能表征這六個點的特征。輸出點為:[0.99244289 0.00755711]。
- 降維操作
pca = PCA(n_components=2)
newData = pca.fit_transform(x)
調用PCA()函數降維,降低成2維數組,并將降維后的數據集賦值給newData變量。下面舉一個例子,載入波士頓(Boston)房價數據集,將數據集中的13個特征降低為2個特征。核心代碼如下所示:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 #載入數據集 from sklearn.datasets import load_boston d = load_boston() x = d.data y = d.target print(x[:2]) print('形狀:', x.shape)#降維 import numpy as np from sklearn.decomposition import PCA pca = PCA(n_components=2) newData = pca.fit_transform(x) print('降維后數據:') print(newData[:4]) print('形狀:', newData.shape)其中,波士頓房價數據集共506行,13個特征,經過PCA算法降維后,降低為兩個特征,并調用newData[:4]輸出前4行數據,輸出結果如下所示。
[[ 6.32000000e-03 1.80000000e+01 2.31000000e+00 0.00000000e+00 5.38000000e-01 6.57500000e+00 6.52000000e+01 4.09000000e+00 1.00000000e+00 2.96000000e+02 1.53000000e+01 3.96900000e+02 4.98000000e+00] [ 2.73100000e-02 0.00000000e+00 7.07000000e+00 0.00000000e+00 4.69000000e-01 6.42100000e+00 7.89000000e+01 4.96710000e+00 2.00000000e+00 2.42000000e+02 1.78000000e+01 3.96900000e+02 9.14000000e+00]] 形狀: (506L, 13L) 降維后數據: [[-119.81821283 5.56072403] [-168.88993091 -10.11419701] [-169.31150637 -14.07855395] [-190.2305986 -18.29993274]] 形狀: (506L, 2L)3.PCA降維實例
前面講述的Birch聚類算法分析氧化物的數據只抽取了數據集的第一列和第二列數據,接下來講述對整個數據集的所有特征進行聚類的代碼,調用PCA將數據集降低為兩維數據,再進行可視化操作,完整代碼如下。
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 #第一步 數據獲取 import pandas as pd glass = pd.read_csv("glass.csv") print(glass[:4])#第二步 聚類 from sklearn.cluster import Birch clf = Birch(n_clusters=3) clf.fit(glass) pre = clf.predict(glass) print(pre)#第三步 降維 from sklearn.decomposition import PCA pca = PCA(n_components=2) newData = pca.fit_transform(glass) print(newData[:4]) x1 = [n[0] for n in newData] x2 = [n[1] for n in newData]#第四步 繪圖 import matplotlib.pyplot as plt plt.xlabel("x feature") plt.ylabel("y feature") plt.scatter(x1, x2, c=pre, marker='x') plt.show()輸出如圖19所示。核心代碼前面已經詳細敘述了,其中[n[0] for n in newData]代碼表示獲取降維后的第一列數據,[n[1] for n in newData]獲取降維后的第二列數據,并分別賦值給x1和x2變量,為最后的繪圖做準備。
同時,上述代碼輸出的前4行數據集結果如下:
最后簡單講述設置不同類簇數的聚類對比代碼,完整代碼如下:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import pandas as pd import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.cluster import Birch#獲取數據集及降維 glass = pd.read_csv("glass.csv") pca = PCA(n_components=2) newData = pca.fit_transform(glass) print(newData[:4]) L1 = [n[0] for n in newData] L2 = [n[1] for n in newData] plt.rc('font', family='SimHei', size=8) #設置字體 plt.rcParams['axes.unicode_minus'] = False #負號#聚類 類簇數=2 clf = Birch(n_clusters=2) clf.fit(glass) pre = clf.predict(glass) p1 = plt.subplot(221) plt.title(u"Birch聚類 n=2") plt.scatter(L1,L2,c=pre,marker="s") plt.sca(p1) #聚類 類簇數=3 clf = Birch(n_clusters=3) clf.fit(glass) pre = clf.predict(glass) p2 = plt.subplot(222) plt.title(u"Birch聚類 n=3") plt.scatter(L1,L2,c=pre,marker="o") plt.sca(p2) #聚類 類簇數=4 clf = Birch(n_clusters=4) clf.fit(glass) pre = clf.predict(glass) p3 = plt.subplot(223) plt.title(u"Birch聚類 n=4") plt.scatter(L1,L2,c=pre,marker="o") plt.sca(p3) #聚類 類簇數=5 clf = Birch(n_clusters=5) clf.fit(glass) pre = clf.predict(glass) p4 = plt.subplot(224) plt.title(u"Birch聚類 n=5") plt.scatter(L1,L2,c=pre,marker="s") plt.sca(p4) plt.savefig('18.20.png', dpi=300) plt.show()輸出如圖20所示,可以分別看到類簇數為2、3、4、5的聚類對比情況。需要注意的是不同類簇數據點的顏色是不同的,建議讀者下來自己去實現該部分代碼,從實際數據分析中體會。
五.基于均值漂移的圖像聚類
前面我看到是針對TXT和CSV文件中的數據,接著我們來看看聚類算法如何應用到圖像分割領域。
1.MeanShift圖像聚類
均值漂移(Mean Shfit)算法是一種通用的聚類算法,最早是1975年Fukunaga等人在一篇關于概率密度梯度函數的估計論文中提出。它是一種無參估計算法,沿著概率梯度的上升方向尋找分布的峰值。Mean Shift算法先算出當前點的偏移均值,移動該點到其偏移均值,然后以此為新的起始點,繼續移動,直到滿足一定的條件結束。
圖像分割中可以利用均值漂移算法的特性,實現彩色圖像分割。在OpenCV中提供的函數為pyrMeanShiftFiltering(),該函數嚴格來說并不是圖像分割,而是圖像在色彩層面的平滑濾波,它可以中和色彩分布相近的顏色,平滑色彩細節,侵蝕掉面積較小的顏色區域,所以在OpenCV中它的后綴是濾波“Filter”,而不是分割“segment”。該函數原型如下所示:
- dst = pyrMeanShiftFiltering(src, sp, sr[, dst[, maxLevel[, termcrit]]])
– src表示輸入圖像,8位三通道的彩色圖像
– dst表示輸出圖像,需同輸入圖像具有相同的大小和類型
– sp表示定義漂移物理空間半徑的大小
– sr表示定義漂移色彩空間半徑的大小
– maxLevel表示定義金字塔的最大層數
– termcrit表示定義的漂移迭代終止條件,可以設置為迭代次數滿足終止,迭代目標與中心點偏差滿足終止,或者兩者的結合
均值漂移pyrMeanShiftFiltering()函數的執行過程是如下:
-
(1) 構建迭代空間。
以輸入圖像上任一點P0為圓心,建立以sp為物理空間半徑,sr為色彩空間半徑的球形空間,物理空間上坐標為x和y,色彩空間上坐標為RGB或HSV,構成一個空間球體。其中x和y表示圖像的長和寬,色彩空間R、G、B在0至255之間。 -
(2) 求迭代空間的向量并移動迭代空間球體重新計算向量,直至收斂。
在上一步構建的球形空間中,求出所有點相對于中心點的色彩向量之和,移動迭代空間的中心點到該向量的終點,并再次計算該球形空間中所有點的向量之和,如此迭代,直到在最后一個空間球體中所求得向量和的終點就是該空間球體的中心點Pn,迭代結束。 -
(3) 更新輸出圖像dst上對應的初始原點P0的色彩值為本輪迭代的終點Pn的色彩值,完成一個點的色彩均值漂移。
-
(4) 對輸入圖像src上其他點,依次執行上述三個步驟,直至遍歷完所有點后,整個均值偏移色彩濾波完成。
下面的代碼是圖像均值漂移的實現過程:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import cv2 import numpy as np import matplotlib.pyplot as plt#讀取原始圖像灰度顏色 img = cv2.imread('scenery.png') spatialRad = 100 #空間窗口大小 colorRad = 100 #色彩窗口大小 maxPyrLevel = 2 #金字塔層數#圖像均值漂移分割 dst = cv2.pyrMeanShiftFiltering( img, spatialRad, colorRad, maxPyrLevel)#顯示圖像 cv2.imshow('src', img) cv2.imshow('dst', dst) cv2.waitKey() cv2.destroyAllWindows()當漂移物理空間半徑設置為50,漂移色彩空間半徑設置為50,金字塔層數 為2,輸出的效果圖如圖21所示。
當漂移物理空間半徑設置為20,漂移色彩空間半徑設置為20,金字塔層數為2,輸出的效果圖如圖22所示。對比可以發現,半徑為20時,圖像色彩細節大部分存在,半徑為50時,森林和水面的色彩細節基本都已經丟失。
寫到這里,均值偏移算法對彩色圖像的分割平滑操作就完成了,為了達到更好地分割目的,借助漫水填充函數進行下一步處理。完整代碼如下所示:
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import cv2 import numpy as np import matplotlib.pyplot as plt#讀取原始圖像灰度顏色 img = cv2.imread('scenery.png') #獲取圖像行和列 rows, cols = img.shape[:2]#mask必須行和列都加2且必須為uint8單通道陣列 mask = np.zeros([rows+2, cols+2], np.uint8) spatialRad = 100 #空間窗口大小 colorRad = 100 #色彩窗口大小 maxPyrLevel = 2 #金字塔層數#圖像均值漂移分割 dst = cv2.pyrMeanShiftFiltering( img, spatialRad, colorRad, maxPyrLevel)#圖像漫水填充處理 cv2.floodFill(dst, mask, (30, 30), (0, 255, 255),(100, 100, 100), (50, 50, 50),cv2.FLOODFILL_FIXED_RANGE)#顯示圖像 cv2.imshow('src', img) cv2.imshow('dst', dst) cv2.waitKey() cv2.destroyAllWindows()輸出的效果圖如圖23所示,它將天空染成黃色。
2.K-Means圖像聚類
同樣,K-Means算法也能實現圖像分割。在圖像處理中,通過K-Means聚類算法可以實現圖像分割、圖像聚類、圖像識別等操作,本小節主要用來進行圖像顏色分割。假設存在一張100×100像素的灰度圖像,它由10000個RGB灰度級組成,我們通過K-Means可以將這些像素點聚類成K個簇,然后使用每個簇內的質心點來替換簇內所有的像素點,這樣就能實現在不改變分辨率的情況下量化壓縮圖像顏色,實現圖像顏色層級分割。
在OpenCV中,Kmeans()函數原型如下所示:
- retval, bestLabels, centers = kmeans(data, K, bestLabels, criteria, attempts, flags[, centers])
– data表示聚類數據,最好是np.flloat32類型的N維點集
– K表示聚類類簇數
– bestLabels表示輸出的整數數組,用于存儲每個樣本的聚類標簽索引
– criteria表示算法終止條件,即最大迭代次數或所需精度。在某些迭代中,一旦每個簇中心的移動小于criteria.epsilon,算法就會停止
– attempts表示重復試驗kmeans算法的次數,算法返回產生最佳緊湊性的標簽
– flags表示初始中心的選擇,兩種方法是cv2.KMEANS_PP_CENTERS ;和cv2.KMEANS_RANDOM_CENTERS
– centers表示集群中心的輸出矩陣,每個集群中心為一行數據
下面使用該方法對灰度圖像顏色進行分割處理,需要注意,在進行K-Means聚類操作之前,需要將RGB像素點轉換為一維的數組,再將各形式的顏色聚集在一起,形成最終的顏色分割。
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import cv2 import numpy as np import matplotlib.pyplot as plt#讀取原始圖像灰度顏色 img = cv2.imread('scenery.png', 0) print(img.shape)#獲取圖像高度、寬度和深度 rows, cols = img.shape[:]#圖像二維像素轉換為一維 data = img.reshape((rows * cols, 1)) data = np.float32(data)#定義中心 (type,max_iter,epsilon) criteria = (cv2.TERM_CRITERIA_EPS +cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)#設置標簽 flags = cv2.KMEANS_RANDOM_CENTERS#K-Means聚類 聚集成4類 compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags)#生成最終圖像 dst = labels.reshape((img.shape[0], img.shape[1]))#用來正常顯示中文標簽 plt.rcParams['font.sans-serif']=['SimHei']#顯示圖像 titles = [u'原始圖像', u'聚類圖像'] images = [img, dst] for i in range(2): plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()輸出結果如圖24所示,左邊為灰度圖像,右邊為K-Means聚類后的圖像,它將灰度級聚集成四個層級,相似的顏色或區域聚集在一起。
下面代碼是對彩色圖像進行顏色分割處理,它將彩色圖像聚集成2類、4類和64類。
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import cv2 import numpy as np import matplotlib.pyplot as plt#讀取原始圖像 img = cv2.imread('scenery.png') print(img.shape)#圖像二維像素轉換為一維 data = img.reshape((-1,3)) data = np.float32(data)#定義中心 (type,max_iter,epsilon) criteria = (cv2.TERM_CRITERIA_EPS +cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)#設置標簽 flags = cv2.KMEANS_RANDOM_CENTERS#K-Means聚類 聚集成2類 compactness, labels2, centers2 = cv2.kmeans(data, 2, None, criteria, 10, flags)#K-Means聚類 聚集成4類 compactness, labels4, centers4 = cv2.kmeans(data, 4, None, criteria, 10, flags)#K-Means聚類 聚集成8類 compactness, labels8, centers8 = cv2.kmeans(data, 8, None, criteria, 10, flags)#K-Means聚類 聚集成16類 compactness, labels16, centers16 = cv2.kmeans(data, 16, None, criteria, 10, flags)#K-Means聚類 聚集成64類 compactness, labels64, centers64 = cv2.kmeans(data, 64, None, criteria, 10, flags)#圖像轉換回uint8二維類型 centers2 = np.uint8(centers2) res = centers2[labels2.flatten()] dst2 = res.reshape((img.shape))centers4 = np.uint8(centers4) res = centers4[labels4.flatten()] dst4 = res.reshape((img.shape))centers8 = np.uint8(centers8) res = centers8[labels8.flatten()] dst8 = res.reshape((img.shape))centers16 = np.uint8(centers16) res = centers16[labels16.flatten()] dst16 = res.reshape((img.shape))centers64 = np.uint8(centers64) res = centers64[labels64.flatten()] dst64 = res.reshape((img.shape))#圖像轉換為RGB顯示 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) dst2 = cv2.cvtColor(dst2, cv2.COLOR_BGR2RGB) dst4 = cv2.cvtColor(dst4, cv2.COLOR_BGR2RGB) dst8 = cv2.cvtColor(dst8, cv2.COLOR_BGR2RGB) dst16 = cv2.cvtColor(dst16, cv2.COLOR_BGR2RGB) dst64 = cv2.cvtColor(dst64, cv2.COLOR_BGR2RGB)#用來正常顯示中文標簽 plt.rcParams['font.sans-serif']=['SimHei']#顯示圖像 titles = [u'原始圖像', u'聚類圖像 K=2', u'聚類圖像 K=4',u'聚類圖像 K=8', u'聚類圖像 K=16', u'聚類圖像 K=64'] images = [img, dst2, dst4, dst8, dst16, dst64] for i in range(6): plt.subplot(2,3,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()輸出結果如圖10所示,它對比了原始圖像和各K-Means聚類處理后的圖像。當K=2時,聚集成2種顏色;當K=4時,聚集成4種顏色;當K=8時,聚集成8種顏色;當K=16時,聚集成16種顏色;當K=64時,聚集成64種顏色。
更多圖像處理知識推薦作者的專欄:
- https://blog.csdn.net/eastmount/category_9278090.html
六.基于文本的樹狀關鍵詞聚類
最后我們簡單補充文本聚類相關知識,這里以樹狀圖為例,后面的文本挖掘系列也會進行詳細介紹。層次聚類繪制的樹狀圖,也是文本挖掘領域常用的技術,它會將各個領域相關的主題以樹狀的形式進行顯示。數據集為作者在CSDN近十年分享的所有博客標題,如下圖所示。
最終輸出結果如下圖所示,可以看到這個內容分為不同的主題,包括網絡安全、人工智能、圖像處理、算法等。
注意,這里作者可以通過設置過濾來顯示樹狀圖顯示的主題詞數量,并進行相關的對比實驗,找到最優結果。
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2021-07-03 import os import codecs from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer from sklearn.manifold import TSNE from sklearn.cluster import KMeans import matplotlib.pyplot as plt import numpy as np import pandas as pd import jieba from sklearn import metrics from sklearn.metrics import silhouette_score from array import array from numpy import * from pylab import mpl from sklearn.metrics.pairwise import cosine_similarity import matplotlib.pyplot as plt import matplotlib as mpl from scipy.cluster.hierarchy import ward, dendrogram#---------------------------------------加載語料------------------------------------- text = open('data-fenci.txt').read() print(text) list1=text.split("\n") print(list1) print(list1[0]) print(list1[1]) mytext_list=list1#控制顯示數量 count_vec = CountVectorizer(min_df=20, max_df=1000) #最大值忽略 xx1 = count_vec.fit_transform(list1).toarray() word=count_vec.get_feature_names() print("word feature length: {}".format(len(word))) print(word) print(xx1) print(type(xx1)) print(xx1.shape) print(xx1[0])#---------------------------------------層次聚類------------------------------------- titles = word #dist = cosine_similarity(xx1)mpl.rcParams['font.sans-serif'] = ['SimHei']df = pd.DataFrame(xx1) print(df.corr()) print(df.corr('spearman')) print(df.corr('kendall')) dist = df.corr() print (dist) print(type(dist)) print(dist.shape)#define the linkage_matrix using ward clustering pre-computed distances linkage_matrix = ward(dist) fig, ax = plt.subplots(figsize=(8, 12)) # set size ax = dendrogram(linkage_matrix, orientation="right",p=20, labels=titles, leaf_font_size=12) #leaf_rotation=90., leaf_font_size=12. #show plot with tight layout plt.tight_layout() #save figure as ward_clusters plt.savefig('KH.png', dpi=200) plt.show()七.總結
寫到這里,這篇文章就結束了,您是否對聚類有更好的認識呢?
聚類是把一堆數據歸為若干類,同一類數據具有某些相似性,并且這些類別是通過數據自發的聚集出來的,而不是事先給定的,也不需要標記結果,機器學習里面稱之為無監督學習,常見的聚類方法包括KMeans、Birch、譜聚類、圖聚類等。聚類被廣泛應用于不同場景中,社交網絡通過聚類來發現人群,關注人群的喜好;網頁通過聚類來查找相似文本內容;圖像通過聚類來進行分割和檢索相似圖片;電商通過用戶聚類來分析購物的人群、商品推薦以及計算購物最佳時間等。
- 一.聚類
1.算法模型
2.常見聚類算法
3.性能評估 - 二.K-Means
1.算法描述
2.K-Means聚類示例
3.Sklearn中K-Means用法介紹
4.K-Means分析籃球數據
5.K-Means聚類優化
6.設置類簇中心 - 三.Birch
1.算法描述
2.Birch分析氧化物數據 - 四.結合降維處理的聚類分析
1.PCA降維
2.Sklearn PCA降維
3.PCA降維實例 - 五.基于均值漂移的圖像聚類
1.MeanShift圖像聚類
2.K-Means圖像聚類 - 六.基于文本的樹狀關鍵詞聚類
- 七.總結
最后希望讀者能復現每一行代碼,只有實踐才能進步。同時更多聚類算法和原理知識,希望讀者下來自行深入學習研究,也推薦大家結合Sklearn官網和開源網站學習更多的機器學習知識。
該系列所有代碼下載地址:
- https://github.com/eastmountyxz/Python-zero2one
感謝在求學路上的同行者,不負遇見,勿忘初心。這周的留言感慨~
(By:娜璋之家 Eastmount 2021-07-06 夜于武漢 https://blog.csdn.net/Eastmount )
參考文獻:
- [1] 楊秀璋. 專欄:知識圖譜、web數據挖掘及NLP - CSDN博客[EB/OL]. (2016-09-19)[2017-11-07]. http://blog.csdn.net/column/details/eastmount-kgdmnlp.html.
- [2] 張良均,王路,譚立云,蘇劍林. Python數據分析與挖掘實戰[M]. 北京:機械工業出版社,2016.
- [3] (美)Wes McKinney著. 唐學韜等譯. 利用Python進行數據分析[M]. 北京:機械工業出版社,2013.
- [4] Jiawei Han,Micheline Kamber著. 范明,孟小峰譯. 數據挖掘概念與技術. 北京:機械工業出版社,2007.
- [5] 楊秀璋. [Python數據挖掘課程] 二.Kmeans聚類數據分析及Anaconda介紹[EB/OL]. (2016-10-10)[2017-11-17]. http://blog.csdn.net/eastmount/article/details/52777308.
- [6] 楊秀璋. [Python數據挖掘課程] 三.Kmeans聚類代碼實現、作業及優化[EB/OL]. (2016-10-12)[2017-11-17]. http://blog.csdn.net/eastmount/article/details/52793549.
- [7] 楊秀璋. [Python數據挖掘課程] 七.PCA降維操作及subplot子圖繪制[EB/OL]. (2016-11-26)[2017-11-17]. http://blog.csdn.net/eastmount/article/details/53285192
- [8] scikit-learn官網. scikit-learn clusterin [EB/OL]. (2017)[2017-11-17]. http://scikit-learn.org/stable/modules/clustering.html#clustering.
- [9] KEEL數據集. KEEL-dateset Basketball dataset[EB/OL]. (2017)[2017-11-17]. http://sci2s.ugr.es/keel/dataset.php?cod=1293.
- [10] UCI官網. 玻璃數據集(Glass Identification Database)[EB\OL]. (2017)[2017-11-17]. http://archive.ics.uci.edu/ml/machine-learning-databases/glass/.
總結
以上是生活随笔為你收集整理的[Python从零到壹] 十三.机器学习之聚类算法四万字总结全网首发(K-Means、BIRCH、树状聚类、MeanShift)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Python从零到壹] 十二.机器学习
- 下一篇: [Python从零到壹] 十四.机器学习