1. 程式人生 > >聚類經典演算法之DBSCAN演算法

聚類經典演算法之DBSCAN演算法

這一篇主要記錄下對dbscan演算法的學習。下一篇將說說把此演算法具體運用到熱點區域分析。好了,切入正題。

第一個,什麼是dbscan?全稱為:Density-Based Spatial Clustering of Applications with Noise(具有噪聲的基於密度的聚類方法)。這是一種基於密度的聚類演算法,能夠除去噪音點,並且聚類的結果是劃分為多個簇,簇的形狀是任意的。基於密度的聚類演算法都是尋找被低密度區域分離的高密度區域。

 第二個,關於點的概念。基於密度的定義(以某一點為中心,在單位半徑範圍內所有點的集合),我們可以把點分為3種: 核心點,邊界點,噪音點。

核心點: 在半徑Eps內含有超多MinPts數目點,則該點就是核心點。

邊界點: 在半徑Eps內含有小於MinPts數目,並且是在核心點的領域內。

噪音點: 任何不適核心點或邊界點的點。(那麼在Eps內數目為0的點必定是噪音點,想想為什麼?)

畫圖舉例:


在上圖中,因為A點在Eps半徑內的點數目為2<3 且另外兩個點也不是核心點,所以A為噪音點。C在Eps半徑內的數目為4>3,所以C為核心點,而B中則為2個點,但是B在A的Eps半徑範圍內。

另外,什麼是Eps鄰域呢?給定物件半徑Eps內的鄰域稱為該物件的Eps鄰域,我們習慣用Neps(p)表示點p的Eps半徑內點的集合,也就是:

Neps(p) = {q| q在資料集D中,distance(p,q)<= Eps};

第三個,關於dbscan的幾個概念:

1)直接密度可達:從字面上,給人的感覺就是某點p在一個密度範圍內可以找到點q。好了,我們規範理解下,就是,給定一個物件集合D,如果說p在q的鄰域內,而q是一個核心物件,則稱物件p從物件q出發時時直接密度可達的。

2)密度可達: 有了上面的經驗,這不難理解就是經過一個或多個密度範圍能夠找到。。規範理解就是,如果存在一條物件鏈P1, P2,  P3, P4 ,...Pn。其中P1 = q, Pn =q。如果對於集合D內的一點Pi存在Pi+1是從Pi關於Eps和MinPts直接密度可達的,則物件p是從物件q關於Eps和MinPts密度可達的。

3)密度相連。這是重點,簡單理解就是,如果存在屬於集合D的物件O,使得物件p和q都是從O關於Eps和MInPts密度可達的,那麼物件p到q是關於Eps和MinPts密度相連的。而dbscan演算法的目的就是要找出最大的密度相連集合。這裡,直接找網上的一個例子就好了。

第四個,dbscan演算法的原理。dbscan遍歷每個物件,假設檢查到物件P,此時判斷p的Eps鄰域內的物件個數是否大於等於MinPts個,如果滿足,則建立以P為核心物件的簇,然後呢,我們說要儘可能的找最大的密度相連集合,那麼就是要迭代查詢P的Eps鄰域內每個點的直接密度可達物件。。

第五個,程式碼如何實現? 以下用虛擬碼實現

1.將資料集D中的所有點標記為未訪問狀態,且簇Id為0.
2.
for p in D:
   if p 已經訪問過或者p的簇Id !=0:
      continue;
   else:
      標記點p已經訪問過;
      獲取p點Eps鄰域內的點集合,個數為Neps(p);
      if Neps(p) <=0 :
          標記p的簇Id為-1(噪音點);
      else if Neps(p) >= MinPts:
          此時標記物件p為核心點,簇Id +=1,並設定鄰域內各點的簇Id;
          for q in p的Eps鄰域所有未處理點的集合:
             檢查q的簇Id是否等於0,若不,則判斷Neps(q)是否大於等於MInPts,滿足則標記簇Id為p的簇Id.

          
         

        第六個,關於Eps和MinPts的那點事。 通過實踐表明,Eps和MinPts的取值會影響到演算法的效果。那麼在實際運用當中,我們又該如何取值呢? 有些人說是看經驗。好吧,反正我是沒那個能力。我會選擇通過不斷調節MinPts和Eps的範圍來檢視聚合的效果。還有通過繪製輔助圖來檢視效果。看看每次的聚合數佔資料集D的比率。

第七個,關於dbscan的優點與缺點。優點的話,正如他的定義,他是基於密度的,所以它的效果不言而喻,簇的形狀可以是任意的。並且能夠分離出那些噪音點。當然,再好的演算法也有它不足的地方,正如那句上帝為你關閉了一扇門,自然為你開啟你了一扇窗。dbscan的不足還是挺明顯的。如果簇的密度變化很大時,效果很差的。這個後面在運用地圖查詢熱點區域時會說到。 還有個就是處理高維問題時,如何定義密度,是一個很棘手的問題(這個真要具體問題具體分析)。

以上就是關於dbscan的初步學習。後面會談具體運用,以及在hadoop下面編寫dbscan演算法(當然有相關庫,但還是要自己動手學習學習,這樣才能不斷進度,才會去考慮如何改進)。