手把手教你如何利用K均值聚類實現異常值的識別!

2021-02-20 Python大本營

來源 | 數據分析1480(ID:lsxxx2011)

前言

在上一期的異常值識別《KNN除了可以做分類和預測,還知道它可以識別異常值嗎?》中,我們詳細分享了如何使用K近鄰的方法完成數據中異常值的查詢。但該方法的最大缺陷在於計算複雜度高,對於大數據而言,識別異常數據將會消耗較長的時間。本期將從K均值聚類的角度,幫助大家理解該方法在異常值識別過程中的優勢!(本文涉及的代碼可以在文末連結中下載)

首先,藉助於Python隨機生成兩組二維數據,用於後文的實戰。為了能夠更加直觀地洞察該數據,我們將其繪製成散點圖。

# 導入第三方包
import numpy as np
import matplotlib.pyplot as plt

# 隨機生成兩組二元正態分布隨機數
np.random.seed(1234)
mean1 = [0.5, 0.5]
cov1 = [[0.3, 0], [0, 0.1]]
x1, y1 = np.random.multivariate_normal(mean1, cov1, 5000).T

mean2 = [0, 8]
cov2 = [[0.8, 0], [0, 2]]
x2, y2 = np.random.multivariate_normal(mean2, cov2, 5000).T

# 繪製兩組數據的散點圖
plt.rcParams['axes.unicode_minus'] = False
plt.scatter(x1, y1)
plt.scatter(x2, y2)
# 顯示圖形
plt.show()

如上圖所示,圖中藍色和紅色之間形成鮮明的簇,其中每個簇內包含5000個數據。如果數據中存在異常點,目測藍色的簇可能會包含更多異常,因為數據點相對分散一些。

K均值聚類算法的思路非常通俗易懂,就是不斷地計算各樣本點與簇中心之間的距離,直到收斂為止,其具體的步驟如下:

(1)從數據中隨機挑選k個樣本點作為原始的簇中心。

(2)計算剩餘樣本與簇中心的距離,並把各樣本標記為離k個簇中心最近的類別。

(3)重新計算各簇中樣本點的均值,並以均值作為新的k個簇中心。

(4)不斷重複(2)和(3),直到簇中心的變化趨於穩定,形成最終的k個簇。

也許上面的4個步驟還不足以讓讀者明白Kmeans的執行過程,可以結合下圖更進一步地理解其背後的思想。

如上圖所示,通過9個子圖對Kmeans聚類過程加以說明:子圖1,從原始樣本中隨機挑選兩個數據點作為初始的簇中心,即子圖中的兩個五角星;子圖2,將其餘樣本點與這兩個五角星分別計算距離(距離的度量可選擇歐氏距離、曼哈頓距離等),然後將每個樣本點劃分到離五角星最近的簇,即子圖中按虛線隔開的兩部分;子圖3,計算兩個簇內樣本點的均值,得到新的簇中心,即子圖中的五角星;子圖4,根據新的簇中心,繼續計算各樣本與五角星之間的距離,得到子圖5的劃分結果和子圖6中新的簇內樣本均值;以此類推,最終得到理想的聚類效果,如子圖9所示,圖中的五角星即最終的簇中心點。

在上文中,我們生成了兩組隨機數據,從圖中一眼就可以看出需聚為兩類,然而在實際應用中,很多數據都無法通過可視化或直覺判斷聚類的個數(即K值)。但這不代表沒有方法鎖定最佳的K值,在書《從零開始學Python數據分析與挖掘》的第十五章介紹了「拐點法」、「輪廓係數法」和「間隔統計量法」,感興趣的朋友可以去了解一下。這裡就使用書中的自定義函數,測試一下K應該對應的值:


X = pd.DataFrame(np.concatenate([np.array([x1, y1]), np.array([x2, y2])], axis=1).T)
X.rename(columns = {0:'x1',1:'x2'}, inplace = True)

k_SSE(X, 10)

如上圖所示,當簇的個數為2時形成了一個明顯的「拐點」,因為 K值從1到2時,折線的斜率都比較大,但是值為3時斜率突然就降低了很多,並且之後的簇對應的斜率都變動很小。所以,合理的值應該為2,與模擬的兩個簇數據相吻合。

使用K均值聚類的思想識別數據中的異常點還是非常簡單的,具體步驟如下:

利用「拐點法」、「輪廓係數法」、「間隔統計量法」或者「經驗法」確定聚類的個數;將距離跟閾值相比較,如果其大於閾值則認為是異常,否則正常;

為了驗證我們在前文所說的的直覺(「目測藍色的簇可能會包含更多異常」),接下來通過構造自定義函數,計算簇內的每個點與簇中心的距離,並判斷其是否超過閾值的異常點(閾值的計算是《Python數據清洗--異常值識別與處理01》為中介紹的sigma法)。下方代碼可能有點長,但仔細閱讀並查看對應的注釋內容,相信你一定能夠理解代碼的思想。

def kmeans_outliers(data, clusters, is_scale = True):
    
    kmeans = KMeans(n_clusters=clusters)
    
    cluster_res = []

    
    if is_scale:
        std_data = scale(data) 
        kmeans.fit(std_data)  
        
        labels = kmeans.labels_
        
        centers = kmeans.cluster_centers_

        for label in set(labels):
            
            diff = std_data[np.array(labels) == label,] - \
                   - np.array(centers[label])
            dist = np.sum(np.square(diff), axis=1)
            
            UL = dist.mean() + 3*dist.std()
            
            OutLine = np.where(dist > UL, 1, 0) 
            raw_data = data.loc[np.array(labels) == label,]
            new_data = pd.DataFrame({'Label':label,'Dist':dist,'OutLier':OutLine})
            
            raw_data.index = new_data.index = range(raw_data.shape[0])
            
            cluster_res.append(pd.concat([raw_data,new_data], axis = 1))
    else:
        kmeans.fit(data)  
        
        labels = kmeans.labels_
        
        centers = kmeans.cluster_centers_

        for label in set(labels):
            
            diff = np.array(data.loc[np.array(labels) == label,]) - \
                   - np.array(centers[label])

            dist = np.sum(np.square(diff), axis=1)
            UL = dist.mean() + 3*dist.std()
            OutLine = np.where(dist > UL, 1, 0)
            raw_data = data.loc[np.array(labels) == label,]
            new_data = pd.DataFrame({'Label':label,'Dist':dist,'OutLier':OutLine})
            raw_data.index = new_data.index = range(raw_data.shape[0])
            cluster_res.append(pd.concat([raw_data,new_data], axis = 1))
    
    return pd.concat(cluster_res)


res = kmeans_outliers(X,2,False)


sns.lmplot(x="x1", y="x2", hue='OutLier', data=res,
           fit_reg=False, legend=False)
plt.legend(loc='best')
plt.show()


如上圖所示,藍色的點即為異常點。從藍色點的分布來看,上面那一簇所對應的異常點比較多(與之前的預判一致),而下面簇的異常點較少,且全部集中在散點的右側。

OK,今天的內容就分享到這裡,下一期將會跟大家分享如何基於密度聚類,針對非球形簇的數據做異常點檢測。如果你有任何問題,歡迎在公眾號的留言區域表達你的疑問。

代碼連結:

https://pan.baidu.com/s/1tNG3IGRx7HsVqzjelHDSNg

提取碼:yew1

(*本文為AI科技大本營轉載文章,轉載請聯繫原作者)

2019 AI開發者大會」 除了邀請國內外一線公司重磅嘉賓外,還邀請到了亞馬遜首席科學家@李沐,他將於9月5日親授「深度學習實訓營」,通過動手實操,幫助開發者全面了解深度學習的基礎知識和開發技巧。原價1099元,目前福利價199元!且現場贈送價值85元《動手學深度學習》一本。

掃碼添加小助手,回覆:大會,加入2019 AI開發者大會福利群,每周更新技術福利,還有不定期的抽獎活動~

