机器学习算法(二十):孤立森林 iForest (Isolation Forest)

目录

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使用了一套非常高效的策略。在孤立森林中,递归地随机分割数据集,直到所有的样本点都是孤立的。在这种随机分割的策略下,异常点通常具有较短的路径。

        具体来说,该算法利用一种名为孤立树二叉搜索树结构来孤立样本。由于异常值的数量较少且与大部分样本的疏离性,因此,异常值会被更早的孤立出来,也即异常值会距离的根节点更近,而正常值则会距离根节点有更远的距离。此外,相较于LOF,K-means等传统算法,孤立森林算法对高纬数据有较好的鲁棒性。

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

2 算法

2.1 定义

        我们先给出孤立树(Isolation Tree)和样本点在孤立树中的路径长度的定义。

        孤立树:若为孤立树的一个节点,存在两种情况:没有子节点外部节点,有两个子节点和一个test的内部节点。在的test由一个属性 q 和一个分割点 p 组成,的点属于,反之属于

        样本点在孤立树中的路径长度:样本点的根节点到叶子节点经过的边的数量。

2.2  iForest的构建

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

(1)第一阶段

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

(2)第二阶段

       Step1: 对于每一个数据点 ,令其遍历每一颗孤立树,计算点在森林中的平均高度 ,对所有点的平均高度做归一化处理。异常值分数的计算公式如下所示:

                      

        其中,

               

                 

        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的例子如下:

                      

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

2.3 iForest 预测

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

        在处理高维数据时,可以对算法进行改进,采样之后并不是把所有的属性都用上,而是用峰度系数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)孤立森林 异常检测 入门篇 - 简书

异常检测概览——孤立森林 效果是最好的异常检测概览——孤立森林 效果是最好的 - bonelee - 博客园

孤立森林(Isolation Forest):孤立森林(Isolation Forest)_extremebingo的博客-CSDN博客_孤立森林

  • 8
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是孤立森林的MATLAB代码实现,其中包括了孤立树和孤立森林的实现: ```matlab function [IForest, Outliers] = iForest(X, nTrees, sampleSize) % X: 输入的数据集,每一行表示一个样本 % nTrees: 孤立森林中包含的孤立树数目 % sampleSize: 每个孤立树中包含的样本数目 % IForest: 输出的孤立森林,包含nTrees棵孤立树 % Outliers: 输出的异常值,其中每个元素表示该样本的异常得分 if nargin < 3 sampleSize = 256; end if nargin < 2 nTrees = 100; end [nSamples, nFeatures] = size(X); % 构造孤立森林 IForest = cell(nTrees, 1); for i = 1:nTrees IForest{i} = iTree(X, sampleSize, 0); end % 计算异常得分 Outliers = zeros(nSamples, 1); for i = 1:nSamples hTemp = 0; for j = 1:nTrees hTemp = hTemp + pathLength(X(i,:), IForest{j}); end Eh = hTemp/nTrees; c = cValue(sampleSize); Outliers(i) = 2^(-Eh/c); end end function Tree = iTree(X, sampleSize, height) % 构造孤立树 [nSamples, nFeatures] = size(X); if height >= 30 || nSamples <= 1 % 树的高度达到设定的最大值,或者样本数小于等于1 Tree = struct('left', [], 'right', [], 'splitAttr', [], 'splitValue', [], 'size', nSamples, 'height', height); return; end % 随机选择一个属性和一个分割值 splitAttr = randi(nFeatures, 1); splitValue = min(X(:,splitAttr)) + rand(1)*(max(X(:,splitAttr))-min(X(:,splitAttr))); % 选择子样本集 if nSamples > sampleSize % 如果样本数大于设定的子样本集大小,则随机选择子样本集 subIdx = randperm(nSamples, sampleSize); Xsub = X(subIdx,:); else % 如果样本数小于等于设定的子样本集大小,则使用全部样本 Xsub = X; end % 递归构造左子树和右子树 idxLeft = Xsub(:,splitAttr) < splitValue; idxRight = Xsub(:,splitAttr) >= splitValue; Tree = struct('left', iTree(Xsub(idxLeft,:), sampleSize, height+1), 'right', iTree(Xsub(idxRight,:), sampleSize, height+1), 'splitAttr', splitAttr, 'splitValue', splitValue, 'size', nSamples, 'height', height); end function pl = pathLength(X, Tree) % 计算样本X在孤立树Tree中的路径长度 pl = 0; while true if isempty(Tree.left) && isempty(Tree.right) % 叶子节点 pl = pl + cValue(Tree.size); break; end if X(Tree.splitAttr) < Tree.splitValue Tree = Tree.left; else Tree = Tree.right; end pl = pl + 1; end end function c = cValue(n) % 计算c(n) if n <= 1 c = 0; else c = 2*harmlog(n-1) - 2*(n-1)/n; end end function h = harmlog(n) % 计算调和平均数的对数 h = 0; for i = 1:n h = h + 1/i; end h = log(h); end ``` 其中,`iTree`函数用于构造孤立树,`pathLength`函数用于计算样本在孤立树中的路径长度,`cValue`函数用于计算c(n),`harmlog`函数用于计算调和平均数的对数,`iForest`函数用于构造孤立森林以及计算异常得分。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值