《异常检测——从经典算法到深度学习》3 基于One-Class SVM的异常检测算法

目录

  • 0 概论
  • 1 基于隔离森林的异常检测算法
  • 2 基于LOF的异常检测算法
  • 3 基于One-Class SVM的异常检测算法
  • 4 基于高斯概率密度异常检测算法
  • 5 Opprentice——异常检测经典算法最终篇

3. 基于 One-Class SVM 的异常检测算法

此篇主要介绍以下内容:

  • One-Class SVM 算法概述
  • One-Class SVM 算法应用实例
  • 小结

3.1 One-Class SVM 算法概述

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 算法特点:

  • 是一种非监督学习算法
  • 是一种基于正常数据的特征进行异常检测的算法,和正常数据特征相似的数据被认为是正常数据,否则则认为是异常数据
  • 比较适用于高维空间中的样本数据集

3.2 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()

输出图片如下(代码没有设置随机种子,所以可能每次运行都不一样):
《异常检测——从经典算法到深度学习》3 基于One-Class SVM的异常检测算法_第1张图片
注意查看图片下面的文字:

  • error train: 21/200 表示把模型认为训练集中有 21 个数据一异常数据。拿 实例1 中的数据来说,模型认为有两个为异常数据,因为有两个预测结果为 -1
  • errors noval regular 2/40: 新正常数据中预测错误数目。也就是代码中 第二次生成大小为40的数据集X中(即对应代码 X = 0.3*np.random.randn(20,2)),模型认为有两个数据为异常数据。
  • errors noval abnormal 0/40: 新异常数据预测错误数目。 也就是说在新生成的异常数据共40个中(即对应代码 X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2)) ),完全预测正确,这些异常数据都被检测到了。

一些参数的使用请参考,sklearn官网文档

关于异常值检测(outlier detection)和新颖值检测(novelty detection)

在 基于LOF的异常检测算法 中解释了二者的差异,并且描述了 基于LOF算法应该如何进行新颖值检测,更加适合用作异常检测。而对于One-Class SVM算法来说,它本身就是设计用来做新颖值检测的,但是在某些条件下加上一些限制条件,也可以用来做异常检测。

一般需要考虑使用以下两种方式:

  1. 调整边界。如上面 实例2 输出图片所示,红色的圆环被认为是边界,这个是训练后由算法生成的,所以可以考虑修改算法参数,来改变边界的大小。(就sklearn的实现而言,即 kernelgamma 这两个参数)
  2. 根据预测评分来设定异常。拿 实例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

3.3 小结

One-Class SVM 也是异常检测领域十分经典的算法。它认为和正常数据相似的(即被超平面分到一起)即是正常数据,和正常数据相差比较大的,则是异常数据。

对于高维空间中的样本数据集,One-Class SVM 能表现出更好的效果。

Smileyan
2020年5越26日

你可能感兴趣的:(异常检测)