異常檢測
我們經常需要識別一些異常行為或者表現,比如 機器是否故障,產品是否合格,這類問題的特點就是 正常數據很多,異常數據很少,甚至根本沒有;
解決這種問題的思路就是,把 訓練樣本中 一小部分數據認為是 異常數據,然后訓練一個 非常緊湊的決策邊界,把 大部分被認為是正常的樣本 框起來,並以此邊界作為衡量標准,邊界外就是異常;
如下圖
這種算法我們稱為 單分類算法;
解決單分類問題的算法有很多,如
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用戶手冊(中文)