數據分析與挖掘(十九)------挖掘建模之離羣點檢測

一、引言

就餐飲企業而言,經常會碰到如下問題。

1)如何根據客戶的消費記錄檢測是否爲異常刷卡消費?

2)如何檢測是否有異常訂單?

這類異常問題可以通過離羣點檢測來解決。

離羣點檢測的任務是發現與大部分其他對象顯著不同的對象。大部分數據挖掘方法都是將這種差異信息視爲噪聲而丟棄,然而在一些應用中,罕見的數據可能蘊含着更大的研究價值。

在上面的數據散佈圖中,離羣點遠離其他數據點。因爲離羣點的屬性值明顯偏離期望的或常見的屬性值,所以離羣點檢測也稱爲偏差檢測。

(1)離羣點檢測應用領域:詐騙檢測、貸款審批、電子商務、網絡入侵、天氣預報等

(2)離羣點的成因:數據來源於不同的類、自然變異、數據測量和收集誤差

(3)離羣點的類型:

 

分類標準

分類名稱

分類描述

從數據範圍

全局離羣點和局部離羣點

從整體來看,某些對象沒有離羣特徵,但是從局部來看,卻顯示了一定的離羣性。

從數據類型

數值型離羣點和分類型離羣點

這是以數據集的屬性類型進行劃分的

從屬性的個數

一維離羣點和多維離羣點

一個對象可能有一個或多個屬性

二、離羣點檢測方法

 

常用離羣點檢測方法

 

離羣點檢測方法

方法描述

方法評估

基於統計

大部分的基於統計的離羣點檢測方法是構建一個概率分佈模型,並計算對象符合該模型的概率,把具有低概率的對象視爲離羣點。

基於統計模型的離羣點檢測方法的前提是必須知道數據集服從什麼分佈;對於高維數據,檢驗效果可能會很差

基於鄰近度

通常可以在數據對象之間定義鄰近性度量,把遠離大部分點的對象視爲離羣點

簡單,二維或三維的數據可以做散點圖觀察,大數據集不適用;對參數選擇敏感;具有全局閾值,不能處理具有不同密度區域的數據集。

基於密度

考慮數據集可能存在不同密度區域這一事實,從基於密度的觀點分析,離羣點是在低密度區域中的對象。一個對象的離羣點得分是該對象周圍密度的逆。

給出了對象是離羣點的定量度量,並且即使數據具有不同的區域也能夠很好處理,大數據集不適用,參數選擇是困難的。

基於聚類

一種利用聚類檢測離羣點的方法是丟棄遠離其他簇的小簇;另一種更系統的方法,首先聚類所以對象,然後評估對象屬於簇的程度(離羣點得分)

基於聚類技術來發現離羣點可能是高度有效的;聚類算法產生的簇的質量對該算法產生的離羣點的質量影響非常大。

 

  • 基於統計模型的離羣點檢測方法需要滿足統計學原理,如果分佈已知,則檢驗可能非常有效。

  • 基於鄰近度的離羣點檢測方法比統計學方法更一般、更容易使用,因爲確定數據集有意義的鄰近度量比確定它的統計分佈更容易。

  • 基於密度的離羣點檢測與基於鄰近度的離羣點檢測密切相關,因爲密度常用鄰近度定義:一種是定義密度爲到K個最鄰近的平均距離的倒數,如果該距離小,則密度高;另一種是使用DBSCAN聚類算法,一個對象周圍的密度等於該對象指定距離d內對象的個數。

三、基於模型的離羣點檢測方法

 

  • 通過估計概率分佈的參數來建立一個數據模型。如果一個數據對象不能很好地同該模型擬合,即如果它很可能不服從該分佈,則它是一個離羣點。

  • 在某些情況下是很難建立模型的。例如,因爲數據的統計分佈未知或沒有訓練數據可用。在這種情況下,可以考慮其他不需要建立模型的檢測方法。

(1)一元正態分佈中的離羣點檢測

N(0,1)的數據對象出現在該分佈的兩邊尾部的機會很小,因此可以用它作爲檢測數據對象是否爲離羣點的基礎,數據對象落在三倍標準差中心區域之外的概率僅有0.0027.

