無監督學習——聚類(clustering)算法應用初探

俗話說:“物以類聚,人以羣分”,在自然科學和社會科學中,存在着大量的分類問題。所謂類,通俗地說,就是指相似元素的集合。
在工業生產過程中,通過分析生產數據及相關數據,將爲我們優化創新、降本增效提供科學依據。以分類需求爲例,通常由人工輔助信息化系統,以及業務專家等,通過大量理論計算,把數據轉化爲圖形、表格,依賴人的智慧把數據分類,打上標籤,爲科研、生產管理提供輔助決策支持。
我們在實際工作中,使用當前信息化資產——歷史生產數據進行大數據人工智能研發工作,通過深度學習,雖然取得很好的結果,不過還有專家對此有疑慮,例如數據準確性問題,物聯網採集的數據“異常”情況、人工分類失誤爲數據打上錯誤的標籤等等,對於這些問題,我引入了聚類算法,用以區分正常數據、不正常數據。
聚類是將對象進行分組的一項任務,使相似的對象歸爲一類,不相似的對象歸爲不同類。聚類分析(Cluster Analysis)是機器學習算法中同數據分類算法同樣重要的算法,數據聚類分析是一種無監督的機器學習方法。

1. DBSCAN聚類

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一個比較有代表性的基於密度的聚類算法。與劃分和層次聚類方法不同,它將簇定義爲密度相連的點的最大集合,能夠把具有足夠高密度的區域劃分爲簇,並可在噪聲的空間數據庫中發現任意形狀的聚類。

1.1. DBSCAN算法原理

DBSCAN算法:將簇定義爲密度相連的點最大集合,能夠把具有足夠高密度的區域劃分爲簇,並且可在噪聲的空間數據集中發現任意形狀的簇。

DBSCAN中的幾個定義:

  • Ε鄰域:給定對象半徑爲Ε內的區域稱爲該對象的Ε鄰域;
  • 直接密度可達:對於樣本集合D,如果樣本點q在p的Ε鄰域內,並且p爲核心對象,那麼對象q從對象p直接密度可達。
  • 密度可達:對於樣本集合D,給定一串樣本點p1,p2….pn,p= p1,q= pn,假如對象pi從pi-1直接密度可達,那麼對象q從對象p密度可達。
  • 密度相連:存在樣本集合D中的一點o,如果對象o到對象p和對象q都是密度可達的,那麼p和q密度相聯;
  • 核心對象:如果給定對象的半徑eps鄰域內樣本數量超過閾值min_samples,則稱爲核心對象;
  • 邊界對象:在半徑eps內點的數量小於min_samples,但是落在覈心點的鄰域內;
  • 噪聲對象:既不是核心對象也不是邊界對象的樣本。

在這裏插入圖片描述
如上圖所示,在衆多樣本點中隨機選中一個(A),圍繞這個被選中的樣本點畫一個圓,規定這個圓的半徑以及圓內最少包含的樣本點,如果在指定半徑內有足夠多的樣本點在內,那麼這個圓圈的圓心就轉移到這個內部樣本點,繼續去圈附近其它的樣本點,類似傳銷一樣,繼續去發展下線。等到這個滾來滾去的圈發現所圈住的樣本點數量少於預先指定的值,就停止了。那麼我們稱最開始那個點爲核心點,如A,停下來的那個點爲邊界點,如B、C,沒得滾的那個點爲離羣點,如N。

Eg: 假設半徑Ε=3,MinPts=3,點p的E鄰域中有點{m,p,p1,p2,o}, 點m的E鄰域中有點{m,q,p,m1,m2},點q的E鄰域中有點{q,m},點o的E鄰域中有點{o,p,s},點s的E鄰域中有點{o,s,s1}.

