1. 程式人生 > 實用技巧 >【21年01月DW打卡】Task01 - 異常檢測概述 (常用場景、常見方法、PyOD工具庫+KNN異常檢測示例)

【21年01月DW打卡】Task01 - 異常檢測概述 (常用場景、常見方法、PyOD工具庫+KNN異常檢測示例)

異常檢測概述

1、什麼是異常檢測

異常檢測(Outlier Detection),顧名思義,是識別與正常資料不同的資料,與預期行為差異大的資料。

識別如信用卡欺詐,工業生產異常,網路流裡的異常(網路侵入)等問題,針對的是少數的事件。

1.1 異常的類別

點異常:指的是少數個體例項是異常的,大多數個體例項是正常的,例如正常人與病人的健康指標;

上下文異常:指的是在特定情境下個體例項是異常的,在其他情境下都是正常的,例如在特定時間下的溫度突然上升或下降,在特定場景中的快速信用卡交易;

群體異常:指的是在群體集合中的個體例項出現異常的情況,而該個體例項自身可能不是異常,例如社交網路中虛假賬號形成的集合作為群體異常子集,但子集中的個體節點可能與真實賬號一樣正常。

1.2 異常檢測任務分類

有監督:訓練集的正例和反例均有標籤

無監督:訓練集無標籤

半監督:在訓練集中只有單一類別(正常例項)的例項,沒有異常例項參與訓練

1.3 異常檢測場景

  • 故障檢測

  • 物聯網異常檢測

  • 欺詐檢測

  • 工業異常檢測

  • 時間序列異常檢測

  • 視訊異常檢測

  • 日誌異常檢測

  • 醫療日常檢測

  • 網路入侵檢測

2.1 傳統方法

2.1.1 基於統計學的方法 (如正態分佈)

統計學方法對資料的正常性做出假定。它們假定正常的資料物件由一個統計模型產生,而不遵守該模型的資料是異常點。統計學方法的有效性高度依賴於對給定資料所做的統計模型假定是否成立。

異常檢測的統計學方法的一般思想是:學習一個擬合給定資料集的生成模型,然後識別該模型低概率區域中的物件,把它們作為異常點。

即利用統計學方法建立一個模型,然後考慮物件有多大可能符合該模型。

假定輸入資料集為\(\{x^{(1)}, x^{(2)}, ..., x^{(m)}\}\),資料集中的樣本服從正態分佈,即\(x^{(i)}\sim N(\mu, \sigma^2)\),我們可以根據樣本求出引數\(\mu\)\(\sigma\)

\(\mu=\frac 1m\sum_{i=1}^m x^{(i)}\)

\(\sigma^2=\frac 1m\sum_{i=1}^m (x^{(i)}-\mu)^2\)

2.1.2 線性模型 (PCA降維)

典型的如PCA方法,Principle Component Analysis是主成分分析,簡稱PCA。它的應用場景是對資料集進行降維。降維後的資料能夠最大程度地保留原始資料的特徵(以資料協方差為衡量標準)。
PCA的原理是通過構造一個新的特徵空間,把原資料對映到這個新的低維空間裡。PCA可以提高資料的計算效能,並且緩解"高維災難"。

2.1.3 基於相似度的方法

  這類演算法適用於資料點的聚集程度高、離群點較少的情況。同時,因為相似度演算法通常需要對每一個數據分別進行相應計算,所以這類演算法通常計算量大,不太適用於資料量大、維度高的資料。
  基於相似度的檢測方法大致可以分為三類:

  • 基於叢集(簇)的檢測,如DBSCAN等聚類演算法。
      聚類演算法是將資料點劃分為一個個相對密集的“簇”,而那些不能被歸為某個簇的點,則被視作離群點。這類演算法對簇個數的選擇高度敏感,數量選擇不當可能造成較多正常值被劃為離群點或成小簇的離群點被歸為正常。因此對於每一個數據集需要設定特定的引數,才可以保證聚類的效果,在資料集之間的通用性較差。聚類的主要目的通常是為了尋找成簇的資料,而將異常值和噪聲一同作為無價值的資料而忽略或丟棄,在專門的異常點檢測中使用較少。
      聚類演算法的優缺點:
    (1)能夠較好發現小簇的異常;
    (2)通常用於簇的發現,而對異常值採取丟棄處理,對異常值的處理不夠友好;
    (3)產生的離群點集和它們的得分可能非常依賴所用的簇的個數和資料中離群點的存在性;
    (4)聚類演算法產生的簇的質量對該演算法產生的離群點的質量影響非常大。
  • 基於距離的度量,如k近鄰演算法。
      k近鄰演算法的基本思路是對每一個點,計算其與最近k個相鄰點的距離,通過距離的大小來判斷它是否為離群點。在這裡,離群距離大小對k的取值高度敏感。如果k太小(例如1),則少量的鄰近離群點可能導致較低的離群點得分;如果k太大,則點數少於k的簇中所有的物件可能都成了離群點。為了使模型更加穩定,距離值的計算通常使用k個最近鄰的平均距離。
      k近鄰演算法的優缺點:
    (1)簡單;
    (2)基於鄰近度的方法需要O(m2)時間,大資料集不適用;
    (3)對引數的選擇敏感;
    (4)不能處理具有不同密度區域的資料集,因為它使用全域性閾值,不能考慮這種密度的變化。
  • 基於密度的度量,如LOF(區域性離群因子)演算法。
      區域性離群因子(LOF)演算法與k近鄰類似,不同的是它以相對於其鄰居的區域性密度偏差而不是距離來進行度量。它將相鄰點之間的距離進一步轉化為“鄰域”,從而得到鄰域中點的數量(即密度),認為密度遠低於其鄰居的樣本為異常值。
    LOF(區域性離群因子)演算法的優缺點:
    (1)給出了對離群度的定量度量;
    (2)能夠很好地處理不同密度區域的資料;
    (3)對引數的選擇敏感。

2.2 整合方法

整合是提高資料探勘演算法精度的常用方法。整合方法將多個演算法或多個基檢測器的輸出結合起來。其基本思想是一些演算法在某些子集上表現很好,一些演算法在其他子集上表現很好,然後整合起來使得輸出更加魯棒。整合方法與基於子空間方法有著天然的相似性,子空間與不同的點集相關,而整合方法使用基檢測器來探索不同維度的子集,將這些基學習器集合起來。

常用的整合方法有Feature bagging,孤立森林等。

feature bagging

與bagging法類似,只是物件是feature。


bagging有以下特徵:

  • 結合策略,隨機取樣,平行計算
  • 最終結果:迴歸採用平均法,分類採用投票法

參考:

孤立森林

孤立森林假設我們用一個隨機超平面來切割資料空間,切一次可以生成兩個子空間。然後我們繼續用隨機超平面來切割每個子空間並迴圈,直到每個子空間只有一個數據點為止。直觀上來講,那些具有高密度的簇需要被切很多次才會將其分離,而那些低密度的點很快就被單獨分配到一個子空間了。孤立森林認為這些很快被孤立的點就是異常點。

用四個樣本做簡單直觀的理解,d是最早被孤立出來的,所以d最有可能是異常。

2.3 機器學習

在有標籤的情況下,可以使用樹模型(gbdt,xgboost等)進行分類,缺點是異常檢測場景下資料標籤是不均衡的,但是利用機器學習演算法的好處是可以構造不同特徵。

3、異常檢測常用開源庫

Scikit-learn:

Scikit-learn是一個Python語言的開源機器學習庫。它具有各種分類,迴歸和聚類演算法。也包含了一些異常檢測演算法,例如LOF和孤立森林。

官網:https://scikit-learn.org/stable/

PyOD:

Python Outlier Detection(PyOD)是當下最流行的Python異常檢測工具庫,其主要亮點包括:

  • 包括近20種常見的異常檢測演算法,比如經典的LOF/LOCI/ABOD以及最新的深度學習如對抗生成模型(GAN)和整合異常檢測(outlier ensemble)
  • 支援不同版本的Python:包括2.7和3.5+;支援多種作業系統:windows,macOS和Linux
  • 簡單易用且一致的API只需要幾行程式碼就可以完成異常檢測,方便評估大量演算法
  • 使用JIT和並行化(parallelization)進行優化,加速演算法執行及擴充套件性(scalability),可以處理大量資料

​ ——https://zhuanlan.zhihu.com/p/58313521

4、練習

0 學習pyod庫基本操作

(如何生成toy example,瞭解訓練以及預測的api)

參考資料:

1 安裝

pip install pyod

2 Model Save & Load

from joblib import dump, load

# save the model
dump(clf, 'clf.joblib')
# load the model
clf = load('clf.joblib')

3 KNN 示例 (pyod演算法)

完整示例:knn_example.py

# 匯入模型
from __future__ import division
from __future__ import print_function

import os
import sys

from pyod.models.knn import KNN
from pyod.utils.data import generate_data
from pyod.utils.data import evaluate_print
from pyod.utils.example import visualize

# 使用生成樣本資料pyod.utils.data.generate_data():

contamination = 0.1  # percentage of outliers
n_train = 200  # number of training points
n_test = 100  # number of testing points

X_train, y_train, X_test, y_test = generate_data(
    n_train=n_train, n_test=n_test, contamination=contamination)

# 初始化pyod.models.knn.KNN檢測器,擬合模型,然後進行預測。

# train kNN detector
clf_name = 'KNN'
clf = KNN()
clf.fit(X_train)

# get the prediction labels and outlier scores of the training data
y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
y_train_scores = clf.decision_scores_  # raw outlier scores

# get the prediction on the test data
y_test_pred = clf.predict(X_test)  # outlier labels (0 or 1)
y_test_scores = clf.decision_function(X_test)  # outlier scores

# 使用ROC和Precision @ Rank n評估預測pyod.utils.data.evaluate_print()。

from pyod.utils.data import evaluate_print
# evaluate and print the results
print("\nOn Training Data:")
evaluate_print(clf_name, y_train, y_train_scores)
print("\nOn Test Data:")
evaluate_print(clf_name, y_test, y_test_scores)
# 在培訓和測試資料上檢視示例輸出。
On Training Data:
KNN ROC:1.0, precision @ rank n:1.0

On Test Data:
KNN ROC:1.0, precision @ rank n:1.0


D:\Anaconda3\lib\site-packages\pyod\utils\data.py:189: FutureWarning: behaviour="old" is deprecated and will be removed in version 0.8.0. Please use behaviour="new", which makes the returned datasets in the order of X_train, X_test, y_train, y_test.
  FutureWarning)
# 通過視覺化所有示例中包含的功能來生成視覺化。
visualize(clf_name, X_train, y_train, X_test, y_test, y_train_pred,
              y_test_pred, show_figure=True, save_figure=True)

X_train[-10:]
array([[ 0.84016461,  0.06656394],
       [-5.57375282,  1.37676822],
       [ 5.23859832, -4.82192459],
       [-4.22173717, -5.25316645],
       [ 5.08503672,  0.63032474],
       [-3.92404899,  2.02719173],
       [-4.50324719,  0.90196511],
       [-4.35362171, -5.33498611],
       [-4.40478978, -5.18715487],
       [-3.23294036,  5.98499889]])
y_train[-10:]
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
X_test[-10:]
array([[ 1.77725564, -5.83322458],
       [ 1.74348338,  4.96599509],
       [-2.21369417,  3.49754018],
       [ 4.76301902, -2.86414014],
       [ 3.27055399,  2.15382358],
       [-3.92860999, -2.1021253 ],
       [-4.75998038,  5.96154543],
       [-0.44913256,  3.13486298],
       [-2.51104944,  1.85939204],
       [-4.91472967, -2.82909014]])
y_test[-10:]
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

5、小結