目录

1 背景

2 算法

2.1 定义

2.2  iForest的构建

2.3 iForest 预测

3 python示例

4 特点


1 背景

        现有的异常检测方法主要是通过对正常样本的描述,给出一个正常样本在特征空间中的区域,对于不在这个区域中的样本,视为异常。这些方法的主要缺点是,异常检测器只会对正常样本的描述做优化,而不会对异常样本的描述做优化,这样就有可能造成大量的误报,或者只检测到少量的异常。

        异常的两个特点:异常数据只占很少量、异常数据特征值和正常数据差别很大。

        孤立森林,不再是描述正常的样本点,而是要孤立异常点,由周志华教授等人于2008年在第八届IEEE数据挖掘国际会议上提出,之后又于2012年提出了改进版本。

        先了解一下该算法的动机。目前学术界对异常(anomaly detection)的定义有很多种,在孤立森林(iForest)中,异常被定义为“容易被孤立的离群点 (more likely to be separated)”,可以将其理解为分布稀疏且离密度高的群体较远的点。 在特征空间里,分布稀疏的区域表示事件发生在该区域的概率很低,因而可以认为落在这些区域里的数据是异常的。孤立森林是一种适用于连续数据(Continuous numerical data)无监督异常检测方法,即不需要有标记的样本来训练,但特征需要是连续的。对于如何查找哪些点容易被孤立(isolated),iForest使用了一套非常高效的策略。在孤立森林中,递归地随机分割数据集,直到所有的样本点都是孤立的。在这种随机分割的策略下,异常点通常具有较短的路径。

        具体来说,该算法利用一种名为孤立树

spark java 孤立森林 训练 孤立森林算法缺点_算法

二叉搜索树结构来孤立样本。由于异常值的数量较少且与大部分样本的疏离性,因此,异常值会被更早的孤立出来,也即异常值会距离

spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_02

的根节点更近,而正常值则会距离根节点有更远的距离。此外,相较于LOF,K-means等传统算法,孤立森林算法对高纬数据有较好的鲁棒性。

        从下图我们可以直观的看到,相对更异常的spark java 孤立森林 训练 孤立森林算法缺点_算法_03只需要4次切割就从整体中被分离出来,而更加正常的点spark java 孤立森林 训练 孤立森林算法缺点_异常检测_04经过了11次分割才从整体中分离出来。这也体现了孤立森林算法的基本思想。

spark java 孤立森林 训练 孤立森林算法缺点_人工智能_05

2 算法

2.1 定义

        我们先给出孤立树(Isolation Tree)和样本点spark java 孤立森林 训练 孤立森林算法缺点_机器学习_06在孤立树中的路径长度

spark java 孤立森林 训练 孤立森林算法缺点_人工智能_07

的定义。        孤立树:若为孤立树spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_08的一个节点,spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_09存在两种情况:没有子节点外部节点,有两个子节点

spark java 孤立森林 训练 孤立森林算法缺点_机器学习_10

和一个test的内部节点。在spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_09的test由一个属性 q 和一个分割点 p 组成,

spark java 孤立森林 训练 孤立森林算法缺点_人工智能_12

的点属于spark java 孤立森林 训练 孤立森林算法缺点_算法_13,反之属于spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_14        样本点spark java 孤立森林 训练 孤立森林算法缺点_机器学习_06在孤立树中的路径长度

spark java 孤立森林 训练 孤立森林算法缺点_人工智能_07

:样本点spark java 孤立森林 训练 孤立森林算法缺点_机器学习_06

spark java 孤立森林 训练 孤立森林算法缺点_机器学习_18

的根节点到叶子节点经过的边的数量。

2.2  iForest的构建

        下面,我们来详细介绍孤立森林算法。该算法大致可以分为两个阶段,第一个阶段我们需要训练出spark java 孤立森林 训练 孤立森林算法缺点_机器学习_19颗孤立树,组成孤立森林。随后我们将每个样本点带入森林中的每棵孤立树,计算平均高度,之后再计算每个样本点的异常值分数。

(1)第一阶段

  1. 为给定数据集,,从中随机抽取个样本点构成的子集放入根节点。
  2. d 个维度中随机指定一个维度 q,在当前数据中随机产生一个切割点 p,。
  3. 切割点 p 生成了一个超平面,将当前数据空间划分为两个子空间:指定维度小于 p 的样本点放入左子节点,大于或等于 p 的放入右子节点。
  4. 递归Step2和Step3,直至所有的叶子节点都只有一个样本点或者孤立树  已经达到指定的高度。
  5. 循环Step1至Step4,直至生成个孤立树。

(2)第二阶段

       Step1: 对于每一个数据点 spark java 孤立森林 训练 孤立森林算法缺点_人工智能_20,令其遍历每一颗孤立树

spark java 孤立森林 训练 孤立森林算法缺点_算法_21

,计算点spark java 孤立森林 训练 孤立森林算法缺点_人工智能_20在森林中的平均高度 

spark java 孤立森林 训练 孤立森林算法缺点_机器学习_23

,对所有点的平均高度做归一化处理。异常值分数的计算公式如下所示:                      

spark java 孤立森林 训练 孤立森林算法缺点_机器学习_24

        其中,

               

spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_25

                 

spark java 孤立森林 训练 孤立森林算法缺点_spark java 孤立森林 训练_26

        S(x,n) 就是记录x在n个样本的训练数据构成的iTree的异常指数,S(x,n)取值范围为[0,1]。

  就是记录 x 在由 n 个样本的训练数据构成 iTree 的异常指数,取值范围为[0, 1],异常情况的判断分以下几种情况

  • 1,越接近1表示是异常点的可能性高
  • 2,越接近0表示是正常点的可能性高
  • 3,如果大部分的训练样本的S(x,n)都接近于0.5,说明整个数据集都没有明显的异常值

   如果是随机选属性,随机选属性值,一棵树这么随机选肯定不行,但是把多棵树结合起来就变的强大了。

        4个测试样本遍历一棵iTree的例子如下:

                      

spark java 孤立森林 训练 孤立森林算法缺点_算法_27

        可以看到d最有可能是异常,因为其最早就被孤立(isolated)了。

2.3 iForest 预测

        IForest构造好之后,对测试进行预测,需要进行综合每棵树的结果,于是 PathLength 表示记录 x 在每棵树的高度均值,另外计算需要改进,在生成叶子节点时,算法记录了叶子节点包含的记录数量,这时候需要用这个数量估计一下平均高度的,其计算方法如下:

spark java 孤立森林 训练 孤立森林算法缺点_机器学习_28

        在处理高维数据时,可以对算法进行改进,采样之后并不是把所有的属性都用上,而是用峰度系数Kurtosis挑选一些有价值的属性,再进行iTree的构造,这跟随机森林就更像了,随机选记录,再随机选属性。 

3 python示例

# _*_coding:utf-8_*_
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest

rng = np.random.RandomState(42)

# Generate  train data
X = 0.3 * rng.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
X = 0.3 * rng.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
X_outliers = rng.uniform(low=-4, high=4, size=(20, 2))

# fit the model
clf = IsolationForest(max_samples=100,
                      random_state=rng, contamination='auto')
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test_1 = clf.predict(X_test)
y_pred_test = clf.predict(X_outliers)
print(y_pred_test_1)

xx, yy = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.title("IsolationForest")
plt.contourf(xx, yy, Z, camp=plt.cm.Blues_r)
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white',
                 s=20, edgecolor='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='green',
                 s=20, edgecolor='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='red',
                s=20, edgecolor='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([b1, b2, c],
           ["training observations",
            "new regular observations", "new abnormal observations"],
           loc="upper left")
plt.show()

4 特点

  1. iForest具有线性时间复杂度。因为是ensemble的方法,所以可以用在含有海量数据的数据集上面。通常树的数量越多,算法越稳定。由于每棵树都是互相独立生成的,因此可以部署在大规模分布式系统上来加速运算。
  2. 2. iForest不适用于特别高维的数据。由于每次切数据空间都是随机选取一个维度,建完树后仍然有大量的维度信息没有被使用,导致算法可靠性降低。高维空间还可能存在大量噪音维度或无关维度(irrelevant attributes),影响树的构建。对这类数据,建议使用子空间异常检测(Subspace Anomaly Detection)技术。此外,切割平面默认是axis-parallel的,也可以随机生成各种角度的切割平面,详见“On Detecting Clustered Anomalies Using SCiForest”。
  3. 3. iForest仅对Global Anomaly 敏感,即全局稀疏点敏感,不擅长处理局部的相对稀疏点 (Local Anomaly)。目前已有改进方法发表于PAKDD,详见“Improving iForest with Relative Mass”。
  4. 4. iForest推动了重心估计(Mass Estimation)理论发展,目前在分类聚类和异常检测中都取得显著效果,发表于各大顶级数据挖掘会议和期刊(如SIGKDD,ICDM,ECML)。

        Isolation Forest 算法主要有两个参数:一个是二叉树的个数;另一个是训练单棵ITree时候抽取样本的数目。实验表明,当设定为100棵树,抽样样本为256条的时候,iForest 在大多数情况下就可以取得不错的效果。这也体现了算法的简单,高效。

  Isolation Forest 是无监督的异常检测算法,在实际应用中,并不需要黑白标签。需要注意的是:

  1. 如果训练样本中异常样本的比例比较高,违背了先前提到的异常检测的基本假设,可能最终的效果会受到影响;
  2. 异常检测根具体的应用场景紧密相关,算法检测出的“异常”不一定是我们实际想要的,比如,在识别虚假交易时,异常的交易未必就是虚假的交易。所以,在特征选择时,可能需要过滤不太相关的特征,以免识别出一些不太相关的“异常”。

iForest (Isolation Forest)孤立森林 异常检测 入门篇:iForest (Isolation Forest)孤立森林 异常检测 入门篇 - 简书