(2)混合模型的離羣點檢測

  • 混合模型是一種特殊的統計模型,他使用若干統計分佈對數據建模。每一個分佈對應一個簇,而每個分佈的參數提供對應簇的描述,通常使用中心和發散描述。

  • 混合模型將數據看作從不同的概率分佈得到的觀測值的集合。概率分佈可以是任何分佈,但是通常是多元正態的,因爲這種類型的分佈不難理解,容易從數學上 進行處理,並且已經證明在很多情況下都能產生好的結果。這種類型的分佈可以對橢圓簇建模。

  • 總的來說,混合模型數據產生的過程爲:給定幾個類型相同但參數不同的分佈,隨機地選取一個分佈並由它產生一個對象。重複該過程m次,其中m是對象的個數。

  • 對於混合模型,每個分佈描述一個不同的組,即一個不同的簇。通過使用統計方法,可以由數據估計這些分佈的參數,從而描述這些分佈(簇)。也可以識別哪個對象屬於哪個簇。然而,混合模型只是給出具體對象屬於特定簇的概率。

  • 聚類時,混合模型方法假定數據來自混合概率分佈,並且每個簇可以使用這些分佈之一識別。同樣,對於離羣點檢測,用兩個分佈的混合模型建模,一個分佈爲正常數據,而另一個爲離羣點。

  • 聚類和離羣點檢測的目標都是估計分佈的參數,以最大化數據的總似然。

  • 一種離羣點檢測的常用的簡單的方法:先將所有數據對象放入正常數據集,這時離羣點集爲空集;再用一個迭代過程將數據對象從正常數據集轉移到離羣點集,該轉移能提高數據的總似然。

  • 因爲正常數據對象的數量比離羣點對象的數量大很多,因此當一個數據對象移動到離羣點集後,正常數據對象的分佈變化不大。在這種情況下,每個正常數據對象的總似然的貢獻保持不變。此外,如果假定離羣點服從均勻分佈,則移動到離羣點集的每一個數據對象對離羣點的似然貢獻一個固定的量。這樣,當一個數據對象移動到離羣點集時,數據總似然的改變粗略地等於該數據對象在均勻分佈下地概率減去該數據對象在正常數據點地分佈下的概率。然而,離羣點由這樣一些數據對象組成。這樣,數據對象在均勻分佈下的概率比正常數據對象分佈下的概率高。

四、基於聚類的離羣點檢測方法

聚類分析用於發現局部強相關的對象組,而異常檢測用來發現不與其他對象強相關的對象。因此,聚類分析非常自然地可以用於離羣點檢測。以下爲兩種基於聚類的離羣點檢測方法。

(1)丟棄遠離其他簇的小簇(丟棄小於某個最小閾值的所有簇)

這個方法可以和其他任何聚類技術一起使用,但是需要最小簇大小和小簇與其他簇之間距離的閾值。而且這種方案對簇個數的選擇高度敏感,使用這個方案很難將離羣點得分附加到對象上。

在上圖中,聚類簇K=2,可以直觀地看出其中一個包含5個對象的小簇遠離大部分對象,可以視爲離羣點。

(2)基於原型的聚類

基於原型的聚類是另一種更系統的方法。首先聚類所有對象,然後評估對象屬於簇的程度(離羣點得分)。在這種方法中,可以用對象到它的簇中心的距離來度量屬於簇的程度。特別地,如果刪除一個對象導致該目標的顯著改進,則可將該對象視爲離羣點。例如,在K-均值算法中,刪除遠離其相關簇中心的對象能夠顯著地改進該簇地誤差平方和(SEE)。

對於基於原型的聚類,主要有兩種方法評估對象屬於簇的程度(離羣點得分):一是度量對象到簇原型的距離,並用它作爲該對象的離羣點得分;二是考慮到簇具有不同的密度,可以度量簇到原型的相對距離,相對距離是點到質心的距離與簇中所有點到質心的距離的中位數之比。

上圖中,如果選擇聚類簇數K=3,則對象A,B,C應分別屬於距離它們最近的簇,但相對於簇內的其他對象,這三個點又分別遠離各自的簇,所以有理由懷疑對象A,B,C是離羣點。

診斷步驟如下:

1)進行聚類。選擇聚類算法(如K-Means算法),將樣本集聚爲K簇,並找到各簇的質心。

2)計算各對象到它的最近質心的距離。

3)計算各對象到它的最近質心的相對距離。

4)與給定的閾值作比較。

如果某對象距離大於該閾值,則認爲該對象是離羣點。

基於聚類的離羣點檢測的改進:

1)離羣點對初始聚類的影響:通過聚類檢測離羣點時,離羣點會影響聚類結果。爲了處理該問題,可以使用方法:對象聚類,刪除離羣點,對象再次聚類(這個不能保證產生最優結果)

2)還有一種更復雜的方法:取一組不能很好地擬合任何簇的特殊對象,這組對象代表潛在的離羣點。隨着聚類過程的進展,簇在變化。不再強屬於任何簇的對象被添加到潛在的離羣點集合;測試當前在該集合中的對象,如果它現在強屬於一個簇,就可以將它從潛在的離羣點集合中移除。聚類過程結束時還留在該集合中的點被分類爲離羣點(這種方法也不能保證產生最優解,甚至不比前面的簡單算法好,在使用相對距離計算離羣點得分時,這個問題特別嚴重)。

對象是否被認爲是離羣點可能依賴於簇的個數(如k很大時的噪聲簇)。該問題也沒有簡單的答案。一種策略是對於不同的簇個數重複該分析。另一種方法是找出大量小簇,其想法如下:

1)較小的簇傾向於更加凝聚;

2)如果存在大量小簇時,一個對象是離羣點,則它多半是一個真正的離羣點。

不利的一面是一組離羣點可能形成小簇從而逃避檢測。

實例:離散點檢測

利用表5-14的數據進行聚類分析,並計算各個樣本到各自聚類中心的距離

#-*- coding: utf-8 -*-
#使用K-Means算法聚類消費行爲特徵數據

import numpy as np
import pandas as pd


#參數初始化
inputfile = '../data/consumption_data.xls' #銷量及其他屬性數據
k = 3 #聚類的類別
threshold = 2 #離散點閾值
iteration = 500 #聚類最大循環次數
data = pd.read_excel(inputfile, index_col = 'Id') #讀取數據
data_zs = 1.0*(data - data.mean())/data.std() #數據標準化

from sklearn.cluster import KMeans
model = KMeans(n_clusters = k, n_jobs = 4, max_iter = iteration) #分爲k類,併發數4
model.fit(data_zs) #開始聚類

#標準化數據及其類別
r = pd.concat([data_zs, pd.Series(model.labels_, index = data.index)], axis = 1)  #每個樣本對應的類別
r.columns = list(data.columns) + [u'聚類類別'] #重命名錶頭


norm = []
for i in range(k): #逐一處理
  norm_tmp = r[['R', 'F', 'M']][r[u'聚類類別'] == i]-model.cluster_centers_[i]
  norm_tmp = norm_tmp.apply(np.linalg.norm, axis = 1) #求出絕對距離
  norm.append(norm_tmp/norm_tmp.median()) #求相對距離並添加


norm = pd.concat(norm) #合併


import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #用來正常顯示中文標籤
plt.rcParams['axes.unicode_minus'] = False #用來正常顯示負號
norm[norm <= threshold].plot(style = 'go') #正常點

discrete_points = norm[norm > threshold] #離羣點
discrete_points.plot(style = 'ro')

for i in range(len(discrete_points)): #離羣點做標記
  id = discrete_points.index[i]
  n = discrete_points.iloc[i]
  plt.annotate('(%s, %0.2f)'%(id, n), xy = (id, n), xytext = (id, n))

plt.xlabel(u'編號')
plt.ylabel(u'相對距離')
plt.show()

輸出如下圖所示距離誤差圖

分析距離誤差圖可以得到,如果距離閾值設置爲2,那麼所給的數據中有8個離散點,在聚類的時候這些數據應該剔除。

 

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