1.2. 參數

  • 半徑(eps):半徑是最難指定的 ,大了,圈住的就多了,簇的個數就少了;反之,簇的個數就多了,這對我們最後的結果是有影響的。我們這個時候K距離可以幫助我們來設定半徑r,也就是要找到突變點;
  • MinPts(min_samples):半徑中要有的樣本數,就是圈住的點的個數,也相當於是一個密度,一般這個值都是偏小一些,然後進行多次嘗試;
  • metric:採用怎樣的距離計算方式,默認是歐式距離,其他的距離,曼哈頓,切比雪夫等;
  • metric_params:Additional keyword arguments for the metric function,計算距離的方式可能還有其他的參數需求,歐氏距離沒有那就是none;
  • algorithm:{‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}在DBSCAN中我們要找一個點他的近鄰,這有三種算法,而auto會自動挑一個最好的給你,稀疏數據的話,一般就brute了。

其實最最重要的參數是前面兩個,eps和min_samples,而我們主要的調參也就是這些,其他的,保持默認就好。

1.3. SKlearn API及其應用代碼實踐

1.3.1. API:

  • model = sklearn.cluster.DBSCAN(eps_領域大小圓半徑,min_samples_領域內,點的個數的閾值)
  • model.fit(data) 訓練模型
  • model.fit_predict(data) 模型的預測方法

1.3.2. 代碼:

聚類應用案例是解決數據分析過程中,異常數據的問題,包括人工標籤錯誤。

'''
Created on 2019年4月12日

@author: xiaoyw
'''
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from sklearn.cluster import DBSCAN
import math

def init_data():
    data_X = []
    data_Y = []

    data_X ,data_Y = featureSet()

    c = len(data_X)

    row = 0

    xp = []
    while row < c:
        tmp_data = data_X[row]
        P = []
        P.append(tmp_data[17])
        P.append(tmp_data[18])
        tmp_x = np.array(P)
        tmp_x = tmp_x.transpose(1,0)  # 二維轉置
        if len(xp) == 0:
            xp = tmp_x
        else:
            xp = np.concatenate((xp,tmp_x))  # concatenate,第三個參數,1是水平連接,默認是0
        row = row + 1

    return np.array(xp)
    

if __name__ == '__main__':
    colors_ = ['b','r','y','g','m','c','k','pink']

    X = init_data()
    db = DBSCAN(eps = 0.8, min_samples = 10).fit(X) #.fit_predict(X)
    y_pred = db.labels_

    index = [int(tmp) for tmp in y_pred]
    col = []
    k = 0
    for i in index:
        k = i
        if k>=len(colors_):
            k = i%len(colors_)
        # 設置不同的顏色
        col.append(colors_[k]) 
    
    plt.scatter(X[:, 0], X[:, 1], c=col)  #y_pred)
    plt.show()

1.3.3. 運行效果

效果一:eps = 0.5、min_samples = 20
在這裏插入圖片描述

效果二:eps = 0.8、min_samples = 10
在這裏插入圖片描述
通過上述效果來分析,異常數據屬於小概率樣本,這樣需要擴大核心密度E領域的半徑,縮小密度,也就是min_samples 的參數值。

算法優缺點

優點 缺點
可以發現任意形狀的聚類 隨着數據量的增加,對I/O、內存的要求也隨之增加。如果密度分佈不均勻,聚類效果較差。

2. Birch聚類

BIRCH的全稱是利用層次方法的平衡迭代規約和聚類(Balanced Iterative Reducing and Clustering Using Hierarchies)。

2.1. Birch算法原理

BIRCH算法利用了一個樹結構來幫助我們快速的聚類,這個數結構類似於平衡B+樹,一般將它稱之爲聚類特徵樹(Clustering Feature Tree,簡稱CF Tree)。這顆樹的每一個節點是由若干個聚類特徵(Clustering Feature,簡稱CF)組成。從下圖我們可以看看聚類特徵樹是什麼樣子的:每個節點包括葉子節點都有若干個CF,而內部節點的CF有指向孩子節點的指針,所有的葉子節點用一個雙向鏈表鏈接起來。
在這裏插入圖片描述
如上圖所示:N = 5
LS=(3+2+4+4+3,4+6+5+7+8)=(16,30)
SS =(32+22+42+42+32,42+62+52+72+82)=(54,190)
在這裏插入圖片描述
對於上圖中的CF Tree,限定了B=7,L=5, 也就是說內部節點最多有7個CF(CF90下的圓),而葉子節點最多有5個CF(CF90到CF94)。葉子節點是通過雙向鏈表連通的。

