检测异常值的方法有很多,选择哪种方法需要具体问题具体分析,下面罗列一些常用的方法。
统计学方法:
1、 一维数据的异常值检测
假设我们的数据(一维)服从正态分布,我们可以通过极大似然法估计出均值$\mu$ 和标准差$\sigma$,然后根据$3\sigma$准则:有99.7%的数据会落入区域$\mu\pm3\sigma$中。一般情况下,我们认为在区域$\mu\pm3\sigma$外的点为异常值。
一种更加简便易操作的方法是利用箱线图方法,我们先求出一维数据的第一个四分位数$Q_1$和第三个四分位数$Q_3$,定义$IQR=Q_3-Q_1$,那么对于小于$Q_1-1.5\times IQR$或大于$Q_3+1.5\times IQR$的值认为是异常值。理由和$3\sigma$准则类似,有99.3%的数据会包含在$Q_1-1.5\times IQR$和$Q_3+1.5\times IQR$之间。
还有一种方法是最大标准残差检验法(Grubb检验),也是假设数据服从正态分布。该方法是先对数据集中每一个元素计算$z-score$:$$z=\frac{|x-\mu|}{\sigma}$$,其中$\bar{x}$为数据集的均值,$\sigma$为数据集的标准差。如果$z\ge\frac{N-1}{\sqrt{n}}\sqrt{\frac{t_{\alpha/(2N),N-2}^2}{N-2+t_{\alpha/(2N),N-2}^2}}$,那么$x$维异常值。公式中$N$是数据集中点的个数,$t_{\alpha/(2N),N-2}$是显著水平$\alpha/(2N)$下的$t-$分布的值。
2、多维数据的异常值检测
对于多维的数据,一种检测思想是转化成一维数据进行异常值检测。我们依然假设其服从多元正态分布。计算Mahalanobis距离:$MDist(x,\mu)=(x-\mu)^T\Sigma^{-1}(x-\mu)$,其中$\mu$是均值向量,$\Sigma$是协方差矩阵。$MDist(x,\mu)$服从自由度为$d$的$\chi^2$分布,$d$是数据维度。如果$MDist(x,\mu)>\chi_{d,0.975}^2$,则$x$为异常值。
基于密度的方法
局部异常因子检测算法是一种基于密度的算法,通过计算局部异常因子来判断异常值,计算公式如下:
*可达距离*(Reachability Distance):$RD_k(x, x')=\max(\|x-x^{(k)}\|, \|x-x'\|)$,其中$x^{(k)}$是训练样本中距$x$第$k$近的点
*局部可达密度*(Local Reachability Density):$LRD_k(x)=\big(\frac{1}{k}\sum_{i=1}^k RD_k(x^{(i)},x)\big)$
*局部异常因子*(Local Outlier Factor):$LOF_k(x)=\frac{\frac{1}{k}\sum_{i=1}^k LRD_k(x^{(i)})}{LRD_k(x)}$
从公式中可以看出:当$x^{(i)}$周围的密度比较高而$x$周围的密度比较低时,局部异常因子比较大,$x$就会被看作是异常值。
基于聚类的方法
基于聚类的方法是一类无监督的检测方法,通过考察数据点与簇之间的关系检测异常值。考虑数据样本中的数据点:
* 判断该数据点是否属于某个簇,如果不属于任何簇,则认为是异常值
* 计算该数据点与最近的簇之间的距离,如果距离很远,则认为是异常值
* 判断该数据点是否是小簇或者稀疏簇的一部分,如果是,则该簇中的所有点都是异常值。
上述三条中的第一条可以采用基于密度的聚类方法(如DBSCAN)进行计算。第二条可以采用k-means聚类方法。第三条寻找小簇和稀疏簇一般采用FindCBLOF算法,其方法为:
* 通过设置一个参数$\alpha(0\le\alpha\le1)$来区别大簇和小簇,至少包含数据集中数据点占比为$\alpha$的簇是大簇,其余的为小簇
* 对每个数据点计算基于簇的局部异常因子(CBLOF):对于大簇的点,CBLOF为簇的大小和该点与簇的相似性的乘积;对于小簇的点,CBLOF为小簇的大小和该点于最近的大簇的相似性的乘积。
点与簇的相似性代表了点属于簇的概率,因此CBLOF的值可以检测远离任何簇的异常值,具有最低CBLOF值的点被认为是异常值。
孤立森林
孤立森林(Isolation Forest)也是一种无监督的检测方法。假设一个空间中有很多点,我们用一个随机的超平面去分割这个空间,会得到两个子空间,再分别对每个子空间用一个随机的超平面去分割,如此循环下去,直到被划分出来的子空间只包含一个点停止。直觉上,如果一个点周围的密度很低,则会很早的停留到一个子空间中。这便是孤立森林的思想。
我们从样本集中随机选择$\psi$个数据作为子样本,在这个子样本上构建一棵iTree:随机选择一个特征,在这个特征上,随意选择一个属于特征取值范围内的值$p$,对子样本进行划分,在该特征上,取值小于$p$的点划分到左侧,取值大于等于$p$的点划分到右侧。按照这种方式继续对左右进行划分,直到满足下面两条中的一条则停止:1、只包含一个数据点,不可再分;2、树高达到$\log_2\psi$
重复$t$次,可构建$t$棵iTree,组成iForest。我们用这个iForest来检测异常值:对于一个数据点$x$,我们让它遍历每一棵iTree,计算在每棵iTree中的高度$h(x)$。然后计算异常分数:$s(x,\psi)=2^{-\frac{E(h(x))}{c(\psi)}}$,其中$c(\psi)=2H(\psi-1)-2(\psi-1)/n$,$H(n)=\ln n+\gamma$,$\gamma$为欧拉常数,约为0.5772156649。
如果异常分数非常接近于1,则该点为异常值;如果异常分数比0.5小得多,则为正常值;如果异常分数在0.5附近,则整个样本没有明显的异常值。