scikit-learn 1.6 官网中文文档翻译已经上线了,欢迎使用:http://www.aidoczh.com/scikit-learn/
许多应用需要能够判断新观测是否属于与现有观测相同的分布(是“内点”),还是应该被视为不同(是“异常值”)。通常,这种能力被用于清理真实数据集。必须进行两个重要的区分:
异常值检测
训练数据包含被定义为远离其他观测的异常值。因此,异常值检测估计器试图拟合训练数据最集中的区域,忽略异常观测。
新奇性检测
训练数据不受异常值污染,我们有兴趣检测一个新的观测是否是异常值。在这种情况下,异常值也被称为新奇值。
异常值检测和新奇性检测都用于异常检测,其中人们有兴趣检测异常或不寻常的观测。因此,异常值检测也被称为无监督异常检测,新奇性检测被称为半监督异常检测。在异常值检测的背景下,异常/异常值不能形成密集的聚类,因为可用的估计器假设异常/异常值位于低密度区域。相反,在新奇性检测的背景下,新奇值/异常值可以形成密集的聚类,只要它们位于训练数据的低密度区域,就被认为是正常的。
scikit-learn 项目提供了一组机器学习工具,可以用于新奇性或异常值检测。这种策略是通过从数据中无监督地学习对象来实现的:
estimator.fit(X_train)
然后可以使用 predict
方法将新观测分为内点或异常值:
estimator.predict(X_test)
内点标记为1,异常值标记为-1。predict
方法使用估计器计算的原始评分函数上的阈值。可以通过 score_samples
方法访问此评分函数,而阈值可以由 contamination
参数控制。
decision_function
方法也是根据评分函数定义的,负值表示异常值,非负值表示内点:
estimator.decision_function(X_test)
请注意,neighbors.LocalOutlierFactor
默认不支持 predict
、decision_function
和 score_samples
方法,而只支持 fit_predict
方法,因为该估计器最初是用于异常值检测的。训练样本的异常性得分可以通过 negative_outlier_factor_
属性访问。
如果您真的想将 neighbors.LocalOutlierFactor
用于新奇性检测,即在新的未见数据上预测标签或计算异常性得分,可以在拟合估计器之前将 novelty
参数设置为 True
来实例化估计器。在这种情况下,fit_predict
不可用。
[!WARNING]
使用 Local Outlier Factor 进行新奇性检测当
novelty
设置为True
时,请注意只在新的未见数据上使用predict
、decision_function
和score_samples
,而不是在训练样本上使用,否则会导致错误的结果。即,predict
的结果将与fit_predict
不同。训练样本的异常性得分始终可以通过negative_outlier_factor_
属性访问。
neighbors.LocalOutlierFactor
的行为总结在下表中。
方法 | 异常值检测 | 新奇性检测 |
---|---|---|
fit_predict | 可用 | 不可用 |
predict | 不可用 | 仅用于新数据 |
decision_function | 不可用 | 仅用于新数据 |
score_samples | 使用 negative_outlier_factor_ | 仅用于新数据 |
negative_outlier_factor_ | 可用 | 可用 |
异常值检测方法概述
scikit-learn 中异常值检测算法的比较。Local Outlier Factor (LOF) 由于没有预测方法可用于异常值检测,因此没有显示黑色的决策边界。
ensemble.IsolationForest
和 neighbors.LocalOutlierFactor
在考虑的数据集上表现得相当好。svm.OneClassSVM
对异常值敏感,因此在异常值检测方面表现不佳。尽管如此,在高维度或没有对内部数据分布做任何假设的情况下进行异常值检测非常具有挑战性。svm.OneClassSVM
仍然可以用于异常值检测,但需要对其超参数 nu 进行精细调整,以处理异常值并防止过拟合。linear_model.SGDOneClassSVM
提供了一个线性 One-Class SVM 的实现,其样本数量的复杂度为线性。该实现使用核近似技术,以获得与默认使用高斯核的 svm.OneClassSVM
类似的结果。最后,covariance.EllipticEnvelope
假设数据服从高斯分布,并学习一个椭圆。有关不同估计器的更多详细信息,请参阅示例 sphx_glr_auto_examples_miscellaneous_plot_anomaly_comparison.py
和下面的部分。
示例:
- 有关
svm.OneClassSVM
、ensemble.IsolationForest
、neighbors.LocalOutlierFactor
和covariance.EllipticEnvelope
的比较,请参见sphx_glr_auto_examples_miscellaneous_plot_anomaly_comparison.py
。 - 有关如何使用 ROC 曲线从
metrics.RocCurveDisplay
评估异常值检测估计器neighbors.LocalOutlierFactor
和ensemble.IsolationForest
的示例,请参见sphx_glr_auto_examples_miscellaneous_plot_outlier_detection_bench.py
。
新奇性检测
考虑一个由 n n n 个观测组成的数据集,这些观测由 p p p 个特征描述。现在假设我们向该数据集添加了一个新的观测。新观测是否与其他观测非常不同,以至于我们怀疑它是否是正常的?(即它是否来自相同的分布?)或者相反,它是否与其他观测非常相似,以至于我们无法将其与原始观测区分开来?这是新奇性检测工具和方法所解决的问题。
一般来说,它是关于在嵌入的 p p p 维空间中绘制的初始观测分布的粗略、接近的边界。然后,如果进一步的观测位于边界限定的子空间内,它们被认为来自与初始观测相同的总体。否则,如果它们位于边界之外,我们可以说它们是异常的,并对我们的评估结果有一定的置信度。
One-Class SVM 是由 Schölkopf 等人为此目的引入的,并在 svm
模块中的 svm.OneClassSVM
对象中实现。它需要选择一个核函数和一个标量参数来定义边界。通常选择 RBF 核函数,尽管没有确切的公式或算法来设置其带宽参数。这是 scikit-learn 实现中的默认值。nu 参数,也称为 One-Class SVM 的边界,对应于在边界之外找到一个新的但正常的观测的概率。
参考文献:
- Estimating the support of a high-dimensional distribution Schölkopf, Bernhard, et al. Neural computation 13.7 (2001): 1443-1471.
示例:
- 有关使用
svm.OneClassSVM
对象可视化一些数据周围学习到的边界的示例,请参见sphx_glr_auto_examples_svm_plot_oneclass.py
。
扩展单类支持向量机
在线线性版本的单类支持向量机实现在linear_model.SGDOneClassSVM
中。这个实现与样本数量成线性比例,并且可以与核近似一起使用,以近似解决一个核化的svm.OneClassSVM
,其复杂度在最好的情况下是样本数量的平方。更多细节请参见sgd_online_one_class_svm
部分。
示例:
- 参见
sphx_glr_auto_examples_linear_model_plot_sgdocsvm_vs_ocsvm.py
,了解使用linear_model.SGDOneClassSVM
结合核近似来近似核化单类支持向量机的示例。
异常检测
异常检测与新奇检测类似,其目标是将一组正常观测结果与一些污染观测结果(称为异常值)分开。然而,在异常检测的情况下,我们没有一个代表正常观测结果总体的干净数据集,可以用来训练任何工具。
拟合椭圆包络
执行异常检测的一种常见方法是假设正常数据来自已知分布(例如,数据服从高斯分布)。基于这个假设,我们通常尝试定义数据的“形状”,并将远离拟合形状的观测结果定义为异常观测结果。
scikit-learn提供了一个名为covariance.EllipticEnvelope
的对象,它对数据拟合了一个鲁棒的协方差估计,从而对中心数据点拟合了一个椭圆,忽略了中心模式之外的点。
例如,假设内部数据服从高斯分布,它将以鲁棒的方式(即不受异常值影响)估计内部位置和协方差。从这个估计得到的马氏距离用于导出异常度量。下面是这种策略的示例。
示例:
- 参见
sphx_glr_auto_examples_covariance_plot_mahalanobis_distances.py
,了解使用标准估计(covariance.EmpiricalCovariance
)或鲁棒估计(covariance.MinCovDet
)位置和协方差来评估观测结果异常度的差异的示例。
参考文献:
- Rousseeuw, P.J., Van Driessen, K. “A fast algorithm for the minimum covariance determinant estimator” Technometrics 41(3), 212 (1999)
孤立森林
在高维数据集中执行异常检测的一种高效方法是使用随机森林。ensemble.IsolationForest
通过随机选择一个特征,然后在所选特征的最大值和最小值之间随机选择一个分割值来“隔离”观测结果。
由于递归分区可以用树结构表示,将样本隔离所需的分割次数等于从根节点到终止节点的路径长度。
这个路径长度在一组这样的随机树中的平均值是一个衡量正常性的指标和决策函数。
对于异常值,随机分区会产生明显较短的路径。因此,当一组随机树的路径长度对特定样本产生较短的路径时,它们很可能是异常值。
ensemble.IsolationForest
的实现基于tree.ExtraTreeRegressor
的集合。根据孤立森林原始论文,每棵树的最大深度设置为
⌈
log
2
(
n
)
⌉
\lceil \log_2(n) \rceil
⌈log2(n)⌉,其中
n
n
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], [0, 0], [-20, 50], [3, 5]])
>>> clf = IsolationForest(n_estimators=10, warm_start=True)
>>> clf.fit(X) # fit 10 trees # doctest: +SKIP
>>> clf.set_params(n_estimators=20) # add 10 more trees # doctest: +SKIP
>>> clf.fit(X) # fit the added trees # doctest: +SKIP
示例:
- 参见
sphx_glr_auto_examples_ensemble_plot_isolation_forest.py
,了解使用IsolationForest的示例。 - 参见
sphx_glr_auto_examples_miscellaneous_plot_anomaly_comparison.py
,了解ensemble.IsolationForest
与neighbors.LocalOutlierFactor
、svm.OneClassSVM
(调整为像异常检测方法一样执行)、linear_model.SGDOneClassSVM
和基于协方差的异常检测(covariance.EllipticEnvelope
)的比较。
参考文献:
- Liu, Fei Tony, Ting, Kai Ming and Zhou, Zhi-Hua. “Isolation forest.” Data Mining, 2008. ICDM’08. Eighth IEEE International Conference on.
局部离群因子
在中等维度的数据集上执行异常检测的另一种高效方法是使用局部离群因子(LOF)算法。
neighbors.LocalOutlierFactor
(LOF)算法计算一个分数(称为局部离群因子),反映观测结果的异常程度。它测量给定数据点相对于其邻居的局部密度偏差。其思想是检测具有明显较低密度的样本,相对于其邻居而言。
在实践中,局部密度是从k个最近邻中获得的。一个观测结果的LOF分数等于其k个最近邻的平均局部密度与其自身局部密度的比值:正常实例的局部密度预计与其邻居的局部密度相似,而异常数据的局部密度预计要小得多。
考虑到的邻居数k(别名参数n_neighbors)通常选择为:1)大于一个簇必须包含的最小对象数,以便其他对象可以相对于该簇是局部离群值,2)小于可能潜在地是局部离群值的附近对象的最大数量。在实践中,通常不可用这样的信息,并且通常在n_neighbors=20的情况下效果良好。当异常值的比例较高(例如大于10%,如下面的示例)时,n_neighbors应该更大(在下面的示例中,n_neighbors=35)。
LOF算法的优势在于它同时考虑了数据集的局部和全局属性:即使在异常样本具有不同基础密度的数据集中,它也可以表现良好。问题不是样本的孤立程度,而是相对于周围邻域的孤立程度。
在应用LOF进行异常检测时,没有predict
、decision_function
和score_samples
方法,只有一个fit_predict
方法。训练样本的异常度分数可以通过negative_outlier_factor_
属性访问。请注意,当LOF用于新颖性检测时,即将novelty
参数设置为True
时,可以在新的未见数据上使用predict
、decision_function
和score_samples
,但predict
的结果可能与fit_predict
的结果不同。请参见novelty_with_lof
。
下面是这种策略的示例。
示例:
- 参见
sphx_glr_auto_examples_neighbors_plot_lof_outlier_detection.py
,了解使用neighbors.LocalOutlierFactor
的示例。 - 参见
sphx_glr_auto_examples_miscellaneous_plot_anomaly_comparison.py
,与其他异常检测方法进行比较。
参考文献:
- Breunig, Kriegel, Ng, and Sander (2000) LOF: identifying density-based local outliers. Proc. ACM SIGMOD
使用局部离群因子进行新颖性检测
lof = LocalOutlierFactor(novelty=True)
lof.fit(X_train)
请注意,在这种情况下,fit_predict
方法不可用,以避免不一致性。
[!WARNING]
使用 Local Outlier Factor 进行新颖性检测当
novelty
参数设置为True
时,请注意只能在新的未见数据上使用predict
、decision_function
和score_samples
方法,而不能在训练样本上使用,否则会导致错误的结果。也就是说,predict
的结果将与fit_predict
不同。训练样本的异常程度分数始终可以通过negative_outlier_factor_
属性访问。
下面是使用 Local Outlier Factor 进行新颖性检测的示例。