2.2. SKlearn Birch算法函數

2.2.1. 主要參數(詳細參數)

  • n_clusters :聚類的目標個數。(可選)
  • threshold :掃描半徑(個人理解,官方說法比較繞口),設置小了分類就多。
  • branches_factor:每個節點中CF子集羣的最大數量,默認爲50。

2.2.2. 主要屬性

labels_ :每個數據點的分類

2.3. 應用案例代碼實現

2.3.1. 代碼

colors_ = ['b','r','y','g','m','c','k','pink']
birch = Birch(n_clusters = 18)
##訓練數據
y_pred = birch.fit_predict(X)

print("CH指標:", metrics.calinski_harabaz_score(X, y_pred))

##繪圖
index = [int(tmp) for tmp in y_pred]
col = []
for i in index:
    col.append(colors_[i]) 
plt.scatter(X[:, 0], X[:, 1], c=col)#y_pred)
plt.show()

與上節重複代碼省略。

2.3.2. 效果

在這裏插入圖片描述
分層效果還是挺好的,但是識別異常數據未達到期望。

3. k-means聚類

k-means算法屬於無監督學習的一種聚類算法,其目的爲:在不知數據所屬類別及類別數量的前提下,依據數據自身所暗含的特點對數據進行聚類。對於聚類過程中類別數量k的選取,需要一定的先驗知識,也可根據“類內間距小,類間間距大“(一種聚類算法的理想情況)爲目標進行實現。

3.1. K-Means算法原理

K-means算法模型,一種流行的聚類算法是首先對可能的聚類定義一個代價函數,聚類算法的目標是尋找一種使代價最小的劃分。

在這類範例中,聚類任務轉化爲一個優化問題,目標函數是一個從輸入(X,d)和聚類方案 C = (C1,C2,…,Ck)映射到正實數(即損失值)的函數。

給定這樣一個目標函數,我們將其表示爲 G,對於給定的一個輸入(X,d),聚類算法的目標被定義爲尋找一種聚類 C 使 G((X,d),C)最小。

  • 首先,我們選擇一些類/組來使用並隨機地初始化它們各自的中心點。要想知道要使用的類的數量,最好快速地查看一下數據,並嘗試識別任何不同的分組。中心點是與每個數據點向量相同長度的向量,在下面的圖形中是“X”;
  • 每個數據點通過計算點和每個組中心之間的距離進行分類,然後將這個點分類爲最接近它的組;
  • 基於這些分類點,我們通過取組中所有向量的均值來重新計算組中心;
  • 對一組迭代重複這些步驟。你還可以選擇隨機初始化組中心幾次,然後選擇那些看起來對它提供了最好結果的來運行。

在這裏插入圖片描述
如圖所示,數據樣本用圓點表示,每個簇的中心點用叉叉表示。[1]

3.1.1. 聚類中心個數K

聚類中心的個數K需要事先給定,但在實際中這個 K 值的選定是非常難以估計的,很多時候,事先並不知道給定的數據集應該分成多少個類別才最合適。這個過程會是一個漫長的調試過程,我們通過設置一個[k, k+n]範圍的K類值,然後逐個觀察聚類結果,最終決定該使用什麼K值對當前數據集是最佳的

在實際情況中,往往是對特定的數據集有對應一個最佳的K值,而換一個數據集,可能原來的K值效果就會下降。但是同一個項目中的一類數據,總體上來說,通過一個抽樣小數據集確定一個最佳K值後,對之後的所有K值都能獲得較好的效果

3.1.2. 初始聚類中心(質心)的選擇

