高维数据异常检测

一、概述

许多真实的数据集是高维的。在某些情况下,真实的数据集可能包含数百或数千个维度。随着维数的不断增加,许多传统的异常检测方法并不能非常有效地工作。这是著名的维数灾难的表现。在高维空间中,当进行全维分析时,数据变得稀疏,真正的离群值被多个不相关维度的噪声效应所掩盖。

维数灾难的一个主要原因是难以在高维情况下确定一个点的相关位置。例如,基于距离相似度的方法通过在所有维度上使用距离函数来定义局部性。然而,某些维度可能与特定的测试点无关,这也会影响基础距离函数的质量。例如,在高维空间中,所有的点对几乎等距。这种现象称为数据稀疏或距离集中。由于离群值被定义为稀疏区域中的数据点,这导致了一种不好的区分情况,即所有数据点都位于几乎同样稀疏的全维区域中。维数诅咒所带来的挑战并不是异常检测所特有的。众所周知,许多问题,例如聚类和最近邻搜索分析,在维度不断增加的情况下遇到了挑战。事实上,有人认为,几乎任何基于邻近概念的算法在高维空间都会在质量上退化,因此需要以更有意义的方式重新定义。

为了进一步解释全维离群点分析算法失效的原因,本文给出了一个实例。在下图中,已经说明了一个假设数据集的四个不同的二维视图。这些视图中的每一个都对应于一组不相交的维。很明显,点“ A”在数据集的第一个视图中被公开为异常值,而点“ B”在数据集的第四个视图中被公开为异常值。但是,在数据集的第二个和第三个视图中,“ A”和“B”这两个数据点都不作为离群值公开。因此,从度量“A”和“B”的离群值的角度来看,这些视图是嘈杂的。在这种情况下,四个视图中的三个视图对于揭示任何特定的离群值“ A”或“B”来说,都是非信息性的和嘈杂的。在这种情况下,离群值在这些视图中的随机分布中丢失了,当距离测量是以完整的维度进行的。这种情况通常会随着维度的增加而自然放大。对于非常高维的数据集,可能只有很小一部分视图可以为离群值分析过程提供信息。
在这里插入图片描述
上述图片说明告诉我们问题的局部相关尺寸至关重要。在实际场景中,对这种情况的物理解释是相当直观的。一个物体可能有几个测量量,而这个物体的显著异常行为可能只反映在这些量的一个小子集中。例如,考虑一个飞机机械故障检测场景,其中不同测试的结果以不同的尺寸表示。在同一架飞机上进行的数千次不同机身测试的结果可能大多数是正常的,有一些噪音的变化,这些变化并不显著。另一方面,一小部分测试中的一些偏差可能非常显著,足以表明异常行为。当来自测试的数据以完整的维度表示时,反常的数据点在数据的几乎所有视图中都会显示为正常的,除了维度的一小部分。因此,聚合邻近度量不太可能暴露出异常值,因为大量正常测试的噪声变化会掩盖异常值。此外,当测试不同的对象(不同机体的实例)时,不同的测试(维度子集)可能与识别异常值有关。换句话说,离群值通常嵌入在局部相关的子空间中。

这对于在这种情况下的全维度分析意味着什么?当使用全维距离来测量偏差时,大量“正常噪声”维度的稀释效应将使得异常值的检测变得困难。在大多数情况下,其他维度的噪音导致距离集中,可能使计算更加错误。此外,噪声在大量不同维度中的累加效应将干扰实际偏差的检测。简单地说,由于全维计算中噪声的掩蔽效应和稀释效应,在使用全维分析时,存在于低维子空间的异常值会被丢失。
其他基于距离的方法也有类似的效果,比如聚类和最近邻搜索。对于这些问题,已经证明,通过检查子空间中数据的行为,可以设计出更有意义的集群,这些集群特定于问题中的特定子空间。这个广泛的观察结果通常也适用于异常检测问题。由于离群值只能在数据的低维子空间中发现,因此探索低维子空间中感兴趣的偏差是有意义的。这种方法滤除了大量维数的附加噪声影响,从而得到更稳健的离群值。一个有趣的现象是,即使在缺少属性值的数据集中,也经常可以识别这种低维预测。这对于许多实际应用非常有用,因为特征提取是一个困难的过程,而且通常不存在完整的特征描述。例如,在机身故障检测方案中,可能只应用了测试的一个子集,因此只有维度子集中的值可用于离群值分析。这种模型被称为计划异常检测,或者,也可以称为子空间异常检测。

相关子空间的识别是一个极具挑战性的问题。这是因为高维数据的可能预测数目与数据的维数成指数关系。一个有效的异常检测方法需要以一种综合的方式搜索数据点和维度,以便揭示最相关的离群值。这是因为维度的不同子集可能与不同的离群值相关,这从上图中的例子中可以明显看出。这进一步增加了计算的复杂性。

一个重要的观察结果是,子空间分析在异常检测问题中通常比在聚类问题中更加困难。这是因为像集群这样的问题是基于聚合行为的,而异常值,从定义上来说,是很少见的。因此,在孤立点分析的情况下,与聚类等基于聚集的问题相比,给定区域内个体维度的统计聚集常常为子空间探索过程提供非常弱的提示。当这种微弱的提示导致相关维度的省略时,效果可能比包含不相关维度更加剧烈,特别是在有趣的情况下,当局部相关维度的数量只是整个数据维度的一小部分。一个常见的错误是假定聚类和离群点分析之间的互补关系可以推广到局部子空间选择问题。特别是,由于对早期子空间聚类方法中的维数选择方法不了解不同问题中子空间分析原理的细微差别,有时会遗漏重要的离群点。在这种情况下,识别离群值分析的相关子空间的困难也是至关重要的。一般来说,为每个数据点选择一个相关的子空间会导致不可预测的结果,因此将多个子空间的结果组合起来是非常重要的。换句话说,子空间异常检测天生就是一个以集成为中心的问题。
常用的方法有以下几类:

  • 基于稀缺性: 这些方法试图基于底层分布的稀缺性来发现子空间。这里的主要挑战是计算,因为稀有子空间的数量远远大于高维稠密子空间的数量。
  • 无偏: 在这些方法中,子空间的采样是无偏的,得分是跨采样子空间组合。当子空间从原始属性集中采样时,这种方法称为特征包装。在任意取向子空间抽样的情况下,该方法称为旋转套袋抽样或旋转子空间抽样。尽管这些方法非常简单,但往往很有效。
  • 基于聚合: 在这些方法中,使用聚合统计,例如集群统计、方差统计或数据的全局或局部子集的非一致性统计,来量化子空间的相关性。与基于稀有性的统计不同,这些方法量化全局或局部参考点集的统计特性,而不是试图直接识别数据稀疏的子空间。由于这些方法只能提供弱的(和容易出错的)提示来识别相关的子空间,多子空间抽样是至关重要的。

二、Feature Bagging

Feature Bagging,基本思想与bagging相似,只是对象是feature。feature bagging属于集成⽅法的⼀种。集成⽅法的设计有以下两个主要步骤:

1.选择基检测器

这些基本检测器可以彼此完全不同,或不同的参数设置,或使⽤不同采样的⼦数据集。Feature bagging常⽤lof算法为基算法。下图是feature bagging的通⽤算法:

在这里插入图片描述

2.分数标准化和组合方法

不同检测器可能会在不同的尺度上产⽣分数。例如,平均k近邻检测器会输出原始距离分数,而LOF算法会输出归⼀化值。另外,尽管⼀般情况是输出较⼤的异常值分数,但有些检测器会输出较小的异常值分数。因此,需要将来⾃各种检测器的分数转换成可以有意义的组合的归⼀化值。分数标准化之后,还要选择⼀个组合函数将不同基本检测器的得分进⾏组合,最常⻅的选择包括平均和最⼤化组合函数。
下图是两个feature bagging两个不同的组合分数⽅法:
在这里插入图片描述
在这里插入图片描述
基探测器的设计及其组合⽅法都取决于特定集成⽅法的特定⽬标。很多时候,我们⽆法得知数据的原始分布,只能通过部分数据去学习。除此以外,算法本⾝也可能存在⼀定问题使得其⽆法学习到数据完整
的信息。这些问题造成的误差通常分为偏差和⽅差两种。

⽅差:是指算法输出结果与算法输出期望之间的误差,描述模型的离散程度,数据波动性。

偏差:是指预测值与真实值之间的差距,特别是在离群点检测问题中,往往没有可⽤的基本真值。

三、Isolation Forests

孤⽴森林(Isolation Forest)算法是周志华教授等⼈于2008年提出的异常检测算法,是机器学习中少⻅的专⻔针对异常检测设计的算法之⼀,⽅法因为该算法时间效率⾼,能有效处理⾼维数据和海量数据,⽆须标注样本,在⼯业界应⽤⼴泛。

孤⽴森林属于⾮参数和⽆监督的算法,既不需要定义数学模型也不需要训练数据有标签。孤⽴森林查找孤⽴点的策略⾮常⾼效。假设我们⽤⼀个随机超平⾯来切割数据空间,切⼀次可以⽣成两个⼦空间。然后我们继续⽤随机超平⾯来切割每个⼦空间并循环,直到每个⼦空间只有⼀个数据点为⽌。直观上来讲,那些具有⾼密度的簇需要被切很多次才会将其分离,而那些低密度的点很快就被单独分配到⼀个⼦空间了。孤⽴森林认为这些很快被孤⽴的点就是异常点。

⽤四个样本做简单直观的理解,d是最早被孤⽴出来的,所以d最有可能是异常。

在这里插入图片描述
怎么来切这个数据空间是孤⽴森林的核⼼思想。因为切割是随机的,为了结果的可靠性,要⽤集成(ensemble)的⽅法来得到⼀个收敛值,即反复从头开始切,平均每次切的结果。孤⽴森林由t棵孤⽴的数组成,每棵树都是⼀个随机⼆叉树,也就是说对于树中的每个节点,要么有两个孩⼦节点,要么⼀个孩⼦节点都没有。树的构造⽅法和随机森林(random forests)中树的构造⽅法有些类似。流程如下:

  1. 从训练数据中随机选择⼀个样本⼦集,放⼊树的根节点;
  2. 随机指定⼀个属性,随机产⽣⼀个切割点V,即属性A的最⼤值和最小值之间的某个数;
  3. 根据属性A对每个样本分类,把A小于V的样本放在当前节点的左孩⼦中,⼤于等于V的样本放在右孩⼦中,这样就形成了2个⼦空间;
  4. 在孩⼦节点中递归步骤2和3,不断地构造左孩⼦和右孩⼦,直到孩⼦节点中只有⼀个数据,或树的⾼度达到了限定⾼度。

获得t棵树之后,孤⽴森林的训练就结束,就可以⽤⽣成的孤⽴森林来评估测试数据。

孤⽴森林检测异常的假设是:异常点⼀般都是⾮常稀有的,在树中会很快被划分到叶⼦节点,因此可以⽤叶⼦节点到根节点的路径⻓度来判断⼀条记录是否是异常的。和随机森林类似,孤⽴森林也是采⽤构造好的所有树的平均结果形成最终结果的。在训练时,每棵树的训练样本是随机抽样的。从孤⽴森林的树的构造过程看,它不需要知道样本的标签,而是通过阈值来判断样本是否异常。因为异常点的路径⽐较短,正常点的路径⽐较⻓,孤⽴森林根据路径⻓度来估计每个样本点的异常程度。

路径⻓度计算⽅法:
在这里插入图片描述
孤⽴森林也是⼀种基于⼦空间的⽅法,不同的分⽀对应于数据的不同局部⼦空间区域,较小的路径对应于孤⽴⼦空间的低维。

四、总结

1.feature bagging可以降低方差

2.孤立森林的优势在于:

  • 计算成本相⽐基于距离或基于密度的算法更小。
  • 具有线性的时间复杂度。
  • 在处理⼤数据集上有优势。
    孤⽴森林不适⽤于超⾼维数据,因为孤立森林每次都是随机选取维度,如果维度过⾼,则会存在过多噪⾳。

五、基于pyod库feature bagging算法实现

from pyod.models.feature_bagging import FeatureBagging
from pyod.utils.data import generate_data
from pyod.utils.data import evaluate_print
from pyod.utils.example import visualize

if name == ‘main’:
contamination = 0.1
n_train = 200
n_test = 100

X_train, y_train, X_test, y_test = generate_data(n_train=n_train,
                                                 n_test=n_test,
                                                 n_features=10,
                                                 contamination=contamination,
                                                 random_state=42)

clf_name = 'FeatureBagging'
clf = FeatureBagging(check_estimator=False)
clf.fit(X_train)

y_train_pred = clf.labels_
y_train_scores = clf.decision_scores_

y_test_pred = clf.predict(X_test)
y_test_scores = clf.decision_function(X_test)

# 打印结果
print("\nOn Training Data:")
evaluate_print(clf_name, y_train, y_train_scores)
print("\nOn Test Data:")
evaluate_print(clf_name, y_test, y_test_scores)

On Training Data:
FeatureBagging ROC:0.9964, precision @ rank n:0.9

On Test Data:
FeatureBagging ROC:0.8244, precision @ rank n:0.6

#作为对比,看看单个LOF检测器的效果
clf_name = ‘LOF’
clf = LOF()
clf.fit(X_train)

y_train_pred = clf.labels_
y_train_scores = clf.decision_scores_

y_test_pred = clf.predict(X_test)
y_test_scores = clf.decision_function(X_test)

# 打印结果
print("\nOn Training Data:")
evaluate_print(clf_name, y_train, y_train_scores)
print("\nOn Test Data:")
evaluate_print(clf_name, y_test, y_test_scores)

On Training Data:
LOF ROC:0.9889, precision @ rank n:0.8

On Test Data:
LOF ROC:0.6333, precision @ rank n:0.5

六、基于pyod库孤立森林算法实现

from pyod.models.iforest import IForest
from pyod.utils.data import generate_data
from pyod.utils.data import evaluate_print
from pyod.utils.example import visualize

if name == ‘main’:
contamination = 0.1
n_train = 200
n_test = 100

X_train, y_train, X_test, y_test = generate_data(n_train=n_train,
                                                 n_test=n_test,
                                                 n_features=10,
                                                 contamination=contamination,
                                                 random_state=42)


clf_name = 'IForest'
clf = IForest()
clf.fit(X_train)

y_train_pred = clf.labels_
y_train_scores = clf.decision_scores_

y_test_pred = clf.predict(X_test)
y_test_scores = clf.decision_function(X_test)

# 打印结果
print("\nOn Training Data:")
evaluate_print(clf_name, y_train, y_train_scores)
print("\nOn Test Data:")
evaluate_print(clf_name, y_test, y_test_scores)

On Training Data:
IForest ROC:1.0, precision @ rank n:1.0

On Test Data:
IForest ROC:1.0, precision @ rank n:1.0

可见对于PyOD生成的具有十个特征的高维数据,孤立森林比基于LOF的Feature Bagging效果好,而基于LOF的Feature Bagging的效果好于单个LOF检测器。

猜你喜欢

转载自blog.csdn.net/weixin_43595036/article/details/113072799