異常檢測 與 One Class SVM


異常檢測

我們經常需要識別一些異常行為或者表現,比如 機器是否故障,產品是否合格,這類問題的特點就是 正常數據很多,異常數據很少,甚至根本沒有

解決這種問題的思路就是,把 訓練樣本中 一小部分數據認為是 異常數據,然后訓練一個 非常緊湊的決策邊界,把 大部分被認為是正常的樣本 框起來,並以此邊界作為衡量標准,邊界外就是異常;

如下圖

這種算法我們稱為 單分類算法

 

解決單分類問題的算法有很多,如

1. 孤立森林:我的博客

2. 自編碼器:我的博客

把 自編碼器 用來做 異常檢測 真的很奇妙,它的思路是,用正常樣本訓練 自編碼器, 輸入和輸出一定相差不大,如果新的樣本通過自編碼器,輸入和輸出相差很大,就是異常樣本;

3. One Class SVM:這種方法類似於 SVM,在理解 SVM 的基礎上,這個算法沒有什么好講的,所以不單獨寫一篇博客了;

由於 SVM 在核函數計算時速度很慢,故不適合海量數據,而 孤立森林 可運行在分布式系統上,自編碼器 可用 GPU 進行加速,適合海量數據;

 

One Class SVM

sklearn 提供了一些機器學習算法,用於 奇異點(Novelty) 或者 異常點(Outlier) 檢測;

novelty detection:訓練樣本中沒有離群點,我們用訓練好的模型去檢測,邊界外的就是異常;      【自編碼器】

outlier  dection:訓練樣本中存在離群點,訓練模型時要匹配密集樣本,忽略離群點;   【孤立森林】

One Class SVM 既可以是 novelty,也可以是 Outlier,當然,嚴格的講,它應該屬於 novelty,但實際上訓練樣本都會存在噪音,我們需要繞過噪音,得到一個干凈的模型,這就是 Outlier;

 

One Class SVM 是一種無監督算法,它的思想是 尋找一個 超球面,使得 正常樣本 在球體內,異常樣本在球體外,然后 最小化這個球 的半徑或者體積;

其中 o 是球心,r 是半徑,V(r) 是球的體積,c 是懲罰系數,ξ 是松弛變量;    【基本上等同於 SVM 我的博客

 

SVDD 介紹

解決  One Class SVM 的方法很多, SVDD 就是其中一種,SVDD 的思路仍然類似於上面的公式,但略作簡化

s.t.

 

再來張圖把

 

sklearn API

官網示例

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager
from sklearn import svm
 
xx, yy = np.meshgrid(np.linspace(-5, 5, 500), np.linspace(-5, 5, 500))
# Generate train data
X = 0.3 * np.random.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
# Generate some regular novel observations
X = 0.3 * np.random.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
# Generate some abnormal novel observations
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
 
# fit the model
clf = svm.OneClassSVM(nu=0.1, kernel="rbf", gamma=0.1)
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
n_error_train = y_pred_train[y_pred_train == -1].size
n_error_test = y_pred_test[y_pred_test == -1].size
n_error_outliers = y_pred_outliers[y_pred_outliers == 1].size
 
# plot the line, the points, and the nearest vectors to the plane
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
 
plt.title("Novelty Detection")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), 0, 7), cmap=plt.cm.PuBu)  #繪制異常樣本的區域
a = plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='darkred')  #繪制正常樣本和異常樣本的邊界
plt.contourf(xx, yy, Z, levels=[0, Z.max()], colors='palevioletred')   #繪制正常樣本的區域
s = 40
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white', s=s, edgecolors='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='blueviolet', s=s,
                 edgecolors='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='gold', s=s,
                edgecolors='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([a.collections[0], b1, b2, c],
           ["learned frontier", "training observations",
            "new regular observations", "new abnormal observations"],
           loc="upper left",
           prop=matplotlib.font_manager.FontProperties(size=11))
plt.xlabel(
    "error train: %d/200 ; errors novel regular: %d/40 ; "
    "errors novel abnormal: %d/40"
    % (n_error_train, n_error_test, n_error_outliers))
plt.show()

nu 代表異常樣本的占比,nu 越大,R 越小,條件越 苛刻 

 

優化

基於蟻群算法的優化 ,可以參考下

 

 

參考資料:

https://www.cnblogs.com/wj-1314/p/10701708.html#top

https://blog.csdn.net/a1154761720/article/details/50708398

https://blog.csdn.net/comli_cn/article/details/103898791  sklearn.svm.OneClassSVM用戶手冊(中文)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM