2.7. 奇异值和异常值检测

许多应用程序要有能力判断新观测值是否与现有观测值具有相同的分布(它是一个内点(inlier)),或者应该被认为是不同的(它是一个离群值)。通常,这种能力被用于清理实际数据集, 必须做出两种重要区分:

离群点检测: 训练数据包含离群点,这些离群点被定义为远离其它内围点的观察值。因此,离群点检测估计器会尝试拟合出训练数据中内围点聚集的区域, 而忽略异常值观察。
奇异值检测: 训练数据没有受到离群点污染,我们感兴趣的是检测一个新的观测值是否为离群点。在这种情况下,离群点被认为是奇异值。

离群点检测和奇异值检测都用于异常检测, 其中一项感兴趣的是检测异常或异常观察。离群点检测又被称之为无监督异常检测,奇异值检测又被称之为半监督异常检测。 在。相反的,在奇异值检测的背景下,奇异值/异常点只要位于训练数据的低密度区域,是可以形成稠密聚类簇的,在此背景下被认为是正常的。

scikit-learn项目提供了一组机器学习工具,可用于新颖性或离群值检测。通过以无监督的方式从数据中学习对象来实现此策略:

estimator.fit(X_train)

然后可以使用以下predict方法将新观察值分类为离群点或内围点 :

estimator.predict(X_test)

内围点标记为1,而离群点标记为-1。预测方法利用了估计器计算的原始评分函数的阈值。通过该score_samples 可以访问此评分函数,而阈值可以由contamination 参数控制。

decision_function还通过评分函数定义该方法,以使负值是离群点,而非负值不是离群点:

estimator.decision_function(X_test)

请注意 neighbors.LocalOutlierFactor 类默认不支持 predict, decision_functionscore_samples 方法,而只支持 fit_predict 方法, 因为这个估计器从本来就是被用到离群点检测中去的。可以通过 negative_outlier_factor_属性来获取训练样本的异常性得分。

如果您真的想把neighbors.LocalOutlierFactor用于奇异值检测,即预测新的样本标签或计算新的未知数据的异常分数,则可以在拟合估计器之前把novelty参数设置为True。在这种情况下,fit_predict不可用。

警告 :使用局部离群因子进行奇异值检测

novelty参数设置为 True 时,在新的未见过的数据上,你只能使用 predict, decision_functionscore_samples ,而不能用在训练数据上, 因为会导致错误的结果。训练样本的异常性得分始终可以通过negative_outlier_factor_属性获取。

neighbors.LocalOutlierFactor下表中总结了离群点检测和奇异值检测中的行为。

方法 离群点检测 新颖性检测
fit_predict 可用 无法使用
predict 无法使用 仅用于新数据
decision_function 无法使用 仅用于新数据
score_samples 采用 negative_outlier_factor_ 仅用于新数据

2.7.1. 离群点检测方法一览

比较scikit-learn中的离群点检测算法。局部离群点因子(Local Outlier Factor, LOF)并没有显示黑色的决策边界,因为当它用于离群点检测时,它没有适用于新数据的 predict 方法。

ensemble.IsolationForestneighbors.LocalOutlierFactor 在此处用到的数据集上表现很好。svm.OneClassSVM被认为对离群点敏感并因此对离群点检测执行的不是很好。最后, covariance.EllipticEnvelope假设数据服从高斯分布并学习一个椭圆。有关不同估计器的更多详细信息,请参阅示例 玩具数据集异常检测算法的比较研究以及以下各节。

示例:

2.7.2. Novelty Detection(奇异值检测)

考虑一个由 个特征描述的相同分布的 个观测的数据集。 现在考虑我们在这个数据集中再增加一个观测值。 这个新观测是否与其他的观测值有很大差异,我们就可以怀疑它是否是常规值 (即它否来自相同的分布?)或者相反,如果新观测与原有观测非常相似以至于我们就无法将其与原有观测值分开? 这是奇异值检测工具和方法所解决的问题。

一般来说,它是要学习出一个粗略的、封闭的边界划定出初始观测分布的轮廓,绘制在嵌入的 维空间中。然后,如果进一步的观测值位于这个边界划分的子空间内,则认为它们来自与初始观测值来自同一处。 否则,如果它们位于边界之外,我们就可以说根据我们评估给定的置信度而言,它们是异常的。

Schölkopf 等人已经采用One-Class SVM(单类支持向量机)来实现新奇检测,并在属于 支持向量机 模块的 svm.OneClassSVM 对象中实现。 它需要选择一个 kernel 和 scalar 参数来定义边界。 虽然没有精确的公式或算法来设置RBF核的带宽参数,但通常选择RBF核。这是scikit-learn实现中的默认设置。参数 ,也称为单类支持向量机的边沿,对应于在边界之外找到新的但常规的观测值的概率。

参考资料:

示例:

2.7.3. Outlier Detection(离群点检测)

离群点检测与新奇性检测类似,其目的是将常规观测的核心数据与被称为离群点的污染数据分离开来。然而,在离群点检测的情况下,我们没有一个清晰的数据集来表示常规观测的总体,这些数据集可以用来训练任何工具。

2.7.3.1. Fitting an elliptic envelope(椭圆模型拟合)

