一文讀懂異常檢測 LOF 算法(Python代碼)

2022-01-12 數據挖掘工程師

上一篇介紹:一文讀懂層次聚類(Python代碼)

本篇介紹一個經典的異常檢測算法:局部離群因子(Local Outlier Factor),簡稱LOF算法

背景

Local Outlier Factor(LOF)是基於密度的經典算法(Breuning et. al. 2000), 文章發表於 SIGMOD 2000, 到目前已經有 3000+ 的引用。

在 LOF 之前的異常檢測算法大多是基於統計方法的,或者是借用了一些聚類算法用於異常點的識別(比如 ,DBSCAN,OPTICS)。這些方法都有一些不完美的地方:

基於統計的方法:通常需要假設數據服從特定的概率分布,這個假設往往是不成立的。聚類方法:通常只能給出 0/1 的判斷(即:是不是異常點),不能量化每個數據點的異常程度。

相比較而言,基於密度的LOF算法要更簡單、直觀。它不需要對數據的分布做太多要求,還能量化每個數據點的異常程度(outlierness)。

下面開始正式介紹LOF算法。

LOF 算法

首先,基於密度的離群點檢測方法有一個基本假設:非離群點對象周圍的密度與其鄰域周圍的密度類似,而離群點對象周圍的密度顯著不同於其鄰域周圍的密度。

什麼意思呢?看下面圖片感受下。

集群 C1 包含了 400 多個點,集群 C2 包含 100 個點。C1 和 C2 都是一類集群點,區別是 C1 位置比較集中,或者說密度比較大。而像 o1、o2點均為異常點,因為基於我們的假設,這兩個點周圍的密度顯著不同於周圍點的密度。

LOF 就是基於密度來判斷異常點的,通過給每個數據點都分配一個依賴於鄰域密度的離群因子 LOF,進而判斷該數據點是否為離群點。 如果

那麼什麼是LOF呢?

了解LOF前,必須先知道一下3個基本概念,因為LOF是基於這幾個概念而來的。

1. k鄰近距離

在距離數據點

比如上圖中,距離點

這裡的距離計算可以採用歐式距離、漢明距離、馬氏距離等等。比如用歐式距離的計算公式如下:

這裡的重點是找到第

2. k距離領域

以點

還是上圖所示,假設k=4,那麼點 1-6 均是鄰域範圍內的點。

3. 可達距離

這個可達距離大家需要留意點,點

這裡計算

4. 局部可達密度

先給出公式,然後再說明密度的含義。

數據點

5. 局部異常因子

根據局部可達密度的定義,如果一個數據點跟其他點比較疏遠的話,那麼顯然它的局部可達密度就小。但LOF算法衡量一個數據點的異常程度,並不是看它的絕對局部密度,而是看它跟周圍鄰近的數據點的相對密度。

這樣做的好處是可以允許數據分布不均勻、密度不同的情況。局部異常因子即是用局部相對密度來定義的。數據點

LOF算法流程

了解了 LOF 的定義以後,整個算法也就顯而易見了:

對於每個數據點,計算它與其它所有點的距離,並按從近到遠排序;

對於每個數據點,找到它的 k-nearest-neighbor,計算 LOF 得分;

如果LOF值越大,說明越異常,反之如果越小,說明越趨於正常。

LOF優缺點

優點

LOF 的一個優點是它同時考慮了數據集的局部和全局屬性。異常值不是按絕對值確定的,而是相對於它們的鄰域點密度確定的。當數據集中存在不同密度的不同集群時,LOF表現良好,比較適用於中等高維的數據集。

缺點

LOF算法中關於局部可達密度的定義其實暗含了一個假設,即:不存在大於等於 k 個重複的點。

當這樣的重複點存在的時候,這些點的平均可達距離為零,局部可達密度就變為無窮大,會給計算帶來一些麻煩。在實際應用時,為了避免這樣的情況出現,可以把 k-distance 改為 k-distinct-distance,不考慮重複的情況。或者,還可以考慮給可達距離都加一個很小的值,避免可達距離等於零。

另外,LOF 算法需要計算數據點兩兩之間的距離,造成整個算法時間複雜度為

Python 實現 LOF

有兩個庫可以計算LOF,分別是PyOD和Sklearn,下面分別介紹。

使用pyod自帶的方法生成200個訓練樣本和100個測試樣本的數據集。正態樣本由多元高斯分布生成,異常樣本是使用均勻分布生成的。

訓練和測試數據集都有 5 個特徵,10% 的行被標記為異常。並且在數據中添加了一些隨機噪聲,讓完美分離正常點和異常點變得稍微困難一些。

from pyod.utils.data import generate_data
import numpy as np
X_train, y_train, X_test, y_test = \
        generate_data(n_train=200,
                      n_test=100,
                      n_features=5,
                      contamination=0.1,
                      random_state=3) 
X_train = X_train * np.random.uniform(0, 1, size=X_train.shape)
X_test = X_test * np.random.uniform(0,1, size=X_test.shape)

PyOD

下面將訓練數據擬合了 LOF 模型並將其應用於合成測試數據。

在 PyOD 中,有兩個關鍵方法:decision_function 和 predict。

decision_function:返回每一行的異常分數predict:返回一個由 0 和 1 組成的數組,指示每一行被預測為正常 (0) 還是異常值 (1)
from pyod.models.lof import LOF
clf_name = 'LOF'
clf = LOF()
clf.fit(X_train)

test_scores = clf.decision_function(X_test)

roc = round(roc_auc_score(y_test, test_scores), ndigits=4)
prn = round(precision_n_scores(y_test, test_scores), ndigits=4)

print(f'{clf_name} ROC:{roc}, precision @ rank n:{prn}')
>> LOF ROC:0.9656, precision @ rank n:0.8

可以通過 LOF 模型方法查看 LOF 分數的分布。在下圖中看到正常數據(藍色)的分數聚集在 1.0 左右。離群數據點(橙色)的得分均大於 1.0,一般高於正常數據。

Sklearn

在scikit-learn中實現 LOF 進行異常檢測時,有兩種模式選擇:異常檢測模式 (novelty=False) 和 novelty檢測模式 (novelty=True)。

在異常檢測模式下,只有fit_predict生成離群點預測的方法可用。可以使用negative_outlier_factor_屬性檢索訓練數據的異常值分數,但無法為未見過的數據生成分數。模型會根據contamination參數(默認值為 0.1)自動選擇異常值的閾值。

import matplotlib.pyplot as plt

detector = LOF()
scores = detector.fit(X_train).decision_function(X_test)

sns.distplot(scores[y_test==0], label="inlier scores")
sns.distplot(scores[y_test==1], label="outlier scores").set_title("Distribution of Outlier Scores from LOF Detector")
plt.legend()
plt.xlabel("Outlier score")

在novelty檢測模式下,只有decision_function用於生成異常值可用。fit_predict方法不可用,但predict方法可用於生成異常值預測。

clf = LocalOutlierFactor(novelty=True)
clf = clf.fit(X_train)
test_scores = clf.decision_function(X_test)

test_scores = -1*test_scores

roc = round(roc_auc_score(y_test, test_scores), ndigits=4)
prn = round(precision_n_scores(y_test, test_scores), ndigits=4)

print(f'{clf_name} ROC:{roc}, precision @ rank n:{prn}')

該模式下模型的異常值分數被反轉,異常值的分數低於正常值。

實戰系列的全部完整代碼可見:https://github.com/xiaoyusmd/PythonDataScience

原創不易,歡迎點讚、在看。

關於LOF的原論文可以在公眾號回覆:LOF 獲取。

參考:

https://pub.towardsai.net/an-in-depth-guide-to-local-outlier-factor-lof-for-outlier-detection-in-python-5a6f128e5871https://zhuanlan.zhihu.com/p/28178476https://mp.weixin.qq.com/s/SHYNjtqCo-Ue3lezdVk1jAhttps://www.cnblogs.com/xzydn/p/14408758.html

相關焦點

  • 異常檢測算法速覽(Python代碼)
    一、異常檢測簡介異常檢測是通過數據挖掘方法發現與數據集分布不一致的異常數據,也被稱為離群點、異常值檢測等等。1.1 異常檢測適用的場景異常檢測算法適用的場景特點有:(1)無標籤或者類別極不均衡;(2)異常數據跟樣本中大多數數據的差異性較大;(3)異常數據在總體數據樣本中所佔的比例很低。
  • Python異常值檢測——孤立森林算法
    本節繼續分享時序數據異常值檢測算法,今天分享的是孤立森林算法(Isolation Forest),孤立森林是基於Ensemble的快速異常檢測方法,具有線性時間複雜度和高精準度,是符合大數據處理要求的state-of-the-art算法。
  • Python異常值檢測——kNN算法
    異常值檢驗方法有很多,針對不同數據特點,時間序列數據和截面數據的檢測方法不完全相同,其時常要考慮到數據特性,本次主要介紹相關的時序數據異常值檢測算法。 3.得到異常點檢測圖
  • 使用Python進行異常檢測
    異常檢測有很多用例,包括信用卡欺詐檢測、故障機器檢測、基於異常特徵的硬體系統檢測、基於醫療記錄的疾病檢測都是很好的例子,除此之外也還有很多的用例。在本文中,我們將使用Python從頭開始實現異常檢測算法。公式和過程與我之前解釋過的其他機器學習算法相比,我們使用的異常檢測算法要簡單得多。該算法使用均值和方差來計算每個訓練數據的概率。
  • 一文教你讀懂 Python 中的異常信息
    下圖顯示了各個組成部分:藍框:Traceback 的最後一行為錯誤消息行。其中包含引發的異常名稱。綠框:異常名稱後面是錯誤消息。此消息通常包含有用的信息,用於了解引發異常的原因。如果通過調用 greet()引發異常,則會列印一個簡單的問候語。只要提供了正確的輸入,此代碼就沒有任何可能導致異常被引發的錯誤。
  • 一文讀懂Python中的異常處理
    (點擊上方公眾號,可快速關注一起學Python)來源: 公眾號—哎媽呀Bug  連結:http://mp.weixin.qq.com/s/xBrVKxBCCQK29c6Na7CXcg異常處理在任何一門程式語言裡都是值得關注的一個話題
  • 一文搞懂Python錯誤和異常
    寫Python代碼的小夥伴不可避免地會遇到代碼執行錯誤和異常,這次就來詳細且不失通俗地總結一下python中的錯誤和異常。
  • 一文讀懂遺傳算法工作原理(附Python實現)
    你也許在想:這句話和遺傳算法有什麼關係?其實遺傳算法的整個概念就基於這句話。讓我們用一個基本例子來解釋 :我們先假設一個情景,現在你是一國之王,為了讓你的國家免於災禍,你實施了一套法案:你選出所有的好人,要求其通過生育來擴大國民數量。這個過程持續進行了幾代。
  • 目標檢測必須要OpenCV?10行Python代碼也能實現,親測好用!
    大數據文摘出品編譯:朱一輝、雪清、小魚短短10行代碼就可以實現目標檢測?!本文作者和他的團隊構建了一個名為ImageAI 的Python庫,集成了現今流行的深度學習框架和計算機視覺庫。本文將手把手教你構建自己的第一個目標檢測應用,而且文摘菌已經幫你踩過坑了,親測有效!
  • 基於機器學習算法的時間序列價格異常檢測(附代碼)
    異常檢測也稱為異常值檢測,是一種數據挖掘過程,用於確定數據集中發現的異常類型並確定其出現的詳細信息。 在當今世界,由於大量數據無法手動標記異常值,自動異常檢測顯得至關重要。 自動異常檢測具有廣泛的應用,例如欺詐檢測,系統健康監測,故障檢測以及傳感器網絡中的事件檢測系統等。
  • Python異常處理
    問題描述大家在使用python語言寫代碼的時候難免會出一些錯誤,而才入門的朋友們往往不知道是哪裡出了錯或者不知道自己錯在哪裡、什麼錯誤。所以我們要知道是哪行代碼出錯,其次室錯誤的類型是什麼,錯在那個細節,逐步分析,從而解決錯誤並改正。
  • 孤立森林:大數據背景下的最佳異常檢測算法
    在這篇文章中,我會總結這個算法,以及其歷史,並分享我實現的代碼來解釋為什麼iForest是現在針對大數據而言最好的異常檢測算法。  為什麼iForest是現在處理大數據最好的異常檢測算法  總結來說,它在同類算法中有最好的表現。iForest在多種數據集上的ROC表現和精確度都比大多數其他的異常檢測算法要好。
  • 異常檢測怎麼做,試試孤立隨機森林算法
    在該任務中,孤立森林算法是簡單而有效的選擇。 本文內容包括: 介紹異常檢測; 異常檢測的用例; 孤立森林是什麼; 用孤立森林進行異常檢測; 用 Python 實現。
  • 獨家 | 一文讀懂Adaboost
    早在2001年Paul Viola和Michael Jones利用Adaboost組合基於Haar特徵的弱分類器,使得人臉檢測速度大幅度提升。近年來,在Kaggle等公開的競賽中,Adaboost算法也被廣泛採用,而且大部分時候表現都不錯,比如將adaboost用在垃圾郵件檢測、手寫數字識別等項目中。
  • Python Robotics代碼詳解:Dijkstra 搜索算法
    PythonRobotics是由Atsushi Sakai, Daniel Ingram等人建立的開原始碼軟體平臺:https://github.com/redglassli/PythonRobotics#a-algorithm收集了機器人學當下主流算法的python代碼(基於python3),為了幫助初學者明白各個算法的基本原理,詳細介紹見(PythonRobotics
  • python學習筆記(9): try...except 異常捕獲
    目前正在學習python基礎,同時也在leetcode-cn上刷算法題目,有興趣的同學一起哦。最近學習了python如何處理異常,發現一篇比較好的文章,整理了一下,供大家學習研究。一、什麼是異常?當無法正確處理程序時就會出現異常。當異常發生時我們需要捕獲處理它,否則程序會終止執行。
  • [翻譯]不平衡數據集的One-Class分類算法
    識別數據中的異常值被稱為異常值或異常檢測,專注於這個問題的一個機器學習子領域被稱為one-class分類。這些是無監督學習算法,試圖對「正常」樣本進行建模,以便將新樣本分類為正常或異常(例如異常值)。 One-class分類算法可用於類分布嚴重偏斜的二分類任務。
  • 一文讀懂 Bellman-Ford 算法
    (點擊上方公眾號,可快速關注)轉自:劉毅https://www.61mon.com/index.php/archives/195/好文投稿
  • 一篇文章幫你搞定Python異常處理
    =1+'str'什麼是異常異常就是程序運行時發生錯誤的信號,在python中,錯誤觸發的異常如下Python中異常種類在python中不同的異常可以用不同的類型(python中統一了類與類型,類型即類)去標識,不同的類對象標識不同的異常,一個異常標識一種錯# 觸發IndexErrorl=['run1','aa']
  • 一文讀懂Python裝飾器
    打開APP 一文讀懂Python裝飾器 工程師3 發表於 2018-04-28 10:48:00 先來看一個簡單例子,雖然實際代碼可能比這複雜很多