1. 程式人生 > 其它 >異常檢測 - 基於統計學的方法

異常檢測 - 基於統計學的方法

技術標籤:AnomalyDetection資料分析python機器學習統計學

github 地址:連結

目錄

1異常檢測—基於統計學的方法

1.1引數方法

假定正常的資料物件被一個以 Θ \Theta Θ為引數的引數分佈產生。該引數分佈的概率密度函式 f ( x , Θ ) f(x,\Theta) f(x,Θ)給出物件 x x x被該分佈產生的概率。該值越小, x x

x越可能是異常點。

圖片名稱
  1. 基於正態分佈的一元異常點檢測

    • x ( i ) ∼ N ( μ , σ 2 ) x^{(i)}\sim N(\mu, \sigma^2) x(i)N(μ,σ2)
    • p ( x ) = 1 2 π σ e x p ( − ( x − μ ) 2 2 σ 2 ) p(x)=\frac 1{\sqrt{2\pi}\sigma}exp(-\frac{(x-\mu)^2}{2\sigma^2}) p(x)=2π σ1exp(2σ2(xμ)2)
    • 黃色線條是N(o,1)標準正態分佈的概率密度函式圖,我們看到,越靠近均值0的部分,概率密度越大,說明資料落在此點範圍內的可能性更大
    • 藍色線條是N(0,0.5)分佈,可以看到,分佈方差 σ \sigma σ越大,資料集中程度越大
    • 引數方法,就是先假設原始資料,服從一個分佈函式,然後通過最大似然估計等方法,通過實際樣本的資料,計算出這個分佈的引數( μ , σ \mu,\sigma μ,σ),從而給定新資料的時候,可以根據通過分佈函式p(x),計算出一個概率值,從而判斷新資料是否是異常樣本
  2. 分量彼此獨立的多元分佈

    • p ( x ) = ∏ j = 1 n p ( x j ; μ j , σ j 2 ) = ∏ j = 1 n 1 2 π σ j e x p ( − ( x j − μ j ) 2 2 σ j 2 ) p(x)=\prod_{j=1}^n p(x_j;\mu_j,\sigma_j^2)=\prod_{j=1}^n\frac 1{\sqrt{2\pi}\sigma_j}exp(-\frac{(x_j-\mu_j)^2}{2\sigma_j^2})
      p(x)=j=1np(xj;μj,σj2)=j=1n2π σj1exp(2σj2(xjμj)2)
  3. 分量存在相關關係的多元高斯分佈

    • p ( x ) = 1 ( 2 π ) n 2 ∣ Σ ∣ 1 2 exp ⁡ ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) p(x)=\frac{1}{(2 \pi)^{\frac{n}{2}}|\Sigma|^{\frac{1}{2}}} \exp \left(-\frac{1}{2}(x-\mu)^{T} \Sigma^{-1}(x-\mu)\right) p(x)=(2π)2nΣ211exp(21(xμ)TΣ1(xμ))

1.2非引數方法

非引數方法,就是不假設資料服從某個分佈,而是通過樣本的實際分佈來作為整體的分佈,然後當給定新樣本後,我們根據此分佈,來判斷新樣本的出現概率,並根據此概率值,決策此樣本是否是異常樣本

圖片名稱
  • 如上圖的直方圖所示,可以看到直方圖的高度越高,說明在此區間內的樣本量越大,因此可以將方塊的面積,作為概率密度,面積的倒數就可以作為異常度
  • 新樣本落在面積比較小的方塊內,異常度就越大
  • 難點就在於方塊(箱)的數量選擇,太多,則異常點易落入正常範圍,太少,則正常值易誤判為異常值。

2HBOS方法實踐

HBOS方法簡介:連結
注意:前提假設是樣本的特徵之間相互獨立

2.1pyod中hbos函式簡介

pyod使用簡介:連結

classpyod.models.hbos.HBOS(n_bins=10, alpha=0.1, tol=0.5, contamination=0.1)
  • 引數介紹
    • n_bins 分割槽也就是分箱的數量
    • alpha 正則化引數
    • tol 決定樣本落在箱外概率的一個引數
    • contamination 資料集的異常值比例
  • 屬性
    • bin_edges_ 箱子的劃分邊界
    • hist_ 直方圖的密度
    • 其他引數同一般模型

2.2hbos例項

2.2.1生成資料

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import matplotlib.font_manager

from pyod.utils.data import generate_data,get_outliers_inliers

# 生成二維隨機資料
X_train, Y_train = generate_data(n_train=200,train_only=True, n_features=2)

# 拆分出異常資料和正常資料
x_outliers, x_inliers = get_outliers_inliers(X_train,Y_train)

# 繪製生成的資料圖
F1 = X_train[:,[0]].reshape(-1,1)
F2 = X_train[:,[1]].reshape(-1,1)
plt.scatter(F1,F2)
plt.xlabel('F1')
plt.ylabel('F2') 
plt.show()
圖片名稱

2.2.2使用HBOS進行預測

from pyod.models.hbos import HBOS

outlier_fraction = 0.1#異常值比例
abod = HBOS(contamination=outlier_fraction)#生成模型
abod.fit(X_train)#訓練模型
score = abod.decision_scores_# 注意異常得分是負的
score = score * -1
score.shape
(200,)

2.2.3預測結果

y_pred = abod.predict(X_train)# 預測訓練樣本的標籤
from sklearn.metrics import classification_report
print(classification_report(y_true=Y_train,y_pred=y_pred))
              precision    recall  f1-score   support

         0.0       0.99      1.00      1.00       180
         1.0       1.00      0.95      0.97        20

    accuracy                           0.99       200
   macro avg       1.00      0.97      0.99       200
weighted avg       1.00      0.99      0.99       200

2.2.4生成熱力圖

n_inliers = len(x_inliers)
n_outliers = len(x_outliers)
#生成熱力圖的座標點
xx , yy = np.meshgrid(np.linspace(-10, 10, 200), np.linspace(-10, 10, 200))
# 根據百分比生成
threshold = -abod.threshold_

# 得到每個座標點的異常值得分
Z = abod.decision_function(np.c_[xx.ravel(), yy.ravel()]) * -1
Z = Z.reshape(xx.shape)
plt.figure(figsize=(10, 10))
#將正常樣本區域繪製成藍色
plt.contourf(xx, yy, Z, levels = np.linspace(Z.min(), threshold, 10),cmap=plt.cm.Blues_r)
#繪製決策曲線
a = plt.contour(xx, yy, Z, levels=[threshold],linewidths=2, colors='red')
#將異常樣本區域繪製成橘黃色
plt.contourf(xx, yy, Z, levels=[threshold, Z.max()],colors='orange')
#繪製正常點(白色)
b = plt.scatter(X_train[:-n_outliers, 0], X_train[:-n_outliers, 1], c='white',s=20, edgecolor='k') 
# 繪製異常點(黑色)
c = plt.scatter(X_train[-n_outliers:, 0], X_train[-n_outliers:, 1], c='black',s=20, edgecolor='k')
plt.axis('tight')

plt.legend(
    [a.collections[0], b, c],
    ['learned decision function', 'true inliers', 'true outliers'],
    prop=matplotlib.font_manager.FontProperties(size=10),
    loc='lower right')

plt.title('HBOS')
plt.xlim((-10, 10))
plt.ylim((-10, 10))
plt.show()
圖片名稱