基于多维直方图的可解释异常值检测器。
https://medium.com/@wkennedy934?source=post_page---byline--ead0d469557a--------------------------------https://towardsdatascience.com/?source=post_page---byline--ead0d469557a-------------------------------- W·布雷特·肯尼迪
·发表于Towards Data Science ·18 分钟阅读·2024 年 6 月 19 日
–
本文继续介绍可解释的异常值检测系列。上一篇文章(可解释的异常值检测:频繁模式异常值因子(FPOF))讲解了 FPOF 算法,以及异常值检测和可解释性的一些基础知识。本文在此基础上,介绍了 Counts 异常值检测器,这是另一种可解释的异常值检测方法。
正如 FPOF 文章中所述,了解为什么记录是异常值与知道哪些记录是异常值一样重要。事实上,如果我们无法确定为什么被标记为异常值的记录会被标记为异常值,那么异常值检测的价值往往有限。例如,如果异常值检测系统识别出可能是安全威胁的内容,为了高效、有效地调查这一问题,必须知道是什么不寻常:为什么会被识别为异常。同样地,当异常值检测系统识别出可能的欺诈行为、机器故障、科学发现、异常有效(或无效)的商业实践,或其他异常值时,也同样需要了解这些异常的原因。
尽管探测器本身使用的算法通常很容易理解,但单个预测结果通常并非如此。例如,标准的探测器如隔离森林(Isolation Forest,IF)、局部离群因子(Local Outlier Factor,LOF)和 k 近邻(kNN)等,虽然它们的算法很容易理解,但生成的得分可能很难评估,尤其是在高维数据中。要确定为何某些记录被标记为离群值并且是异常的,往往非常困难。
原则上,解释离群值是相当可管理的。对于大多数离群值来说,只有一小部分特征具有异常值(极少数离群值在每个特征上都有异常值)。知道哪些特征是不寻常的,以及这些特征是如何不寻常的,通常就是理解为什么离群值是离群值所需的全部内容,但不幸的是,这些信息通常是不可得的。
只有少数离群值探测器提供它们生成的得分的解释。这些包括FPOF和基于关联规则的相关离群值检测方法(这两者都在《Python 中的离群值检测》中有介绍),仅举两个例子。但,可解释的模型远少于人们希望的那样。出于这个原因,我开发了两个可解释的模型,计数离群值探测器(COD)和数据一致性检查器,这两个模型我至今仍在维护。
它们的工作原理差异很大,但都是有用的工具。前者将在本文中讨论;数据一致性检查器将在即将发布的文章中介绍。此外,两者均在《Python 中的离群值检测》中有涉及;本文的其余部分来自于关于计数离群值探测器的章节。
计数离群值探测器
计数离群值探测器的主页是github.com/Brett-Kennedy/CountsOutlierDetector。
计数离群值探测器(Counts Outlier Detector,COD)是一种适用于表格数据的离群值探测器,旨在为被标记为离群值的行及其具体得分提供清晰的解释。更具体来说,COD 是一个基于多变量直方图的模型:它将数据分为多个区间,并通过识别计数异常低的区间中的记录来识别离群值。
这是一种有效、高效且可解释的离群值检测技术。多维直方图确实存在一些非常现实的局限性,我们将在这里讨论这些问题,但正如我们接下来将讨论的,这些问题是可以解决的。对该方法的测试和评估表明,它是一种强大的探测器,常常与更标准的工具一样有用,并且具有显著的可解释性优势。
基于直方图的离群值检测介绍
在解释 COD 之前,我将解释另一个较简单的基于直方图的异常值检测算法,它先于 COD 被提出,叫做 HBOS(基于直方图的异常值分数)。这是流行的PyOD(Python 异常值检测)库的一部分,并且通常是一个有效的工具。也存在其他基于直方图的异常值检测算法,它们的工作原理类似。
HBOS 基于一个非常简单的思想工作:要确定表格中的某一行有多不寻常,它只是评估该行中每个单独值有多不寻常。为此,每个值都会与其所在列进行比较。这是通过首先创建一个直方图来表示每个特征(HBOS 仅处理数值数据),并将每个值与直方图进行比较来实现的。
还有其他方法可以确定一个数值相对于表格列(或其他数值序列)的异常程度。核密度估计、累积分布和其他方法也能很好地工作。但直方图是一个简单有效的手段。其他方法已在Python 中的异常值检测中介绍,但为了简化起见,且由于 COD 使用的是这种方法,我们将在本文中仅讨论直方图。
HBOS 将每个特征划分为一组等宽的区间。每个特征可以通过直方图表示,例如:
在这种情况下,直方图使用了 20 个区间;对于 HBOS,我们通常会为每个特征使用大约 5 到 50 个区间。如果表格有 30 个特征,那么就会有 30 个像这样的直方图。
任何位于区间中计数非常低的值都会被视为不寻常。在这个直方图中,例如,6.0 左右的值会被认为是稀有的,因为它所在的区间在训练数据中有很少的示例;因此,它会被赋予相对较高的异常值评分。另一方面,4.0 的值会被认为是非常正常的,因此会被赋予较低的异常值评分。
因此,为了评估一行,HBOS 确定该行中每个单独值的异常程度(相对于其特征的直方图),给每个值打分,并将这些分数相加。通过这种方式,具有最多稀有值的行,以及具有最稀有稀有值的行,将获得最高的总体异常值评分;如果一行具有一个对于其列非常稀有的值,或者具有多个对于其列适度稀有的值,它可能会获得较高的总体异常值评分。
这意味着 HBOS 只能找到一种特定类型的异常值:包含一个或多个不寻常单一值的行;它无法识别包含不寻常值组合的行。这是一个非常大的限制,但 HBOS 能够非常快速地工作,并且它识别出的异常值往往是真正的强异常值,即使它也会错过许多异常值。
但 HBOS 的一个主要局限性是它会忽略不寻常的值组合。例如,在描述人的表格中,某条记录可能有 130 岁的年龄或 7 英尺 2 英寸的身高,HBOS 会检测到这些异常。但也可能有一条记录的年龄是 2 岁,身高是 5 英尺 10 英寸。虽然年龄和身高都很常见,但它们的组合却不常见:这是两个特征的稀有组合的一个例子。
也有可能出现三、四个或更多特征的稀有组合,这些组合可能和不寻常的单一值一样重要。
计数异常值检测器概述
COD 扩展了基于直方图的异常值检测方法,支持多维直方图。这使得 COD 能够识别稀有的 2、3 个或更多值的组合的异常值,以及可以通过标准的(1 维)基于直方图的方法(如 HBOS)检测到的稀有单一值。它能够识别出不寻常的单一值,例如 7 英尺 2 英寸的身高,也能检测到某人年龄为 2 岁,身高为 5 英尺 10 英寸的情况。
我们首先查看二维直方图,但 COD 支持最多 6 维的直方图(我们将在下面描述为什么它不支持更多维度,实际上,通常使用 2 维、3 维或 4 维会效果最好)。
二维直方图可以类似于热图查看。在下面的图像中,我们可以看到一个二维空间的直方图,其中每个维度的数据被分为 13 个桶,形成 169 个(13 x 13)二维空间的桶。我们还可以看到一个点(被圈住)是二维空间中的异常值。这个点在一个桶中,只有很少的项目(在这种情况下只有一个项目),因此当检查这个二维空间时,可以将其识别为异常值。
这个点在 1 维空间中既不是异常值,也不在 x 维度或 y 维度中不寻常,因此会被 HBOS 和其他仅检查单一维度的工具忽略。
与 HBOS 类似,COD 会为每个单一特征创建一个 1 维直方图。但随后,COD 还会为每一对特征创建一个这样的二维直方图,因此能够检测到任何不寻常的特征对值。相同的思路也可以应用于任何维度的组合。虽然绘制起来更困难,但 COD 会为每组三个特征(每个桶是一个立方体)创建三维直方图,依此类推。然后,它会计算每个桶中的计数(使用训练数据),并能够识别出异常值:出现在计数异常低的桶中的值(或值的组合)。
维度灾难
尽管基于每一组 2、3 个甚至更多特征创建直方图是有效的,但通常不可能使用所有特征来创建直方图,特别是当数据中有超过 6 或 7 个特征时。由于所谓的维度灾难,我们可能会有比数据记录更多的桶。
例如,如果有 50 个特征,即使每个特征只使用 2 个箱子,我们在一个 50 维的直方图中将会有 2 的 50 次方个箱子,这显然比数据记录的数量大得多。即使只有 20 个特征(并且每个特征使用 2 个箱子),我们也会有 2 的 20 次方,超过一百万个箱子。因此,最终我们可能会发现大多数箱子没有任何记录,而有记录的箱子也只包含一两个项目。
大多数数据都是相对偏斜的,特征之间通常存在关联,因此其影响不会像数据在空间中均匀分布时那样强烈,但使用基于直方图的异常检测方法一次性考虑过多特征仍然可能会导致问题。
然而,幸运的是,这实际上并不是问题。并不需要创建高维直方图;低维直方图就足够检测最相关的(也是最易解释的)异常值。例如,检查每个 1 维、2 维和 3 维空间就足以识别每个不寻常的单一值、值对和值三元组。这些是最容易理解的异常值,并且可以说是最相关的(或者至少通常是最相关的)。如果需要(且数据足够),也可以使用 COD 检查 4 维、5 维或 6 维空间。
COD 算法
COD 采用的方法是先检查 1 维空间,再检查 2 维空间,然后是 3 维空间,依此类推,直到最多 6 维。如果一个表格有 50 个特征,那么它将检查(50 选择 1)个 1 维空间(找到不寻常的单一值),然后是(50 选择 2)个 2 维空间(找到不寻常的值对),然后是(50 选择 3)个 3 维空间(找到不寻常的值三元组),依此类推。这覆盖了大量的空间,但也意味着每一条记录都会被彻底检查,而且异常值(至少在低维空间中)不会被遗漏。
使用直方图还允许相对快速的计算,因此这通常是相当可行的。在特征数量非常大的情况下,它可能会出现问题,但在这种情况下,几乎所有的异常值检测器最终都会出现问题。如果一个表格有许多特征(例如几十个或几百个),可能需要将 COD 限制为 1 维空间,仅找到不寻常的单一值——在这种情况下,这可能已经足够了。但对于大多数表格,COD 能够相当好地检查最多到 4 维、5 维或 6 维的空间。
使用直方图也消除了许多离群值检测方法中使用的距离度量,包括一些最常用的方法。虽然在较低维度下非常有效的方法(如 LOF、kNN 和其他几种方法)会一次性使用所有特征,但它们在较高维度时非常容易受到维度灾难的影响。例如,kNN 通过识别与其 k 个最近邻距离较远的点来标记离群值。这是一种合理且通常有效的方法,但在高维度下,点与点之间的距离计算可能变得极不可靠,这使得使用 kNN 或类似算法识别离群值变得不可能。
通过一次仅检查较低维度,COD 能够处理比许多其他离群值检测方法更多的特征。
限制评估在较低维度
要理解为什么只检查大约 3 到 6 个维度就足够了,我们可以通过 4 维离群值的例子来说明。4 维离群值是指那些是四个特征的稀有组合,但不是任何 1、2 或 3 个特征的稀有组合。也就是说,每个单一特征、每对特征以及每组三个特征都相当常见,但所有四个特征的组合是稀有的。
这是可能的,且确实会发生,但实际上相当少见。对于大多数具有稀有四个特征组合的记录,至少其中两个或三个特征的子集通常也会是稀有的。
在我进行这项工作及其他工具开发时,我发现一个有趣的事情,那就是大多数离群值可以通过相对较小的特征集合来描述。例如,考虑一个表示房价的表格(有四个特征),我们可能会有以下特征:平方英尺、房间数量、楼层数量和价格。任何单一的异常值都可能会很有趣。同样,对于任何特征对(例如,较小的平方英尺与较多楼层的组合,或较小的平方英尺与高价格的组合),以及可能的任何特征三元组也如此。但是,所有四个特征的组合能有多么不寻常,却没有任何单一特征、特征对或特征三元组不寻常,实际上是有限制的。
通过仅检查较低维度,我们可以覆盖大部分离群值。覆盖的维度越多,我们发现的离群值就越多,但收益递减,不论是在离群值的数量上,还是在其相关性上。
即使存在一些合法的离群值,这些离群值只能通过例如六个或七个特征来描述,它们通常也很难解释,并且可能比那些只有单一稀有值、单一对特征或稀有值三元组的离群值重要性低。它们也变得难以在统计上量化,因为当涉及到多个特征时,特征值的组合数量可能会非常庞大。
通过处理少量特征,COD 提供了一个很好的折衷方案,介于那些独立考虑每个特征的检测器(如 HBOS、z-score、四分位数范围、基于熵的测试等)和那些同时考虑所有特征的离群值检测器(如局部离群因子和 KNN)之间。
COD 如何去除解释中的冗余
计数离群值检测器通过首先检查每一列,识别出与其列相比异常的所有值(一维离群值)。
然后,它检查每一对列,识别每对列中具有异常值的行(二维离群值)。检测器接着考虑三列的集合(识别三维离群值),四列的集合(识别四维离群值),以此类推。
在每个阶段,算法都会寻找异常实例,排除在低维空间中已经标记的值或组合。例如,在上面描述的人物表格中,身高 7 英尺 2 英寸会是稀有的。鉴于这一点,任何年龄和身高(或身高和其他任何东西)的组合,只要身高是 7 英尺 2 英寸,都会是稀有的,因为 7 英尺 2 英寸本身就是稀有的。因此,没有必要识别例如 7 英尺 2 英寸和 25 岁作为一个稀有组合;它之所以稀有,仅仅因为 7 英尺 2 英寸稀有,将其作为二维离群值报告是多余的。严格按照身高报告为一维离群值(仅基于身高)能够提供最清晰、最简单的解释,适用于包含此身高的所有行。
因此,一旦我们将 7 英尺 2 英寸识别为一维离群值,就不再将该值纳入二维离群值、三维离群值等的检查中。然而,大多数值(相对于当前数据集更典型的身高)仍然被保留,这使我们能够进一步检查数据并识别异常的组合。
同样,任何在二维空间中的稀有值对都不会被考虑在三维及更高维度的空间中;任何在三维空间中的稀有值三元组将在四维及更高维度的空间中被排除;依此类推。
因此,每个异常值都尽可能使用最少的特征进行报告,这使得每个异常的解释尽可能简单。
然而,任何一行都可能被多次标记。例如,一行可能在 F 列有一个异常值;在 A 列和 E 列有一对异常值;在 D 列和 F 列有另一对异常值;以及在 B 列、C 列和 D 列有一组三个异常值。该行的总离群分数将是这些分数的总和。
可解释性
我们可以为数据集中的每个离群值识别出其异常的特征集合。这样,就能够提供非常清晰的解释。而且,鉴于大多数离群值是在一维或二维空间中的,绝大多数解释可以通过视觉方式呈现(下面会展示一些示例)。
评分
计数异常值检测器(Counts Outlier Detector)得名于它检查每个 bin 的确切计数。在每个空间中,会识别出计数异常低的 bins(如果有的话),任何在这些 bins 中的记录都会被识别为存在异常。
然后使用的评分系统非常简单,这进一步支持了可解释性。每个稀有值或组合都会被等同评分,而不考虑维度或 bins 中的计数。每一行仅根据发现的异常数量进行评分。
这可能会丧失一些精度(稀有的组合会与非常稀有的组合得分相同),但能够显著加快执行速度,并且结果更具可解释性。这还避免了任何复杂性,避免了在不同空间中对异常值进行加权的任意性。例如,可能不清楚如何比较 4D 空间中的异常值与 2D 空间中的异常值。COD 消除了这一问题,平等对待每个空间。因此,尽管这样做会牺牲一些得分的细节,但工具的重点是可解释性,并且对准确度的影响很小(而且通常会产生积极效果——将异常值等同处理有一种正则化效果)。
默认情况下,只有强烈异常的值或组合会被标记。此过程可以通过设置阈值参数进行调整。
示例
这里,我们提供一个使用 COD 的简单示例,使用 鸢尾花 数据集,这是一个由 scikit-learn 提供的玩具数据集。要执行此操作,首先必须导入 CountsOutlierDetector 类。然后,我们只需创建 CountsOutlierDetector 的实例,并调用 fit_predict()。
import pandas as pd
from sklearn.datasets import load_iris
from counts_outlier_detector import CountsOutlierDetector
iris = load_iris()
X, y = iris.data, iris.target
det = CountsOutlierDetector()
results = det.fit_predict(X)
结果包括传入数据集中每一行的评分,以及标记这些行的原因信息,还包括关于数据集中异常值的总结统计。
GitHub 页面提供了多个示例笔记本,帮助你入门,并帮助调整超参数(与几乎所有的异常值检测器一样,超参数可能会影响哪些数据被标记为异常)。但是,通常使用 COD 和这个示例一样简单。
提供在 GitHub 上的笔记本也深入探讨了其性能,并涵盖了一些实验,旨在确定通常需要一次性检查多少个特征,才能找到数据集中相关的异常值。如所示,通常将分析限制在 2 或 3 维的直方图中,就足以识别数据集中的最相关异常值。测试是使用来自 OpenML 的大量数据集进行的。
可视化解释
COD 提供了多种方法,帮助理解找到的异常值。第一个是 explain_row() API,用户可以获得针对指定行的评分依据的详细解释。
如所示,异常值行可能包含任意数量的异常值。对于每个发现的一维异常值,都会展示条形图或直方图,将该值与该列中的其他值进行对比。为了提供更多上下文,其他被标记为异常的值也会显示出来。
下图展示了来自 GitHub 页面上 Examples_Counts_Outlier_Detector 笔记本的一个异常值(该笔记本使用了简单的合成数据)。这是第 1 行的一个异常值,在列 A 中有一个不寻常的值。左侧窗格展示了列 A 的分布,绿色垂直线表示区间边界,红色垂直线表示标记的异常值。这个例子使用了 7 个区间(将数值特征划分为:‘非常低’、‘低’、‘中低’、‘中’、‘中高’、‘高’、‘非常高’)。
右侧窗格展示了直方图。由于有 5 个区间为空(该列中的所有值都是‘非常低’或‘非常高’),这里仅显示了 2 个区间。图示表明,‘非常高’值在此特征中非常稀有,明显少于‘非常低’值,因此被视为异常值。
对于任何发现的二维异常值,会展示散点图(如果是两个数值列)、条形图(如果是一个数值列和一个类别列),或热图(如果是两个类别列)。这能清楚地显示该值与二维空间中其他值的比较。
这里展示了一个例子(来自 GitHub 网站上的 demo_OpenML 笔记本),包含两个数值特征。除了散点图(左侧窗格),还显示了一个热图(右侧窗格),用于展示每个区间的计数:
这里使用的是 OpenML 的海螺数据集 (www.openml.org/search?type=data&sort=runs&id=183&status=active,依据 CC BY 4.0 许可发布)。被解释的行(行 2407)在两个图中都作为星形显示。在此示例中,每个特征使用了 3 个区间,因此二维空间有 9 个区间。被解释的行位于一个只有 36 条记录的区间中。相比之下,记录最多的区间包含 2212 条数据。
在散点图中(左侧窗格),该区间中的其他记录以红色显示。计数异常低的其他区间记录以黄色显示。
理解一维和二维异常值是直观的,因为可用的可视化方式非常易于理解。处理三维及更高维度的异常值概念上类似,尽管可视化较为困难。只要维度数合理低,依然可以管理,但不如一维或二维直观。
对于超过二维的异常值,将展示条形图,显示当前空间(特征组合)内每种值组合的计数,并提供标记值组合/区间的计数及其上下文。
以下是对 Abalone 数据集中识别出的一个离群行的部分解释,在这种情况下,基于性别、直径和整体重量特征,包含了一个三维离群值。
还可以调用 explain_features() API,以进一步深入了解任何这些内容。在这种情况下,它提供了每种组合的计数,我们可以在上面的图表中看到,组合(Sex=I,Diameter=Med;Whole_weight=Med)的计数仅为 12:
为了获得最高水平的可解释性,我建议将 max_dimensions 限制为 2,这样将仅检查数据集中的 1 维和 2 维离群值,并以一维条形图或直方图,或者二维图的形式呈现结果,这样可以获得对呈现空间的最完整理解。然而,使用 3 维或更多维度(如上面性别、直径和整体重量的图表)仍然是合理可解释的。
精度实验
尽管 COD 的优势在于其可解释性,但算法仍然需要能够识别大多数有意义的离群值,并且不应错误地标记更多典型的记录。
实验(在 github 页面中描述)表明,Counts Outlier Detector 与 Isolation Forest 具有竞争力,至少在一种被称为doping的测试形式中有所表现:在这种测试中,真实数据集中的少数值会被修改(随机修改,但通常会创建异常记录——即在特征之间没有正常关联的记录),并测试离群值检测器是否能够识别这些修改的行。
评估离群值检测器还有其他有效的方法,即使使用 dopинг过程,数据的修改方式、修改的记录数量等也可能有所不同。在这些测试中,COD 略微优于 Isolation Forest,但在其他测试中,Isolation Forest 可能会比 COD 表现更好,其他检测器也可能如此。然而,这确实证明了 COD 在精度上表现良好,并且与标准离群值检测器在竞争中不相上下。
安装
该工具使用了一个单独的类——CountsOutlierDetector,该类需要包含在任何使用该工具的项目中。可以通过复制或下载定义该类的单个.py 文件,counts_outlier_detector.py并导入该类来实现。
结论
该检测器的优点包括:
-
它能够尽可能清晰地提供每个离群值的解释。为了说明一行数据的得分为何如此,给出的解释只使用了必要的特征来解释其得分。
-
它能够提供每个空间的完整统计数据,这使得它能够提供每一行离群性的完整背景。
在异常值检测中普遍认为,每个检测器会识别某些类型的异常值,通常使用多个检测器来可靠地捕捉数据集中的大部分异常值是有益的。COD 可能仅仅为了这个目的而有用:它是一个简单且有用的异常值检测器,可能会检测到与其他检测器有所不同的异常值。
然而,在异常值检测中,可解释性通常非常重要,但不幸的是,目前可用于可解释的异常值检测的选项非常少。COD 提供了为数不多的选择之一,因此可能值得尝试。
所有图像均由作者创作。
4724

被折叠的 条评论
为什么被折叠?



