异常点检测,有时也叫离群点检测,英文一般叫做Novelty Detection或者Outlier Detection,是比较常见的一类非监督学习算法,这里就对异常点检测算法做一个总结。
一、1. 异常点检测算法使用场景
什么时候我们需要异常点检测算法呢?常见的有三种情况。一是在做特征工程的时候需要对异常的数据做过滤,防止对归一化等处理的结果产生影响。二是对没有标记输出的特征数据做筛选,找出异常的数据。三是对有标记输出的特征数据做二分类时,由于某些类别的训练样本非常少,类别严重不平衡,此时也可以考虑用非监督的异常点检测算法来做。
二、2. 异常点检测算法常见类别
异常点检测的目的是找出数据集中和大多数数据不同的数据,常用的异常点检测算法一般分为三类。
第一类是基于统计学的方法来处理异常数据,这种方法一般会构建一个概率分布模型,并计算对象符合该模型的概率,把具有低概率的对象视为异常点。比如特征工程中的RobustScaler方法,在做数据特征值缩放的时候,它会利用数据特征的分位数分布,将数据根据分位数划分为多段,只取中间段来做缩放,比如只取25%分位数到75%分位数的数据做缩放。这样减小了异常数据的影响。
第二类是基于聚类的方法来做异常点检测。这个很好理解,由于大部分聚类算法是基于数据特征的分布来做的,通常如果我们聚类后发现某些聚类簇的数据样本量比其他簇少很多,而且这个簇里数据的特征均值分布之类的值和其他簇也差异很大,这些簇里的样本点大部分时候都是异常点。比如我之前讲到的BIRCH聚类算法原理和DBSCAN密度聚类算法都可以在聚类的同时做异常点的检测。
第三类是基于专门的异常点检测算法来做。这些算法不像聚类算法,检测异常点只是一个赠品,它们的目的就是专门检测异常点的,这类算法的代表是One Class SVM和Isolation Forest.
下文主要会对One Class SVM和Isolation Forest做详细的讨论分析。
三、3. One Class SVM算法
One Class SVM也是属于支持向量机大家族的,但是它和传统的基于监督学习的分类回归支持向量机不同,它是无监督学习的方法,也就是说,它不需要我们标记训练集的输出标签。
那么没有类别标签,我们如何寻找划分的超平面以及寻找支持向量呢?One Class SVM这个问题的解决思路有很多。这里只讲解一种特别的思路SVDD, 对于SVDD来说,我们期望所有不是异常的样本都是正类别,同时它采用一个超球体而不是一个超平面来做划分,该算法在特征空间中获得数据周围的球形边界,期望最小化这个超球体的体积,从而最小化异常点数据的影响。
假设产生的超球体参数为中心 \(o\)和对应的超球体半径 \(r>;0\) ,超球体体积 \(V(r)\) 被最小化,中心\(o\) 是支持向量的线性组合;跟传统SVM方法相似,可以要求所有训练数据点 \(x_{i}\) 到中心的距离严格小于 $r $,但同时构造一个惩罚系数为 \(C\) 的松弛变量 \(\xi_i\),优化问题如下所示:
\[ \underbrace{min}_{r,o}V(r) + C\sum\limits_{i=1}^m\xi_i \]
\[ ||x_i-o||_2 \leq r + \xi_i,\;\; i=1,2,...m \]
\[ \xi_i \geq 0,\;\;i=1,2,...m \]
和之前讲的支持向量机系列类似的求解方法,在采用拉格朗日对偶求解之后,可以判断新的数据点 \(z\) 是否在类内,如果\(z\)到中心的距离小于或者等于半径\(r\),则不是异常点,如果在超球体以外,则是异常点。
在sklearn中,我们可以用svm包里面的OneClassSVM来做异常点检测。OneClassSVM也支持核函数,所以普通SVM里面的调参思路在这里也适用。
四、4. Isolation Forest算法
Isolation Forest(以下简称IForest)是周志华老师的学生提出来的,主要是利用集成学习的思路来做异常点检测,目前几乎成为异常点检测算法的首选项,我之前在Bagging与随机森林算法原理小结第4.3节中也简略讲解了IForest的思路,它是随机森林大家族的一员。
算法本身并不复杂,主要包括第一步训练构建随机森林对应的多颗决策树,这些决策树一般叫iTree,第二步计算需要检测的数据点\(x\)最终落在任意第t颗iTree的层数\(h_t(x)\)。然后我们可以得出\(x\)在每棵树的高度平均值\(h(x)\)。第三步根据\(h(x)\)判断\(x\)是否是异常点。
对于第一步构建决策树的过程,方法和普通的随机森林不同。
首先采样决策树的训练样本时,普通的随机森林要采样的样本个数等于训练集个数。但是iForest不需要采样这么多,一般来说,采样个数要远远小于训练集个数。原因是我们的目的是异常点检测,只需要部分的样本我们一般就可以将异常点区别出来了。
另外就是在做决策树分裂决策时,由于我们没有标记输出,所以没法计算基尼系数或者和方差之类的划分标准。这里我们使用的是随机选择划分特征,然后在基于这个特征再随机选择划分阈值,进行决策树的分裂。直到树的深度达到限定阈值或者样本数只剩一个。
第二步计算要检测的样本点在每棵树的高度平均值\(h(x)\)。首先需要遍历每一颗iTree,得到检测的数据点\(x\)最终落在任意第t颗iTree的数层数\(h_t(x)\)。这个\(h_t(x)\)代表的是树的深度,也就是离根节点越近,则\(h_t(x)\)越小,越靠近底层,则\(h_t(x)\)越大,根节点的高度为0.
第三步是据\(h(x)\)判断\(x\)是否是异常点。我们一般用下面的公式计算\(x\)的异常概率分值:
\[ s(x,m) = 2^{-\frac{h(x)}{c(m)}} \]
, \(s(x,m)\)的取值范围是[0,1],取值越接近于1,则是异常点的概率也越大。其中,m为样本个数。的表达式为:
\[ c(m) =2\ln(m-1) + \xi - 2\frac{m-1}{m}, \; \xi 是欧拉常数 \]
从\(s(x,m)\)表示式可以看出,如果高度\(h(x) \to 0\), 则\(s(x,m) \to 1\),即是异常点的概率是100%,如果高度\(h(x) \to m-1\), 则\(s(x,m) \to 0\),即不可能是异常点。如果高度\(h(x) \to c(m)\), 则\(s(x,m) \to 0.5\),即是异常点的概率是50%,一般我们可以设置$s(x,m)的一个阈值然后去调参,这样大于阈值的才认为是异常点。
在sklearn中,我们可以用ensemble包里面的IsolationForest来做异常点检测。
五、5. 异常点检测算法小结
IForest目前是异常点检测最常用的算法之一,它的优点非常突出,它具有线性时间复杂度。因为是随机森林的方法,所以可以用在含有海量数据的数据集上面。通常树的数量越多,算法越稳定。由于每棵树都是互相独立生成的,因此可以部署在大规模分布式系统上来加速运算。对于目前大数据分析的趋势来说,它的好用是有原因的。
但是IForest也有一些缺点,比如不适用于特别高维的数据。由于每次切数据空间都是随机选取一个维度和该维度的随机一个特征,建完树后仍然有大量的维度没有被使用,导致算法可靠性降低。此时推荐降维后使用,或者考虑使用One Class SVM。
另外iForest仅对即全局稀疏点敏感,不擅长处理局部的相对稀疏点 ,这样在某些局部的异常点较多的时候检测可能不是很准。
而One Class SVM对于中小型的数据分析,尤其是训练样本不是特别海量的时候用起来经常会比iForest顺手,因此比较适合做原型分析。
(欢迎转载,转载请注明出处。欢迎沟通交流: 微信:nickchen121)