此篇主要介绍以下内容:
SVM (Support Vector Machines): 支持向量机是一类按监督学习方式对数据进行二元分类的广义线性分类器,其决策边界是对学习样本求解的最大边距超平面。 —— 百度百科
One-Class SVM: One-Class SVM是一种无监督算法,它学习用于新颖性(novelty)检测的决策函数:将新数据分类为与训练集相似或不同的数据。参考论文
严格来说,One-Class SVM 不是一个异常点检测算法,而是一个新颖值检测(Novelty Detection)算法。换句话说,在One-Class SVM 将所以与正常数据有一定区别的都当成新颖数据,而我们根据实际需要设定边界,才认为超出边界的数据为异常数据。关于边界的问题,可以参考后面的例子。 —— sklearn官网相关介绍
One-Class SVM 算法与SVM算法的原理以及数学模型基本相同。总而言之就是寻找一个超平面,使用这个超平面把正常数据和异常数据(或称之为新颖数据)划分开,这是SVM算法的基本思想,而One-Class SVM 是基于一类数据(正常数据)求超平面,对 SVM 算法中求解负样本最大间隔目标进行改造,进而完成非监督学习下的异常检测。
One-Class SVM 算法特点:
来自 sklearn官网例子
实例1
from sklearn.svm import OneClassSVM
X = [[0], [0.44], [0.45], [0.46], [1]]
clf = OneClassSVM(gamma='auto').fit(X)
print(clf.predict(X))
clf.score_samples(X)
输出内容:
[-1 1 1 1 -1]
array([1.77987316, 2.05479873, 2.05560497, 2.05615569, 1.73328509])
实例2
print(__doc__)
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()
输出图片如下(代码没有设置随机种子,所以可能每次运行都不一样):
注意查看图片下面的文字:
21
个数据一异常数据。拿 实例1 中的数据来说,模型认为有两个为异常数据,因为有两个预测结果为 -1
。X = 0.3*np.random.randn(20,2)
),模型认为有两个数据为异常数据。X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
),完全预测正确,这些异常数据都被检测到了。一些参数的使用请参考,sklearn官网文档
关于异常值检测(outlier detection)和新颖值检测(novelty detection)
在 基于LOF的异常检测算法 中解释了二者的差异,并且描述了 基于LOF算法应该如何进行新颖值检测,更加适合用作异常检测。而对于One-Class SVM算法来说,它本身就是设计用来做新颖值检测的,但是在某些条件下加上一些限制条件,也可以用来做异常检测。
一般需要考虑使用以下两种方式:
实例2
输出图片所示,红色的圆环被认为是边界,这个是训练后由算法生成的,所以可以考虑修改算法参数,来改变边界的大小。(就sklearn的实现而言,即 kernel
和 gamma
这两个参数)实例1
来说,当输出对所有结果的打分的时候,可以考虑根据分数进行异常判定,比如说排序后,认为 前2%
可能是异常等等。参考文档:
https://scikit-learn.org/stable/auto_examples/svm/plot_oneclass.html#sphx-glr-auto-examples-svm-plot-oneclass-py
https://scikit-learn.org/stable/modules/generated/sklearn.svm.OneClassSVM.html?highlight=one%20class%20svm#sklearn-svm-oneclasssvm
https://scikit-learn.org/stable/modules/outlier_detection.html#outlier-detection
One-Class SVM 也是异常检测领域十分经典的算法。它认为和正常数据相似的(即被超平面分到一起)即是正常数据,和正常数据相差比较大的,则是异常数据。
对于高维空间中的样本数据集,One-Class SVM 能表现出更好的效果。
Smileyan
2020年5越26日