機器學習(8)——其他聚類

weixin_33860722發表於2018-03-24

層次聚類

緊接上章,本章主要是介紹和K-Means演算法思想不同而的其他聚類思想形成的聚類演算法。

k-means演算法卻是一種方便好用的聚類演算法,但是始終有K值選擇和初始聚類中心點選擇的問題,而這些問題也會影響聚類的效果。為了避免這些問題,我們可以選擇另外一種比較實用的聚類演算法-層次聚類演算法。顧名思義,層次聚類就是一層一層的進行聚類,可以由上向下把大的類別(cluster)分割,叫作分裂法;也可以由下向上對小的類別進行聚合,叫作凝聚法;但是一般用的比較多的是由下向上的凝聚方法。

本章主要涉及到的知識點有:

層次聚類
BIRCH演算法

層次聚類

層次聚類方法對給定的資料集進行層次的分解,直到滿足某種條件為止,傳統的層次聚類演算法主要分為兩大類演算法:分裂的層次聚類和凝聚的層次聚類。

分裂的層次聚類

DIANA演算法( Divisive analysis)採用自頂向下的策略。首先將所有物件置於一個簇中,然後按照某種既定的規則逐漸細分為越來越小的簇(比如最大的歐式距離),直到達到某個終結條件(簇數目或者簇距離達到閾值)。

分裂法指的是初始時將所有的樣本歸為一個類簇,然後依據某種準則進行逐漸的分裂,直到達到某種條件或者達到設定的分類數目。演算法構建步驟:

(1)將樣本集中的所有的樣本歸為一個類簇;

(2)在同一個類簇(計為c)中計算兩兩樣本之間的距離,找出距離最遠的兩個樣本a,b;

(3)將樣本a,b分配到不同的類簇c1和c2中;

(4)計算原類簇(c)中剩餘的其他樣本點和a,b的距離,若是dis(a)<dis(b),則將樣本點歸到c1中,否則歸到c2中;

(5)重複以上步驟,直到達到聚類的數目或者達到設定的條件。

這裡我們可以看出,上一章所說的 K-Means演算法及其優化演算法就是運用這種自頂向下的策略。例如:有一些點,按照上面所說的演算法構建步驟的過程可以如下圖表示出來:


1652713-8f1d8146ce7f7f08.png
自頂向下聚類思想

常見的自頂向下的演算法有K-means層次聚類演算法。但值得注意的是:對於以上的例子,紅色橢圓框中的物件聚類成一個簇可能是更優的聚類結果,但是由於橙色物件和綠色物件在第一次K-means就被劃分到不同的簇,之後也不再可能被聚類到同一個簇。

1652713-90c7fa214b36fe5a.png
image.png

兩個簇之間最近的兩個點的距離作為簇之間的距離,該方式的缺陷是受噪點影響大,容易產生長條狀的簇。

凝聚的層次聚類

AGNES演算法( Agglomerative Nesting)採用自底向上的策略。最初將每個物件作為一個簇,然後這些簇根據某些準則被一步一步合併,兩個簇間的距離可以由這兩個不同簇中距離最近的資料點的相似度來確定;聚類的合併過程反覆進行直到所有的物件滿足簇數目。

凝聚法指的是初始時將每個樣本點當做一個類簇,所以原始類簇的大小等於樣本點的個數,然後依據某種準則合併這些初始的類簇,直到達到某種條件或者達到設定的分類數目。演算法步驟:

(1) 將樣本集中的所有的樣本點都當做一個獨立的類簇;

(2) 計算兩兩類簇之間的距離(後邊會做介紹),找到距離最小的兩個類簇c1和c2;

(3) 合併類簇c1和c2為一個類簇;

(4) 重複以上步驟,直到達到聚類的數目或者達到設定的條件。

根據演算法構建的步驟,演算法的思想可以用下圖來表現出來:

[圖片上傳失敗...(image-fbc155-1521869527009)]

8.1.1 簇間距離

在以上演算法的構建過程中,我們提到了兩個簇之間的距離的計算,例如對於兩個簇C_1和C_2,有三種方法計算塔門之間的距離:

(1)單連鎖(Single link)

兩個簇之間的最小距離:

1652713-f857316524400f60.png
image.png

如下圖所示:

1652713-494748c1926f1e7c.png
image.png

圖10.3単連鎖圖

兩個簇之間最近的兩個點的距離作為簇之間的距離,該方式的缺陷是受噪點影響大,容易產生長條狀的簇。

(2)全連鎖(Complete link)

兩個簇之間的最大距離:


1652713-410a5eff6d04cd8d.png
image.png

1652713-9e2a1cda89987107.png
image.png

兩個簇之間最遠的兩個點的距離作為簇之間的距離,採用該距離計算方式得到的聚類比較緊湊。

(3)平均連鎖(Average link)

兩個簇之間的平均距離:

兩個簇之間兩兩點之間距離的平均值,該方式可以有效地排除噪點的影響。

1652713-947bfcf6953de36e.png
image.png

1652713-d00205a4066d64c6.png
image.png

層次聚類小結

層次聚類的優缺點:

(1)簡單,理解容易

(2)合併點/分裂點選擇不太容易

(3)合併/分類的操作不能進行撤銷

(4)大資料集不太適合

(5)執行效率較低Ot*n2),t為迭代次數,n為樣本點數

層次聚類演算法示例

Agglomerative演算法

對於如下資料:

1652713-c9118a21e61a1235.png
image.png

將A到F六個點,分別生成6個簇;

找到當前簇中距離最短的兩個點,這裡我們使用單連鎖的方式來計算距離,發現A點和B點距離最短,將A和B組成一個新的簇,此時簇列表中包含五個簇,分別是{A,B},{C},{D},{E},{F},如下圖所示;

1652713-7b0a7190c6a42763.png
image.png

2 . 找到當前簇中距離最短的兩個點,這裡我們使用單連鎖的方式來計算距離,發現A點和B點距離最短,將A和B組成一個新的簇,此時簇列表中包含五個簇,分別是{A,B},{C},{D},{E},{F},如下圖所示;

3 . 重複步驟二、發現{C}和{D}的距離最短,連線之,然後是簇{C,D}和簇{E}距離最短,依次類推,直到最後只剩下一個簇,得到如下所示的示意圖:

1652713-7e5016f89c27e87e.png
image.png

4 .此時原始資料的聚類關係是按照層次來組織的,選取一個簇間距離的閾值,可以得到一個聚類結果,比如在如下紅色虛線的閾值下,資料被劃分為兩個簇:簇{A,B,C,D,E}和簇{F}

1652713-f35805407bf53e09.png
image.png

Agglomerative聚類演算法的優點是能夠根據需要在不同的尺度上展示對應的聚類結果,缺點同Hierarchical K-means演算法一樣,一旦兩個距離相近的點被劃分到不同的簇,之後也不再可能被聚類到同一個簇,即無法撤銷先前步驟的工作。另外,Agglomerative效能較低,並且因為聚類層次資訊需要儲存在記憶體中,記憶體消耗大,不適用於大量級的資料聚類,下面介紹一種針對大資料量級的聚類演算法BIRCH。

BIRCH演算法

B|RCH演算法(平衡迭代削減聚類法):聚類特徵使用3元組進行一個簇的相關資訊,通過構建滿足分枝因子和簇直徑限制的聚類特徵樹來求聚類,聚類特徵樹其實是個具有兩個引數分枝因子和類直徑的高度平衡樹;分枝因子規定了樹的每個節點的子女的最多個數,而類直徑體現了對這一類點的距離範圍;非葉子節點為它子女的最大特徵值;聚類特徵樹的構建可以是動態過程的,可以隨時根據資料對模型進行更新操作。

BIRCH演算法的全稱是Balanced Iterative Reducing and Clustering using Hierarchies,它使用聚類特徵來表示一個簇,使用聚類特徵樹(CF-樹)來表示聚類的層次結構,演算法思路也是“自底向上”的。該演算法的步驟如下:

(1)構建BIRCH演算法的核心—CF-樹(Clustering Feature Tree),而CF-樹種每個節點代表一個簇的抽象特徵,包含三個資料:簇中資料個數,n個點的線性和,n個資料點的平方和;

(2)從根節點開始,自上而下選擇最近的孩子節點;

到達葉子節點後,檢查距離其最近的CF能否吸收此資料點:

a) 是,更新CF值

b) 否,建立一個新的CF節點,檢查該節點能否加入到當前葉子節點

i. 能,新增到當前葉子節點;

ii. 否,分裂最遠的一對CF節點,按最近距離重新分配其它節點;

(3)更新每個非葉子節點的CF資訊,如果分裂節點,在父節點中插入新的CF節點,直到root;

演算法示意圖如下圖:

1652713-0ad82eb1d2a3fd52.png
image.png

示例

基於scikit包中的建立的模擬資料的API進行資料的建立。使用BIRCH演算法對資料進行資料進行劃分類,比較不同模型數量對演算法的影像的影響。

  1. 匯入模組。
#匯入我們要用的包,包括演算法資料建立模組,演算法評估模組,演算法模組。

from itertools import cycle  
from time import time  
import numpy as np  
import matplotlib as mpl 
import matplotlib.pyplot as plt  
import matplotlib.colors as colors  
from sklearn.preprocessing import StandardScaler  
from sklearn.cluster import Birch 
from sklearn.datasets.samples_generator import make_blobs
  1. 建立資料
#建立呈現3個團狀共3000個樣本資料,樣本有兩個特徵屬性,

## 設定屬性防止中文亂碼  mpl.rcParams['font.sans-serif'] = [u'SimHei']  
mpl.rcParams['axes.unicode_minus'] = False  
## 產生模擬資料  
xx = np.linspace(-22, 22, 10)  
yy = np.linspace(-22, 22, 10)  
xx, yy = np.meshgrid(xx, yy)  
n_centres = np.hstack((np.ravel(xx)[:, np.newaxis],                         
np.ravel(yy)[:, np.newaxis])) 
 #產生10萬條特徵屬性是2,類別是100,符合高斯分佈的資料集 
 X, y = make_blobs(n_samples=100000,n_features=2, centers=n_centres, random_state=28)

原始的資料集如下圖所示:

1652713-0255c5b422f1351f.png
image.png
  1. 模型構建
#建立不同的引數(簇直徑)Birch層次聚類
birch_models = [
    Birch(threshold=1.7, n_clusters=100),
    Birch(threshold=1.7, n_clusters=None)
]
#threshold:簇直徑的閾值,    branching_factor:大葉子個數

#我們也可以加引數來試一下效果,比如加入分支因子branching_factor,給定不同的引數值,看聚類的結果
final_step = [ u'直徑=1.7;n_clusters=100',
               u'直徑=1.7;n_clusters=None'
               ]

plt.figure(figsize=(12, 8), facecolor='w')
plt.subplots_adjust(left=0.02, right=0.98, bottom=0.1, top=0.9)
colors_ = cycle(colors.cnames.keys())
cm = mpl.colors.ListedColormap(colors.cnames.keys())

5.模型的構建



for ind, (birch_model, info) in enumerate(zip(birch_models, final_step)):
    t = time()
    birch_model.fit(X)
    time_ = time() - t
    # 獲取模型結果(label和中心點)
    labels = birch_model.labels_
    centroids = birch_model.subcluster_centers_
    n_clusters = len(np.unique(centroids))
    print("Birch演算法,引數資訊為:%s;模型構建消耗時間為:%.3f秒;聚類中心數目:%d" % (info, time_, len(np.unique(labels))))

   


  1. 畫圖預測模型
 ## 畫圖
    subinx = 221 + ind
    plt.subplot(subinx)
    for this_centroid, k, col in zip(centroids, range(n_clusters), colors_):
        mask = labels == k
        plt.plot(X[mask, 0], X[mask, 1], 'w', markerfacecolor=col, marker='.')
        if birch_model.n_clusters is None:
            plt.plot(this_centroid[0], this_centroid[1], '*', markerfacecolor=col, markeredgecolor='k', markersize=2)
    plt.ylim([-25, 25])
    plt.xlim([-25, 25])
    plt.title(u'Birch演算法%s,耗時%.3fs' % (info, time_))
    plt.grid(False)

畫出原始資料的圖

# 原始資料集顯示
plt.subplot(224)
plt.scatter(X[:, 0], X[:, 1], c=y, s=1, cmap=cm, edgecolors='none')
plt.ylim([-25, 25])
plt.xlim([-25, 25])
plt.title(u'原始資料')
plt.grid(False)
plt.show()

  1. 當簇的直徑為0.5時候,處的數量分別為100和None時候輸出的結果:

Birch演算法,引數資訊為:直徑=0.5;n_clusters=100;模型構建消耗時間為:6.762秒;聚類中心數目:100

Birch演算法,引數資訊為:直徑=0.5;n_clusters=None;模型構建消耗時間為:6.698秒;聚類中心數目:3205

  1. 輸出的圖畫:
1652713-4c71ac69885972be.png
image.png
1652713-f49a9742616b81fc.png
image.png
  1. 當簇的直徑為0.5時候,處的數量分別為100和None時候輸出的結果:

Birch演算法,引數資訊為:直徑=1.7;n_clusters=100;模型構建消耗時間為:2.244秒;聚類中心數目:100

Birch演算法,引數資訊為:直徑=1.7;n_clusters=None;模型構建消耗時間為:2.391秒;聚類中心數目:171

  1. 輸出的結果如下圖所示:
1652713-b147a4ea71102832.png
image.png

BIRCH演算法相比Agglomerative凝聚演算法具有如下特點:

(1)解決了Agglomerative演算法不能撤銷先前步驟的工作的缺陷;

(2)CF-樹只儲存原始資料的特徵資訊,並不需要儲存原始資料資訊,記憶體開銷上更優;

(3)BIRCH演算法只需要遍歷一遍原始資料,而Agglomerative演算法在每次迭代都需要遍歷一遍資料,所以BIRCH在效能也優於Agglomerative;

(4)支援對流資料的聚類,BIRCH一開始並不需要所有的資料;

小結

本章主要介紹了聚類中的其他聚類演算法的思想—層次聚類,著重介紹了演算法—Agglomerative演算法,BIRCH演算法。以上所有的演算法的實現都是依賴於機器學習庫—scikit-learn庫,當然還有其他聚類比如,譜聚類,Apriori關聯分析等都有很好的聚類分析能力。只要掌握其思想,才能對各種聚演算法融會貫通。

相關文章