相關焦點

  • k均值聚類算法原理和(TensorFlow)實現(無師自通)
    顧名思義,k均值聚類是一種對數據進行聚類的技術,即將數據分割成指定數量的幾個類,揭示數據的內在性質及規律。
  • 有了K均值聚類,為什麼還需要DBSCAN聚類算法?
    使用K均值的另一個困難是需要指定聚類的數量(「k」)以便使用。很多時候不會預先知道什麼是合理的k值。DBSCAN的優點在於,不必指定使用它的聚類數量。需要的只是一個計算值之間距離的函數,以及一些將某些距離界定為「接近」的指令。在各種不同的分布中,DBSCAN也比K均值產生更合理的結果。
  • 人工智慧算法|K均值聚類算法Python實現
    以下是K均值法的python代碼實現。程序使用的工具包括numpy和matplotlib,其中numpy是一個用於處理多維數組的庫,而Matplotlib 則用於繪製二維圖形。3    clusterDict = minDistance(dataSet,centroidList)  # 第一次聚類迭代    newVar = getVar(clusterDict, centroidList)  #獲得均方誤差值,通過新舊均方誤差來獲得迭代終止條件    oldVar = -0.0001  #開始時均方誤差值初始化為-0.0001    print
  • 圖解機器學習-聚類(k均值)
    聚類的相似性度量歐氏距離(Euclidean Distance)是聚類相似性計算距離的一種方法,來自幾何數學中計算兩點間的距離公式。兩個n維向量a(x11,x12,…,x1n)與 b(x21,x22,…,x2n)間的歐氏距離如下圖:K均值聚類(K-means) 算法K均值算法偽代碼,來自周志華《機器學習》圖解分析
  • 機器學習算法實踐 K均值聚類的實用技巧
    在本文中,他詳細介紹了一種稱為 K-Means Clustering(k均值聚類)的算法,其中包括如何衡量算法效果,以及如何確定你需要生成的數據段集數量。雷鋒網編譯整理,更多AI開發技術文章,關注AI研習社(微信號:okweiwu)。Bilal Mahmood:我們最常做的分析之一,便是在數據中提取模式。 比方說,某公司的客戶可被劃分入哪些細分市場?
  • 機器學習算法實踐之K均值聚類的實用技巧
    在本文中,他詳細介紹了一種稱為 K-Means Clustering(k均值聚類)的算法,其中包括如何衡量算法效果,以及如何確定你需要生成的數據段集數量。雷鋒網編譯整理,更多AI開發技術文章,關注AI研習社(微信號:okweiwu)。Bilal Mahmood:我們最常做的分析之一,便是在數據中提取模式。 比方說,某公司的客戶可被劃分入哪些細分市場?
  • 算法雜貨鋪——k均值聚類(K-means)
    本文首先介紹聚類的基礎——距離與相異度,然後介紹一種常見的聚類算法 ——k均值和k中心點聚類,最後會舉一個實例:應用聚類方法試圖解決一個在體育界大家頗具爭議的問題——中國男足近幾年在亞洲到底處於幾流水平。4.2、相異度計算      在正式討論聚類前,我們要先弄清楚一個問題:如何定量計算兩個可比較元素間的相異度。
  • SAS用K-Means 聚類最優k值的選取和分析
    K-均值中的「 K」代表簇數。距離量度將確定兩個元素之間的相似性,並將影響簇的形狀。通常,歐幾裡得距離將用於K-Means聚類歐幾裡得距離是「普通」直線。它是歐氏空間中兩點之間的距離。 K-Means算法如何工作?
  • 不足 20 行 Python 代碼,高效實現 k-means 均值聚類算法!
    k-means均值算法雖然是聚類算法中比較簡單的一種,卻包含了豐富的思想內容,非常適合作為初學者的入門習題。關於 k-means 均值聚類算法的原理介紹、實現代碼,網上有很多,但運行效率似乎都有點問題。今天稍微有點空閒,寫了一個不足20行的 k-means 均值聚類算法,1萬個樣本平均耗時20毫秒(10次均值)。同樣的數據樣本,網上流行的算法平均耗時3000毫秒(10次均值)。
  • R語言做K均值聚類的一個簡單小例子
    /k均值聚類是一種比較常用的聚類方法,R語言裡做k均值聚類比較常用的函數是kmeans(),需要輸入3個參數,第一個是聚類用到的數據,第二個是你想將數據聚成幾類k,第三個參數是nstarthttps://www.datanovia.com/en/lessons/k-means-clustering-in-r-algorith-and-practical-examples
  • 使用Python進行K均值聚類
    有時我們只是想知道我們的數據是如何組織起來的這樣我們就能知道數據是如何組織起來的。聚類意味著對一組對象進行分組。K-means聚類是無監督學習的一部分,我們使用的是未標記的數據集,這個算法會自動為我們將數據分組成聚類。它是目前最流行、應用最廣泛的聚類算法之一。它用於各種應用程式,例如市場細分,圖像細分等。
  • 機器學習十大經典算法之K-Means聚類算法
    聚類介紹聚類在機器學習,數據挖掘,模式識別,圖像分析以及生物信息等領域有廣泛的應用。聚類是把相似的對象通過靜態分類的方法分成不同的組別或者更多的子集(subset),這樣讓在同一個子集中的成員對象都有相似的一些屬性,常見的包括在坐標系中更加短的空間距離(一般是歐式距離)等。
  • 聚類算法之Kmeans
    Kmeans算法,也叫k均值算法,顧名思義,其核心思想也就是根據均值來更新簇心。其具體算法流程如下:1、隨機初始化k個簇心2、對於每個樣本,根據其到各簇心的距離(這裡用歐式距離),將其標註為距離最近的簇心類別。
  • K-Means聚類講解:算法和Sklearn的實現(附代碼)
    K-Means聚類是機器學習領域中最強大的聚類算法之一。他的原因比較簡單,但得出的結果也非常準確。聚類是理解數據集的非常重要的方式,因此在本文中,我們將討論什麼是聚類,為什麼需要聚類以及什麼是k-means聚類。
  • k-means聚類算法原理總結
    小批量處理的k-means聚類算法5. k值的選取6. k-means聚類算法不適用的幾個場景7. k-means與knn區別8. 小結聚類算法性能度量的文章提到若簇類相似度好簇間的相似度差,則聚類算法的性能較好。我們基於此定義k-means聚類算法的目標函數: 其中
  • 機器學習之SKlearn(scikit-learn)的K-means聚類算法
    在工程應用中,用python手寫代碼來從頭實現一個算法的可能性非常低,這樣不僅耗時耗力,還不一定能夠寫出構架清晰,穩定性強的模型。更多情況下,是分析採集到的數據,根據數據特徵選擇適合的算法,在工具包中調用算法,調整算法的參數,獲取需要的信息,從而實現算法效率和效果之間的平衡。而sklearn,正是這樣一個可以幫助我們高效實現算法應用的工具包。
  • k-means聚類算法從入門到精通
    小批量處理的k-means聚類算法5. k值的選取6. k-means聚類算法不適用的幾個場景7. k-means與knn區別8. 小結聚類算法性能度量的文章提到若簇類相似度好簇間的相似度差,則聚類算法的性能較好。我們基於此定義k-means聚類算法的目標函數: 其中
  • 吳恩達《Machine Learning》精煉筆記 8:聚類 KMeans 及其 Python實現
    本文中首先介紹的是聚類中的K均值算法,包含:算法思想圖解K-Meanssklearn實現Python實現無監督學習unsupervised learning無監督學習簡介聚類和降維是無監督學習方法,在無監督學習中數據是沒有標籤的。
  • 數字油畫製作中的k均值聚算法
    1數值實驗 在MATLAB2009a的環境下,應用AkMTI-CCI算法和傳統k均值算法,對圖1中的RGB圖像進行顏色聚類.分別取聚類數k=6和k=12,將AkMTI-CCI算法和傳統的k均值算法兩種算法分別運行10次.1)由算法運行時間表(表1)可見,10次實驗中傳統k均值算法收斂速度波動較大,而AkMTI-CCI算法收斂速度比較穩定;且傳統k均值算法平均收斂速度均大於
  • python之kmeans數據聚類算法
    圖3kmeans實現邏輯:需要輸入待聚類的數據和欲聚類簇數k1.隨機生成k個初始點作為質心>2.將數據集中的數據按照距離質心的遠近分到各個簇中3.對每個簇的數據求平均值,作為新的質心,重複上一步,直到所有的簇不再改變k是聚類個數,可以根據我們的經驗給數值,也可以通過程序初步預測k設置為多少對聚類最準確。