剛開始時是原始數據,雜亂無章,沒有label,看起來都一樣,都是綠色的

Kmeans需要人爲地確定初始聚類中心,不同的初始聚類中心可能導致完全不同的聚類結果。在實際使用中我們往往不知道我們的待聚類樣本中哪些是我們關注的label,人工事先指定質心基本上是不現實的,在大多數情況下我們採取隨機產生聚類質心這種策略

假設數據集可以分爲兩類,令K = 2,隨機在座標上選兩個點,作爲兩個類的中心點(聚類質心)

3.1.3. 確定了本輪迭代的質心後,將餘下的樣本點根據距離度量標準進行歸類

這一步也非常直觀,計算樣本點和所有質心的“距離”,選取“距離”最小(argmin)的那個質心作爲該樣本所屬的類別。

這裏要注意的是,特徵空間中兩個實例點的距離是兩個實例點相似程度的反映,高維向量空間點的距離求解,可以泛化爲Lp距離公式,它在不同的階次數中分爲不同的形式

K-Means聚類算法的優勢在於它的速度非常快,因爲我們所做的只是計算點和羣中心之間的距離;它有一個線性複雜度O(n)。

另一方面,K-Means也有幾個缺點。首先,你必須選擇有多少組/類。這並不是不重要的事,理想情況下,我們希望它能幫我們解決這些問題,因爲它的關鍵在於從數據中獲得一些啓示。K-Means也從隨機選擇的聚類中心開始,因此在不同的算法運行中可能產生不同的聚類結果。因此,結果可能是不可重複的,並且缺乏一致性。其他聚類方法更加一致。

3.2. SKlearn K-Means應用代碼

與第1章節相同代碼,省略。
把數據放到三維空間中,包括時序、位移、力三個特徵數據。

if __name__ == '__main__':

    X = init_data()
    est = KMeans(n_clusters=20).fit(X)
    labels = est.labels_
    
    colors_ = ['b','r','y','g','m','c','k','pink','orange']

    index = [int(tmp) for tmp in labels]
    col = []
    k = 0
    for i in index:
        k = i
        if k>=len(colors_):
            k = i%len(colors_)
    
        col.append(colors_[k]) 
        
    fig = plt.figure()
    plt.clf()
    ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)

    plt.cla()

    ax.scatter(X[:, 2], X[:, 0], X[:, 1], c=col)

    ax.w_xaxis.set_ticklabels([])
    ax.w_yaxis.set_ticklabels([])
    ax.w_zaxis.set_ticklabels([])
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    
    plt.show()  

效果不理想,請看下圖。
在這裏插入圖片描述

注:繪製3D圖形,出現環境上的問題“ImportError: No module named mpl_toolkits”
找到mpl_toolkits文件夾,在下邊建一個文件:_init_.py

try:
import(‘pkg_resources’).declare_namespace(name)
except ImportError:
pass # must not have setuptools

由於本人的水平有限,開始試驗了K-Means、Birch等算法,都是很不理想,接着,重點研究、試驗DBSCAN算法,但是,比較擔心數據密度不夠,將會影響分析效果。最後總結如下,需要進一步驗證。

首先,異常數據、離羣點都是小樣本,數據密度很低。這樣,在接手別人數據集時,可以通過DBSCAN聚類打一次標籤試試,和原數據標籤有多大差異。

歡迎讀者反饋交流。

參考:
[1]. 《各類聚類(clustering)算法初探》 博客園/長路 Andrew.Hann 2018年1月
[2]. 《異常點檢測算法小結》 博客園/劉建平Pinard 2018年7月
[3]. 《DBSCAN聚類算法——機器學習(理論+圖解+python代碼)》 CSDN博客 風弦鶴 2018年7月
[4]. 《Python實現聚類算法(6種算法)》 CSDN博客 周小董 2019年3月
[5]. 《使用Python Matplotlib繪圖並輸出圖像到文件中的實踐》 CSDN博客 肖永威 2018年4月
[6]. Visualizing DBSCAN Clustering

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章