Local Outlier Factor

      在〈Local Outlier Factor〉中尚無留言

LOF 演算法全名為Local Outlier Factor,局部離群因子。Outlier[ˋaʊt͵laɪɚ] 是離群值的意思。這是用來判斷異常檢測的方法。LOF 是基於密度的經典演算法,此演算法發表於 SIGMOD 2000。

檢測到異常時,並不是全然要將其值去除,有時反而是要抓住其值。比如地震儀平時在一定範圍震動,突然發生異常大幅震盪時,並不是將其值去除,而是立馬發佈地震警告,記錄震幅並轉換震度。

安裝套件

pip install scikit-learn

產生訓練資料

首先使用 numpy 的 randn 產生 2 行 100 組標準正態分佈亂數。標準常態分佈就是大部份的值都在 0 附近,然後往正及往負慢慢減少,如下代碼及圖示。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#產生訓練資料
np.random.seed(1)
inliers = np.random.randn(100, 2)
sns.set_style('whitegrid')
ax1=plt.subplot(1,2,1)
ax1.set_xlim((-5,5))
ax1.set_ylim((0,30))
sns.histplot(inliers[:,0], kde=True)

sns.set_style('whitegrid')
ax2=plt.subplot(1,2,2)
ax2.set_xlim((-5,5))
ax2.set_ylim((0,30))
sns.histplot(inliers[:,1], kde=True)
plt.show()

分成二組

將inliers 分別加3及減3,然後將二組合併,產生分離的二群組。

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
# 產生訓練資料
inliers = np.random.randn(100, 2)
inliers = np.r_[inliers + 3, inliers - 3]
x=inliers[:,0]
y=inliers[:,1]
plt.scatter(x, y, s=5, c='k')
plt.xlim(-6,6)
plt.ylim(-6,6)
plt.show()

加入離群資料點

使用 np.random.uniform() 加入 20 點離群資料。uniform 是在指定的範圍中隨機採樣。不過這 20 點不一定會全部離群。底下的 np.r_ 會將 outliers 加到 inliers 之後。

import numpy as np
import matplotlib.pyplot as plt
# 產生訓練資料
np.random.seed(1)
inliers = np.random.randn(100, 2)
inliers = np.r_[inliers + 3, inliers - 3]
outliers = np.random.uniform(low=-6, high=6, size=(20, 2))
data=np.r_[inliers, outliers]
x=data[:,0]
y=data[:,1]
plt.scatter(x, y, s=3,c='k')
plt.xlim(-6,6)
plt.ylim(-6,6)
plt.savefig("lof_5.jpg")
plt.show()

偵測離群點

使用 LOF 產生 lof 物件,參數 n_neighbors 為 k-distance(第 k 距離),使用預設值 20,其說明請參照
K-Mean 詳解

參數 contamination[kən͵tæməˋneʃən] 是污染,在此為異常點的比例,使用預設的 ‘auto’ 即可。

然後 lof.fit_predict(data)即可偵測每個點的離群狀況 : y_pred。y_pred為一list資料,代表每個點的狀況,1表示未離群,-1 表示離。所以可以使用 np.ones()跟 y_pred相減,讓未離群的點變成0,而離群點變成 2, 再用此資料決定圓圈的半徑。

另外 lof.negative_outlier_factor_ 為每一點的離群分數,負值愈大,代表離群的機會愈大。

在繪制點散圖時 (plt.scatter),facecolors 是圓點的填滿色,’none’ 表示為空心圓,edgecolors 則為圓的邊框顏色。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor as LOF
# 產生訓練資料
#np.random.seed(1)
inliers = np.random.randn(100, 2)
inliers = np.r_[inliers + 3, inliers - 3]
outliers = np.random.uniform(low=-6, high=6, size=(20, 2))
data=np.r_[inliers, outliers]
lof = LOF(n_neighbors=20, contamination='auto') # 使用 fit_predict 進行偵測 y_pred = lof.fit_predict(data)
scores=lof.negative_outlier_factor_
print(y_pred)
print(scores) radius=np.ones(len(y_pred)) radius-=y_pred x=data[:,0] y=data[:,1] plt.scatter(x, y, s=3,c='k') #離群點畫圓圈 plt.scatter(x, y, s=100*radius, edgecolors='r', facecolors='none') plt.xlim(-7,7) plt.ylim(-7,7) plt.savefig("lof_6.jpg") plt.show()

LOF演算法

為什麼 LOF可以這麼輕易的算出離群點呢,這有蠻複雜的演算法,目前因沒啥空檔來撰寫,請大家到網路上Google,待本人比較有空時再來撰寫。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *