本篇結構
- 簡介
- 聚類算法的分類
- K-Means聚類算法
- DBSCAN聚類算法
本篇介紹了聚類算法的種類,重點關注K-Means和DBSCAN兩類聚類算法,并給出具體實現。
一、簡介
1.1 什么是聚類
聚類是數據挖掘中的概念,就是按照某個特定標準(如距離)把一個數據集分割成不同的類或簇,使得同一個簇內的數據對象的相似性盡可能大,同時不在同一個簇中的數據對象的差異性也盡可能地大。也即聚類后同一類的數據盡可能聚集到一起,不同類數據盡量分離。
1.2 什么是分類
分類簡單來說,就是根據文本的特征或屬性,劃分到已有的類別中。也就是說,這些類別是已知的,通過對已知分類的數據進行訓練和學習,找到這些不同類的特征,再對未分類的數據進行分類。
1.3 聚類與分類的區別
Clustering (聚類),是把相似的東西分到一組。聚類的時候,并不關心某一類是什么,需要實現的目標只是把相似的東西聚到一起。因此,一個聚類算法通常只需要知道如何計算相似度就可以開始工作了,因此 clustering 通常并不需要使用訓練數據進行學習,這在Machine Learning中被稱作unsupervised learning (無監督學習)。
Classification (分類),對于一個classifier,通常需要告訴它“這個東西被分為某某類”這樣一些例子,理想情況下,一個 classifier 會從它得到的訓練集中進行“學習”,從而具備對未知數據進行分類的能力,這種提供訓練數據的過程通常叫做supervised learning (監督學習)。
1.4 舉例說明兩者的區別
假設有一批人的年齡的數據,大致知道其中有一堆少年兒童,一堆青年人,一堆老年人。
聚類就是自動發現這三堆數據,并把相似的數據聚合到同一堆中。所以對于這個例子,如果要聚成3堆的話,那么輸入就是一堆年齡數據,注意,此時的年齡數據并不帶有類標號,也就是說我只知道里面大致有三堆人,至于誰是哪一堆,現在是不知道的,而輸出就是每個數據所屬的類標號,聚類完成之后,就知道誰和誰是一堆了。
而分類就是,事先告訴你,少年兒童、青年人及老年人的年齡是什么樣的,現在新來了一個年齡,輸出它的類標號,就是它是屬于少年兒童、青年人、老年人的哪個類。一般來說,分類器是需要訓練的,也就是要告訴你的算法,每個類的特征是什么樣子,它才能識別新的數據。
下面再舉一個實際的例子。
對于聚類,比如有些搜索引擎有“查看相似網頁”的功能,這個就可以用聚類來做,把網頁就行聚類,在聚類的結果中,每一個類中的網頁看成是相似的。
對于分類,比如手寫識別就可以看到是分類問題,比如我寫了10個“我”字,然后對這10個“我”字進行特征提取,就可以告訴算法,“我”字具有什么樣的特征,于是來了一個新的“我”字,雖然筆畫和之前的10個“我”字不完全一樣,但是特征高度相似,于是就把這個手寫的字分類到“我”這個類,就識別出來了。
總結一下,數據分類是分析已有的數據,尋找其共同的屬性,并根據分類模型將這些數據劃分成不同的類別,這些數據賦予類標號。這些類別是事先定義好的,并且類別數是已知的。相反,數據聚類則是將本沒有類別參考的數據進行分析并劃分為不同的組,即從這些數據導出類標號。聚類分析本身則是根據數據來發掘數據對象及其關系信息,并將這些數據分組。每個組內的對象之間是相似的,而各個組間的對象是不相關的。不難理解,組內相似性越高,組間相異性越高,則聚類越好。
二、聚類算法的分類
來自博文:常用聚類算法有哪些?
主要分為層次化聚類算法,劃分式聚類算法,基于密度的聚類算法,基于網格的聚類算法,基于模型的聚類算法等。
2.1 基于劃分的聚類(partitioning methods)
給定一個有N個元組或者記錄的數據集,分裂法將構造K個分組,每一個分組就代表一個聚類,K《N。而且這K個分組滿足下列條件:
- 每一個分組至少包含一個數據紀錄;
- 每一個數據紀錄屬于且僅屬于一個分組(注意:這個要求在某些模糊聚類算法中可以放寬);
對于給定的K,算法首先給出一個初始的分組方法,以后通過反復迭代的方法改變分組,使得每一次改進之后的分組方案都較前一次好,而所謂好的標準就是:同一分組中的記錄越近越好,而不同分組中的紀錄越遠越好。
大部分劃分方法是基于距離的。給定要構建的分區數k,劃分方法首先創建一個初始化劃分。然后,它采用一種迭代的重定位技術,通過把對象從一個組移動到另一個組來進行劃分。一個好的劃分的一般準備是:同一個簇中的對象盡可能相互接近或相關,而不同的簇中的對象盡可能遠離或不同。
代表算法有:K-means,K-medoids,CLARANS。
2.2 基于分層的聚類(hierarchical methods)
這種方法對給定的數據集進行層次似的分解,直到某種條件滿足為止。具體又可分為“自底向上”和“自頂向下”兩種方案。
例如:在“自底向上”方案中,初始時每個數據點組成一個單獨的組,在接下來的迭代中,按一定的距離度量將相互鄰近的組合并成一個組,直至所有的記錄組成一個分組或者滿足某個條件為止。代表算法有:BIRCH,CURE,CHAMELEON等。
2.3 基于密度的聚類(density-based methods)
基于密度的方法的特點是不依賴于距離,而是依賴于密度,從而克服基于距離的算法只能發現“球形”聚簇的缺點。其核心思想在于只要一個區域中點的密度大于某個閾值,就把它加到與之相近的聚類中去。代表算法有:DBSCAN,OPTICS,DENCLUE,WaveCluster。
2.4 基于網格的聚類(gird-based methods)
這種方法通常將數據空間劃分成有限個單元的網格結構,所有的處理都是以單個的單元為對象。這樣做起來處理速度很快,因為這與數據點的個數無關,而只與單元個數有關。代表算法有:STING,CLIQUE,WaveCluster。
2.5 基于模型的聚類(model-based methods)
基于模型的方法給每一個聚類假定一個模型,然后去尋找能很好的擬合模型的數據集。模型可能是數據點在空間中的密度分布函數或者其它。這樣的方法通常包含的潛在假設是:數據集是由一系列的潛在概率分布生成的。通常有兩種嘗試思路:統計學方法和神經網絡方法。其中,統計學方法有COBWEB算法、GMM(Gaussian Mixture Model),神經網絡算法有SOM(Self Organized Maps)算法。
三、K-Means聚類算法
3.1 定義
k-means算法中的k代表類簇個數,means代表類簇內數據對象的均值(這種均值是一種對類簇中心的描述),因此,k-means算法又稱為k-均值算法。k-means算法是一種基于劃分的聚類算法,以距離作為數據對象間相似性度量的標準,即數據對象間的距離越小,則它們的相似性越高,則它們越有可能在同一個類簇。
數據對象間距離的計算有很多種,k-means算法通常采用歐氏距離來計算數據對象間的距離,計算公式如下(如果是多維也可以進行擴展):
k-means算法聚類過程中,每次迭代,對應的類簇中心需要重新計算(更新):對應類簇中所有數據對象的均值,即為更新后該類簇的類簇中心。
k-means算法需要不斷地迭代來重新劃分類簇,并更新類簇中心,那么迭代終止的條件是什么呢?一般情況,有兩種方法來終止迭代:一種方法是設定迭代次數T,當到達第T次迭代,則終止迭代,此時所得類簇即為最終聚類結果;另一種方法是采用誤差平方和準則函數。
3.2 算法思路
k-means算法思想可描述為:
- 首先初始化K個類簇中心;
- 然后計算各個數據對象到聚類中心的距離,把數據對象劃分至距離其最近的聚類中心所在類簇中;
- 接著根據所得類簇,更新類簇中心;
- 繼續計算各個數據對象到聚類中心的距離,把數據對象劃分至距離其最近的聚類中心所在類簇中;
- 根據所得類簇,繼續更新類簇中心;
- 一直迭代,直到達到最大迭代次數T,或者兩次迭代J的差值小于某一閾值時,迭代終止,得到最終聚類結果。
3.3 算法實現
網上有很多實現,可以參考一下下面的博文:
C#下實現的基礎K-MEANS多維聚類
k-means聚類算法
也可以參考我的github:
3.4 優缺點
k-means算法優缺點分析
- 優點
??原理比較簡單,實現也是很容易,收斂速度快
??聚類效果較優
??算法的可解釋度比較強 - 缺點
??K值的選取不好把握
??聚類結果對初始類簇中心的選取較為敏感
??對噪音和異常點比較的敏感
??可能收斂到局部最小值,在大規模數據集上收斂較慢
??只能發現球型類簇
四、DBSCAN聚類算法
4.1 定義
來自博文:從DBSCAN算法談談聚類算法
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪聲的基于密度的聚類方法)是一種基于密度的空間聚類算法。該算法將具有足夠密度的區域劃分為簇,并在具有噪聲的空間數據庫中發現任意形狀的簇,它將簇定義為密度相連的點的最大集合。
DBSCAN一些關鍵概念的定義:
- ?鄰域:給定對象半徑?內的區域稱為該對象的?鄰域。
- 核心對象(core points):如果給定對象?鄰域內的樣本點數大于等于MinPts,則稱該對象為核心對象。
- 直接密度可達(directly density-reachable):給定一個對象集合D,如果p在q的?的鄰域內,且q是一個核心對象,則我們說對象p從對象q出發是直接密度可達的。
- 密度可達(density-reachable):對于樣本集合D,如果存在一個對象鏈P1,P2,...,Pn,P1=q,Pn=p,對于Pi∈D,1≤i≤n,Pi+1是從Pi關于?和MinPts直接密度可達,則對象p是從對象q關于?和MinPts密度可達的。
- 密度相連(density-connected):如果存在對象o∈D,使對象p和q都是從o關于?和MinPts密度可達的,那么對象p到q是關于?和MinPts密度相連的。
根據上圖,分別解釋這五條定義。
- 以某個數據樣本點作為圓心,以?為半徑畫圓,每個圓所圈的區域就是?鄰域。直觀上來說,有多少個數據樣本點,就有多少個鄰域。
- 核心對象數學形式的定義如下:N?(p)={q∈D|dist(p,q)≤?},且p∈N?(p),|N?(p)|≥MinPts,滿足上述兩個條件的p為核心對象。從同圖中來說,假設MinPts是3,紅色的點都屬于核心對象。
- 如A點所畫出的圈圈內的其他任何紅色點都屬于直接密度可達。
- 密度可達的關系相對弱一點,除A點鄰域內的其他紅色點與A的關系均屬于密度可達。
- 從A出發,能夠密度可達的任意兩個點都屬于密度相連。
由以上概念,DBSCAN算法中將數據點分為一下三類:
- 核心點--在半徑Eps內含有超過MinPts數目的點
- 邊界點--在半徑Eps內點的數量小于MinPts,但是落在核心點的鄰域內
- 噪音點--既不是核心點也不是邊界點的點
4.2 算法思路
DBSCAN算法描述:
- DBSCAN算法從一個未被訪問的任意的數據點開始。這個點的鄰域是用距離epsilon來定義(即該點ε距離范圍內的所有點都是鄰域點)。
- 如果在該鄰域內有足夠數量的點(根據minPoints的值),則聚類過程開始,并且當前數據點成為新簇中的第一個點。否則,該點將被標記為噪聲(稍后,這個噪聲點可能成為聚類中的一部分)。在這兩種情況下,該點都會被標記為“已訪問”。
- 對于新簇中的第一個點,它的ε距離鄰域內的點也會成為同簇的一部分。這個過程使ε鄰域內的所有點都屬于同一個簇,然后對才添加到簇中的所有新點重復上述過程。
- 重復步驟2和3兩個過程直到確定了聚類中的所有點才停止,即訪問和標記了聚類的ε鄰域內的所有點。
- 一旦我們完成了當前的聚類,就檢索和處理新的未訪問的點,就能進一步發現新的簇或者是噪聲。重復上述過程,直到所有點被標記為已訪問才停止。由于所有點已經被訪問完畢,每個點都被標記為屬于一個簇或是噪聲。
具體算法描述如下:
- 檢測數據庫中尚未檢查過的對象p,如果p未被處理(歸為某個簇或者標記為噪聲),則檢查其鄰域,若包含的對象數不小于MinPts ,建立新簇C,將其中的所有點加入候選集N;
- 對候選集N 中所有尚未被處理的對象q,檢查其鄰域,若至少包含MinPts個對象,則將這些對象加入N;如果q 未歸入任何一個簇,則將q 加入C;
- 重復步驟2),繼續檢查N 中未處理的對象,當前候選集N為空;
- 重復步驟1)~3),直到所有對象都歸入了某個簇或標記為噪聲。
其偽代碼描述如下:
輸入:數據對象集合D,半徑Eps,密度閾值MinPts
輸出:聚類C
**DBSCAN(D, Eps, MinPts)
Begin
init C=0; //初始化簇的個數為0
for each unvisited point p in D
mark p as visited; //將p標記為已訪問
N = getNeighbours (p, Eps);
//如果滿足sizeOf(N) < MinPts,則將p標記為噪聲
if sizeOf(N) < MinPts then
mark p as Noise;
else
C= next cluster; //建立新簇C
ExpandCluster (p, N, C, Eps, MinPts);
end if
end for
End**
ExpandCluster(p, N, C, Eps, MinPts)
add p to cluster C; //首先將核心點加入C
for each point p’ in N
mark p' as visited;
N’ = getNeighbours (p’, Eps); //對N鄰域內的所有點在進行半徑檢查
if sizeOf(N’) >= MinPts then
N = N+N’; //如果大于MinPts,就擴展N的數目
end if
if p’ is not member of any cluster
add p’ to cluster C; //將p' 加入簇C
end if
end for
End ExpandCluster
如果沒有講清楚,可以參考下面的博文:
聚類分析常用算法原理:KMeans,DBSCAN
DBSCAN 算法介紹以及C++實現
4.3 算法實現
可以參考博文:
也可以訪問我的github:
4.4 優缺點
DBSCAN算法優缺點:
- 優點
??可以對任意形狀的稠密數據集進行聚類,相對的,K-Means之類的聚類算法一般只適用于凸數據集
??可以在聚類的同時發現異常點,對數據集中的異常點不敏感
??聚類結果沒有偏倚,相對的,K-Means之類的聚類算法初始值對聚類結果有很大影響 - 缺點
??如果樣本集的密度不均勻、聚類間距差相差很大時,聚類質量較差,這時用DBSCAN聚類一般不適合
??調參相對于傳統的K-Means之類的聚類算法稍復雜,主要需要對距離閾值?,鄰域樣本數閾值MinPts聯合調參,不同的參數組合對最后的聚類效果有較大影響