1. 程式人生 > >聚類分析K均值演算法講解

聚類分析K均值演算法講解

聚類分析及K均值演算法講解

吳裕雄

當今資訊大爆炸時代,公司企業、教育科學、醫療衛生、社會民生等領域每天都在產生大量的結構多樣的資料。產生資料的方式更是多種多樣,如各類的:攝像頭、感測器、報表、海量網路通訊等等,面對這海量結構各式各樣的資料,如果單是依靠人力來完成,是件非常不現實的事,但這些資料又包含著許多對我們有很高價值的資訊。面對這樣的矛盾,我們必須通過一些方法來科學、高效地分析、處理這些資料,最後輸出能夠讓人或者機器作出無差別的行為判斷。聚類分析——就是解決這類問題的一種典型方法,它是基於生活常識,運用數學抽象模型及科學度量的一種海量資料分析、處理的方法。藉助這樣的聚類分析方法,形成了三大經典的演算法:K

均值、凝聚的層次聚類和DBSCAN。下面是具體的概念及K均值演算法的介紹。

在現實客觀自然界中,每一樣事物都有其屬性,世界上'' 沒有一片完全相同的葉子'',最根本的原因是:每一樣的事物本身的屬性不是跟其它任何事物的完全相同。但是我們分析和描述客觀自然事物的時候,往往是基於對某一事物重要的、突出的和具有普遍性的屬性來進行歸門別類。這就是:旨在理解的聚類。它體現的是一種由一般到特殊的科學邏輯思想方法。比如:竹葉、楓葉等樹葉具有'' 葉子''這個類的全部屬性,白貓、黑貓等不同品種的貓具有''''類的全部屬性。通過這樣的分類,我們可以把前兩者叫做:葉子,把後兩者叫做:貓。但並不是說它們之間完全沒有相同的屬性,比如:它們分化程度較低的細胞都可以進行有絲分裂,都有細胞的基本結構等等。只不過我們在日常生活中對於這些事物比較少提起、不明顯的屬性常常不拿來做分析和判斷。因為根本就沒有必要把每個事物的各個要素都

'' 錙銖必較'',除非是對某一事物進行必要的詳盡的調查和研究,否則全盤考慮每一事物的屬性是很不現實、很不科學的。從這一方面來說:概念上有意義的具有公共特性的物件組,扮演著十分重要的角色。這樣的物件組我們可以稱之為:簇。簇也是一種潛在的類,而聚類分析研究的就是:自動發現這些類的技術。聚類分析早期的大部分工作都是在尋求建立可以自動發現分類結構的數學分類方法。

比如:在生物學方面,生物學家使用聚類分析大量的遺傳資訊,以此來發現具有功能類似的基因組;在資訊檢索方面,網路搜尋引擎可能返回成百上千萬的頁面資訊,可以使用聚類將搜尋結果分成若干簇,每個簇捕獲查詢的某個特定方面,每個簇又可劃分為若干的子簇,從而產生一個層次結構來幫助使用者進一步查詢結果;在氣候方面,通過對大氣層和海洋的氣壓進行聚類分析,以此發現對陸地氣候有明顯影響的極地和海洋壓力模式;在心理學和醫學方面,通過聚類分析來識別不同型別的癌症特徵,也可以用來檢測疾病的時間和空間分佈模式;在商業方面,可以使用聚類將顧客劃分成若干組,以便進一步分析和開展營銷活動

......

與上面旨在理解的聚類相對應的一種聚類是:旨在實用的聚類。聚類分析提供由個別資料物件到資料物件所指派的簇的抽象。它體現的是一種由特殊到一般的科學邏輯思想方法。(可以很明顯看出:科學與哲學其實就是相互統一的一門簡單易懂的學科)此外,一些聚類技術實用簇原型(即代表簇中其他物件的資料物件)來刻畫簇特徵。比如:現在需要描述鳥類,通過什麼方法來將這麼多品種的鳥描述刻畫清楚,表述給人或者機器知道呢?通常都是通過描述刻畫鳥的一些普遍而又能夠與其它事物區別開來的屬性,來解決的。那我們如何獲取或者知道鳥這樣的屬性呢?一般是通過某些個別具有鳥本身代表性和普遍性的鳥來確定這樣的屬性的,那麼以後人或者機器就通過這些屬性來區別某一事物,它到底是不是鳥類。剛才得出來能夠普遍性地刻畫鳥類這樣的屬性的那些具體的鳥,也就是能夠代表一般的資料物件,就是簇原型。這些簇原型可以用作大量資料分析和資料處理技術的基礎。因此,就實用而言,聚類分析是研究發現最具有代表性的簇原型的技術。

比如:在彙總方面,許多資料分析技術,如迴歸和PCA,都具有O)或更高的時間或者空間複雜度(其中m是物件的個數)。因此,對於大型資料集,這些技術不切實際。然而,可以將演算法用於僅包含簇原型的資料集,而不是整個資料集。依賴分析型別、原型個數和原型代表資料的精度,彙總結果可以與使用所有資料得到的結果相媲美。在壓縮方面,可以使用簇原型來進行資料壓縮。例如,建立一個包含所有簇原型的表,即每個原型賦予一個整數值,作為它在表中的位置(索引)。每個物件用與它所在的簇相關聯的原型的索引來表示。這類壓縮稱作向量量化。常常用於影象、聲音和視訊這類資料,此類資料的特點是:(1)許多資料物件之間高度相似,(2)某些資訊的丟失是可以接受的,(3)希望能夠大幅度地壓縮資料。在有效地發現最近鄰方面,找出最近鄰可能需要計算所有點對點之間的距離。通常,可以更有效地發現簇和簇原型。如果物件相對地靠近簇的原型,則我們可以使用簇原型減少發現物件最鄰近所需要計算的距離的數目。直觀地說,如果兩個簇原型相距很遠,則對應簇中的物件也不可能互為鄰近。這樣,為了找出一個物件的最鄰近,只需要計算到鄰近簇中物件的距離,也就是說兩個簇的鄰近性用其原型之間的距離來進行度量。

基於大體上了解聚類能夠為我們解決什麼樣的問題之後,接下來來對其經典的三大演算法——K均值、凝聚的層次聚類和DBSCAN,本篇幅主要討論K均值演算法。

有許多技術是可以實現:基於原型的聚類技術建立資料物件的單層劃分。在這許多這樣的技術中,最突出的一個是K均值,一個是K中心點。那什麼是:基於原型的聚類技術呢?我們都知道,簇是物件的集合,並且每個物件到定義該簇的原型的距離比到其他簇原型的距離更近,或者說更相似。對於具有連續屬性的資料,簇的原型通常是質心,即簇中所有點的平均值。當質心沒有意義時,例如當資料具有分類(標稱)屬性時,原型通常是中心點,即簇中最有代表性的點。對於許多資料型別,原型可以視為最靠近中心的點,在這種情況下,通常把基於原型的簇看作基於中心的簇(用一個具有代表性的資料來作為分類的依據,得到最後的各個類(物件最後的集合)就是基於原型的簇)。那什麼是:建立資料物件的單層劃分呢?劃分聚類就是簡單地將資料物件劃分成不重疊的子集(簇),使得每個資料物件恰在一個子集中。總的來說:K均值和K中心點的核心思想都是通過一個能夠起到代表性作用的特殊點,來將資料集中的資料來進行分類(劃分)。下面瞭解區分K均值演算法與K中心點演算法的各自特點。

K均值用質心定義原型,其中質心是一組點的均值。通常K均值聚類用於n維連續空間中的物件。而K中心點使用中心點定義原型,其中中心點是一組點中最具有代表性的點。K中心點聚類可以用於廣泛的資料,因為它只需要完成對資料物件之間的鄰近性進行度量。儘管質心幾乎從來不對應於實際的資料點,但是根據定義,中心點必須是一個實際資料點。下面針對K均值演算法做一個全面的認識。

K均值演算法的具體操作步驟:1、選擇K個初始質心,其中K是使用者指定的引數,即所期望的簇的個數。每個點指派到最近的質心,而指派到一個質心的點集為一個簇。2、根據指派到簇的點,更新每個簇的質心。3、重複指派和更新步驟,直到簇不發生變化,或等價地,直到質心不發生變化。

K均值的偽演算法如下:

1、選擇K個點作為初始的質心

2、Repeat

3、   將每個點指派到最近的質心,形成K個簇。

4、   重新計算每個簇的質心

5、Until 質心不發生變化

對於鄰近性函式和質心型別的某些組合,K均值總是收斂到一個解,即K均值到達一種狀態,其中所有點都不會從一個簇轉移到另一個,從而質心不再改變。然而,由於大部分收斂都發生在早期階段,因此上面的虛擬碼最後一行通常使用較弱的條件來替換,比如:until 直到僅有1%的點改變簇。

下面我們將更加詳細地考慮基本K均值演算法的每一個步驟,並分析演算法的時間和空間複雜度。

為了將點指派到最近的質心,需要鄰近性度量來量化所考慮的資料的最近這個抽象的概念。通常,對於歐氏空間中的點使用歐幾里得距離(),對於文件則使用餘弦相似性。

K均值演算法第4步一般可以陳述為:重新計算每個簇的質心,因為質心可能隨資料鄰近性度量和聚類的目標不同而改變。聚類的目標通常用一個目標函式表示,該函式依賴於點之間,或點到簇的質心的鄰近性,如:最小化每個點到最近質心的距離的平方。

當考慮近鄰度量為歐幾里得距離的資料時,我們使用:誤差的平方和(Sum of the Squared ErrorSSE)作為度量聚類質量的目標函式。SSE也稱為:散佈(scatter)。換言之,我們需要計算每個點的誤差,即它到最近質心的歐幾里得距離,然後計算誤差的平方和。如果給定由兩次執行K均值產生的兩個不同的簇集,我們更喜歡誤差的平方和最小的那個,因為這說明:聚類的原型(質心)可以更好地代表簇中點。SSE形式地定義如下:

 

其中,dist是歐幾里得空間中兩個物件之間的標準歐幾里得距離()。給定的這些假設,使得簇的SSE最小的質心是均值。這個證明我們留到後面。那麼,怎麼計算第i個簇的質心呢?我們可以通過以下的公式來獲得:

 

符號表

符 號

說明

x

物件

 

i個簇

 

簇的質心

c

所有點的質心

 

i個簇中物件的個數

m

資料集中物件的個數

K

簇的個數

 

例如,3個二維點(11)、(2,3)和(62)的質心是((1+2+6/3,(1+3+2/3=32

K均值演算法的步驟3和步驟4都試圖直接最小化SSE(目標函式),步驟3通過將點指派到最近的質心形成簇,最小化關於給定質心集的SSE,而步驟4則是在簇內中的物件來重新計算質心,更進一步最小化SSE。在這裡很明顯了:K均值的步驟3和步驟4只能確保找到關於SSE的區域性最優,因為它們是對選定的質心和簇,而不是對所有可能的選擇來優化SSE。這將導致了:次最優聚類的產生。

上面是使用K均值演算法來處理歐幾里得空間的連續型資料,那對於具有分類的標稱屬性的文件資料,我們該如何使用K均值演算法來進行擬合聚類分析呢?

對於文件資料,我們是通過餘弦相似性度量,來對 最近 這個抽象的詞進行量化的。文件型別資料我們一般使用:文件—詞矩陣表示,如下圖示:

 

teach

for

and

win

great

Document1

3

45

20

3

6

Document2

0

67

12

5

9

Document3

0

23

8

0

2

上圖就是典型的文件—詞矩陣表。我們的目標是最大化簇中文件與簇的質心的相似性,該度量稱為簇的:凝聚度(cohesion)。對於該度量,也可以證明,與歐幾里得資料一樣,簇的質心就是均值。與SSE的相似量是:總凝聚度(total cohesion),其計算公式如下:

 

以上討論了兩種常見的情況,下面看一下一般的情況。

一般情況,一些近鄰性函式、質心和目標函式可以用基於K均值演算法,並且確保收斂。需要注意的是:對於哈曼頓距離()和最小化距離和的目標,合適的質心是簇中各點的中位數。下面表格列舉了一些組合:

K均值:常見的鄰近度、質心和目標函式組合

鄰近度函式

質心

目標函式

哈曼頓距離()

中位數

最小化物件到其簇質心的距離和

平方歐幾里得距離()

均值

最小化物件到其簇質心的距離平方和

餘弦

均值

最大化物件與其簇質心的餘弦相似度

Bregman散度

均值

最小化物件到其簇質心的Bregman散度和

上表最後一項,Bregman散度實際上是一類近鄰性度量,它包括了平方歐幾里得距離,Mahalanobis距離和餘弦相似度。Bregman散度函式的重要性在於:任意這類函式都可以用均值作為質心,並以此作為K均值聚類演算法的基礎。具體地說,如果我們使用Bregman散度作為鄰近度函式,則聚類演算法的收斂性、區域性最小等性質,與通常的K均值相同。此外,對於所有可能的Bregman散度函式,都可以開發具有這樣性質的聚類演算法。事實上,我們使用的餘弦相似度或平方歐幾里得距離的K均值演算法,都是基於Bregman散度的一般聚類演算法的特例。

接下來通過使用二維資料來進一步討論K均值演算法及其性質。因為K均值是非常一般的聚類演算法,所以它可以用於許多型別的資料,如文件、時間序列等。

從上面的討論中,我們知道:K均值演算法的第一步就是要選定一個初始質心,然後開始聚類(形成簇),接下來再改變質心(從簇中計算出),這個過程一直持續到until條件滿足為止。所以如果選定的初始質心一樣的話,執行相同的K均值演算法,得到最後總SSE是不同的,所以如何選取這個初始質心是十分重要的(演算法本身對這個初始質心依賴性很大)。選擇適當的初始質心是基本K均值過程的關鍵步驟。常見的方法是隨機地選取初始質心,但是這樣最後得到的簇的質量往往都是很差的。

上面這種隨機地選取初始質心的屬於:拙劣的初始質心的做法。還有一種是:隨機初始化的侷限做法,具體是這樣的:多次執行,每次使用一組不同的隨機初始質心,然後選取具有最小SSE的簇集。該策略雖然簡單,但是效果可能不好,這取決於資料集和尋找的簇的個數。只有兩個初始質心,無論落在簇對的任何位置,都能得到最優聚類,因為質心將自己重新分佈,每個簇一個。但不幸的是,隨著簇的個數增加,至少一個簇對只有一個初始質心的可能性也逐步增大。在這種情況下,由於簇對相距較遠,K均值演算法不能在簇對之間重新分佈質心,這樣就只能得到區域性最優了。

隨機選擇初始質心存在的問題,即使重複執行多次也不能克服,因此常常使用其他技術進行初始化。一種有效的方法是:取一樣本,並使用層次聚類技術對它聚類。從層級聚類中提取K個簇,並使用這些簇的質心作為初始質心。這種方法通常很有效,但也僅對下列的情況有效:(1)樣本相對較小,例如數百到數千(層次聚類開銷較大);(2K相對於樣本大小較小。下面來了解一下層次聚類是怎樣的。

如果允許簇具有子簇,我們就可以得到一個層次聚類(hierarchical clustering)。層次聚類是巢狀簇的集族,組織成一棵樹。除葉節點外,樹中每一個節點(簇)都是其子女(子簇)的並,而樹根是包含所有物件的簇。通常(並非總是),樹葉是單個數據物件的單元素簇。層次聚類可以看做是劃分聚類的序列,劃分聚類可以通過取序列的任意成員得到,即通過在一個特定層剪斷層次樹得到。接下來了解一下什麼是劃分聚類。

劃分聚類(partitional clustering)就是簡單地將資料物件集劃分成不重疊的子集(簇),並且使得每個資料物件恰在一個子集中。

我們下面還可以通過另外一種選擇初始質心的方法——隨機地選取第一個點,或取所有點的質心(均值)作為第一個點。然後,對於每個後繼初始質心,選擇離已經選取過的初始質心最遠的點。使用這種方法,我們得到初始質心的集合,確保不是隨機的,而是散開的。然而,這種方法可能選中離群點,而不是稠密區域(簇)中的點。此外,求離當前初始質心集最遠的點,開銷也是非常大的。為了克服這些問題,通常將該方法用於點樣本。由於離群點很少,它們多半不會在隨機樣本中出現。相比之下,除非是樣本非常小,否則來自稠密區的點是很有可能包含在樣本中的。此外,找出初始質心所需要的計算量也大幅度減少了,因為樣本的大小通常遠小於點的個數。

以上討論的K均值演算法,都對最初的初始質心有很大的依賴(對初始質心很敏感)了,稍後,我們將要討論另外的兩種產生較高質量(較低SSE)聚類的方法:(1)使用對初始化問題不太敏感的K均值的變種——二分K均值法;(2)使用後處理來修補所產生的簇集。下面來看一下K均值的時間複雜性和空間複雜性是怎樣的。

K均值的空間需求是適度的,因為只需要存放資料點和質心。具體地說,所需要的儲存量為O((m+K*n),其中m是點數,n是屬性數。K均值演算法的時間複雜度也是適度的。它基本上與資料點個數是線性相關的。具體地說,所需要的時間為OI*K*m*n),其中I是收斂所需要迭代的次數。如前面所述,I通常很小,可以是有界的,因為大部分變化通常出現在前幾次迭代。因此,只要簇的個數K顯著小於m的話,那麼K均值的計算時間與m線性相關,並且是有效的和簡單的。

現在可以討論一下有關K均值的一些附加問題以及對應的處理方法了。

前面介紹的基本K均值演算法存在的問題之一是:如果所有的點在指派步驟都未分配都某個簇,就會得到一個空簇。如果這種情況發生,則需要某種策略來選擇一個替補質點,否則的話,平方誤差將會偏大。一種方法是選擇一個距離當前任何質心最遠的點。這將消除當前對總平方誤差影響最大的點。另一種方法是從具有最大SSE的簇中,選擇一個替補質心。這將分裂簇,並降低聚類的總SSE。如果有多個空簇,則該過程重複多次。這是處理空簇的問題,接下來是離群點問題的處理了。

使用平方誤差標準時,離群點可能會過度影響所發現的簇。具體地說,當存在離群點時,結果簇的質心(原型)可能不如沒有離群點時那樣有代表性,並且SSE也比較高。正是因為如此,提前發現離群點並刪除它們是有用的。然而,也應當意識到有一些聚類的應用,是不能刪除離群點的。當聚類用來壓縮資料時,必須對每個點聚類。在某些情況下(如財經分析),明顯的離群點(如不尋常的有利可圖的顧客)可能是最令人感興趣的點。如果我們使用的方法在聚類前就刪除離群點,則我們就避免了對不能很好聚類的點進行聚類。當然也可以在後處理時,識別離群點。例如,我們可以通過記錄每個點對SSE的影響,刪除那些具有異乎尋常的點(尤其是多次執行演算法時)。此外,我們還可能需要刪除那些很小的簇,因為它們常常代表離群點的組。

下面介紹如何使用:用後處理降低SSE

一種明顯降低SSE的方法是找出更多簇,即使用較大的K值。然而,在許多情況下,我們希望降低SSE,但並不想增加簇的個數。這是有可能做到的,因為K均值常常收斂於區域性極小。可以使用多種技術來修補結果簇,以便產生較小SSE的聚類。策略是關注每一個簇,因為總SSE只不過是每個簇的SSE之和。通過在簇上進行諸如分裂和合並等操作,我們可以改變總SSE。一種常用的方法是是交替地使用簇分裂和簇合並。在分裂階段,將簇分開,而在合併階段將簇合並。用這種方法,常常可以避開區域性極小,並且仍能夠得到具有期望個數簇的聚類。

通過增加簇個數來降低總SSE的兩種策略:(1)分裂一個簇:通常選擇具有最大SSE的簇,但是我們也可以分裂在特定屬性上具有最大標準差得到簇。(2)引進一個新的質心:通常選擇離所有簇質心最遠的點。如果我們記錄每個點對SSE的貢獻,則可以很容易地確定最遠的點。另一種方法是從所有的點或者具有最高SSE的點中隨機地選擇。

通過減少簇個數來最小化總SSE增長的兩種策略:(1)拆散一個簇:刪除簇的對應質心,並將簇中的點重新指派到其他簇。理想情況下,被拆散的簇應當是使總SSE增加最少的簇。(2)合併兩個簇:通常選擇質心最接近的兩個簇,儘管另一種方法(合併兩個導致總SSE增加最少的簇)或許會更好。這兩種合併的策略與層次聚類使用的方法相同,分別稱作:質心方法和Ward方法。

下面來看K均值的:增量地更新質心的方法。

我們可以在點到簇的每次指派之後,增量地更新質心,而不是在所有的點都指派到簇中之後才更新簇質心。注意,每步需要零次或兩次簇質心更新,因為一個點或者轉移到一個新的簇(兩次更新),或者是留在它的當前簇(零次更新)。使用增量更新策略確保不會產生空簇,因為所有的簇都從單個點開始;並且如果一個簇只有單個點,則該點總是被重新指派到相同的簇。此外,如果使用增量更新,則可以調整點的相對權值;例如,點的權值通常隨聚類的進行而減小。儘管這可能產生更好的準確率和更快的收斂性,但是在千變萬化的情況下,選擇好的相對權值可能是困難的。這些更新問題類似於人工神經網路的權值更新。

增量更新的另一個優點是使用不同於最小化SSE的目標。加上給定一個度量簇集的目標函式。當我們處理某個點時,我們可以對每個可能的簇指派計算目標函式的值,然後選擇優化目標的簇指派。缺點方面,增量地更新質心可能導致演算法對次序的依賴性。換言之,所產生的簇可能依賴於點的處理次序。儘管隨機地選擇點,次序問題可以解決,但是,基本K均值方法在把所有點指派到簇中之後才更新質心,就沒有次序依賴性的問題。此外,增量更新的開銷也稍微大一些。然而,K均值收斂相當快,因此切換簇的點數很快就會變小。

前面已經提到過了一種:能夠產生大量較高質量(較低SSE)聚類的方法——二分K均值法,其實它就是K均值法的變種,它具有的特點是:對初始化問題不太敏感。下面重點討論二分K均值法。

二分K均值演算法是基本K均值演算法的直接擴充,它基於一種簡單的想法:為了得到K個簇,將所有點的集合分裂成兩個簇,從兩個簇中選取一個繼續分裂,如此下去,直到產生K個簇。

二分K均值的細節演算法如下:

1、初始化簇表,使之包含由所有的點組成的簇。

2、Repeat

3、從簇表中取出一個簇

4、{對選定的簇進行多次二分試驗。}

5、For i=1 to 實驗次數 do

6、    使用基本K均值,二分選定的簇。

7、End for

8、從二分試驗中選擇具有最小總SSE的兩個簇

9、將這兩個簇新增到簇表中

10、until 簇表中包含K個簇

待分裂的簇有許多不同的選擇方法。可以選擇最大的簇,選擇具有最大SSE的簇,或者使用一個基於大小和SSE的標準進行選擇。不同的選擇導致不同的簇。

我們通常使用結果簇的質心作為基本K均值的初始質心,對結果簇逐步求精。這是必要的,因為儘管K均值演算法可以確保找到使SSE區域性最小的聚類,但是在二分K均值演算法中,我們是通過區域性地使用了K均值演算法,即每次二分一個個體簇。因此,最終的簇集並不代表是SSE區域性最小的聚類。

二分K均值不太受初始化的困擾,因為它執行了多次二分試驗並選取具有最小SSE的試驗結果,還因為每步只有兩個質心。最後,通過記錄K均值二分簇所產生的聚類序列,我們還可以使用二分K均值產生層次聚類。

最後討論一下:K均值的優缺點問題。

K均值簡單並且可以用於各種資料型別。它也相當有效,儘管常常多次執行。K均值的某些變種(包含二分均值)甚至更有效,並且不太受初始化問題的影響。然而,K均值並不適合所有的資料型別。它不能處理非球形簇、不同尺寸和不同密度的簇,儘管指定足夠大的簇個數時,它通常能夠發現純子簇。對包含離群點的資料進行聚類時,K均值也有問題。在這種情況下,離群點檢測和刪除大有幫助。最後,K均值僅限於具有中心(質心)概念的資料。在之前提到過的另外一種聚類技術——K中心點聚類技術沒有這種限制,但開銷更大。