执行离群值检测的一种常见方法是假设常规数据来自一个已知分布(例如数据是高斯分布的)。根据这一假设,我们一般尝试定义数据的“形状”,并可以将边缘观测定义为距离拟合形状足够远的观测值。

scikit-learn 提供了 covariance.EllipticEnvelope对象,椭圆包络线,它对数据进行稳健的协方差估计,从而对中心数据点进行拟合出一个椭圆,忽略中心模式之外的点。

例如,假设内部数据是高斯分布的,它将以一种可靠的方式(即不受离群值的影响)估算离群位置和协方差。从这个估计值得到的马氏距离用来得出离群度的度量。这个策略如下所示。

示例:

参考资料:

  • Rousseeuw, P.J., Van Driessen, K. “A fast algorithm for the minimum covariance determinant estimator” Technometrics 41(3), 212 (1999)

2.7.3.2. Isolation Forest

在高维数据集中实现离群点检测的一种有效方法是使用随机森林。ensemble.IsolationForest 通过随机选择一个特征,然后随机选择一个被选择特征的最大值和最小值之间的分割值来“隔离”观察结果。

由于递归划分可以由树形结构表示,因此隔离样本所需的分割次数等于从根节点到终止节点的路径长度。

在这样的随机树的森林中取平均值就是这条路径的长度,是对数据正态性和我们的决策函数的一种度量。

随机划分能为异常观测产生明显的更短路径。 因此,当随机树的森林为特定样本共同产生较短的路径长度时,他们很可能是异常的。

ensemble.IsolationForest的实现,是基于tree.ExtraTreeRegressor全体。按照Isolation Forest原始,每棵树的最大深度设置为,其中n是构建树所用的样本数量(详见:(Liu et al., 2008) )

该算法如下图所示。

ensemble.IsolationForest支持warm_start=True,可以让你添加更多的树到已拟合好的模型中:

>>> from sklearn.ensemble import IsolationForest
>>> import numpy as np
>>> X = np.array([[-1-1], [-2-1], [-3-2], [00], [-2050], [35]])
>>> clf = IsolationForest(n_estimators=10, warm_start=True)
>>> clf.fit(X)  # fit 10 trees  
>>> clf.set_params(n_estimators=20)  # add 10 more trees  
>>> clf.fit(X)  # fit the added trees  

Examples:

References:

  • Liu, Fei Tony, Ting, Kai Ming and Zhou, Zhi-Hua. “Isolation forest.” Data Mining, 2008. ICDM’08. Eighth IEEE International Conference on.

2.7.3.3. Local Outlier Factor(局部离群因子)

对中等高维数据集(即维数勉强算是高维)执行离群点检测的另一种有效方法是使用局部离群因子(LOF)算法。

neighbors.LocalOutlierFactor LocalOutlierFactor (LOF)算法计算一个反映观测异常程度的得分(称为局部离群因子)。 它测量给定数据点相对于相邻数据点的局部密度偏差。这样做的目的是为了检测出那些比近邻的密度低得多的样本。

实际应用中,局部密度从 k 个最近邻求得的。 观测数据的 LOF 得分等于其 k 个最近邻的平均局部密度与其本身密度的比值:正常数据集预计与其近邻有着相似的局部密度,而异常数据则预计比近邻的局部密度要小得多。

k个近邻数(别名参数 n_neighbors )通常选择 1) 大于一个聚类簇必须包含的最小数量的对象,所以其它对象可以成为该聚类簇的局部离散点,并且 ,2) 小于可能成为聚类簇对象的最大数量, 减少这K个近邻成为离群点的可能性。在实践中,这样的信息通常不可用,并且使 n_neighbors = 20 似乎都能使算法有很好的表现。 当离群点的比例较高时(大于 10% 时,如下面的示例),n_neighbors 应该较大(在下面的示例中,n_neighbors = 35)。

LOF 算法的优点是考虑到数据集的局部和全局属性:即使在具有不同潜在密度的离群点数据集中,它也能够表现得很好。 问题不在于样本是如何被分离的,而是样本与周围近邻的分离程度有多大。

在使用 LOF 进行离群点检测时,不能使用 predict, decisionfunction 和 score_samples 方法, 只能用 fit_predict 方法。训练样本的异常性得分可通过 negative_outlier_factor 属性来获得。 注意当使用LOF算法进行奇异值检测的时候(novelty 设为 True), predict, decision_function 和 score_samples 函数可被用于新的未知数据。请查看具有局部离群因子(LOF)的新颖性检测.

该策略如下所示。

示例:

参考资料:

2.7.4. 使用LOF进行奇异值检测

为了使用 neighbors.LocalOutlierFactor 进行奇异值检测, 即对新的未见过的样本预测其标签或计算异常性得分,在拟合之前,你必须在实例化估计器时, 将novelty参数设为 True:

lof = LocalOutlierFactor(novelty=True)
lof.fit(X_train)Copy

请注意此情况下fit_predict 不再适用。

警告 :使用局部离群因子(Local Outlier Factor,LOF)进行奇异值检测

要注意,在新的未见过的数据上,当novelty参数被设为 True 时只能使用 predict, decision_functionscore_samples ,不能把这几个函数用在训练数据上, 否则会导致错误的结果。训练样本的异常性得分可以通过 negative_outlier_factor_属性来访问获取。

使用局部离群因子进行奇异值检测的示例见下图: