孤立森林(Isolation Forest)从原理到实践

异常检测

离群点是在给定数据集中,与其他数据点显著不同的数据点。异常检测是找出数据中离群点(和大多数数据点显著不同的数据点)的过程。


离群点

真实世界中的大型数据集的模式可能非常复杂,很难通过查看数据就发现其模式。这就是为什么异常检测的研究是机器学习中极其重要的应用。

孤立森林原理

孤立森林(Isolation Forest)于2008年由西瓜书作者周志华团队提出,凭借其线性的时间复杂度与优秀的准确率被广泛应用于工业界中结构化数据的异常检测。


孤立森林

孤立森林的基本理论基础有二:

  1. 异常数据占总样本量的比例很小;
  2. 异常点的特征值与正常点的差异很大。
对孤立森林的通俗理解

一句话总结孤立森林的基本原理:异常样本相较普通样本可以通过较少次数的随机特征分割被孤立出来。样本空间有一批数据,其有的地方分布密集,有的地方分布稀疏,如果该批数据大部分样本都分布密集,那么稀疏的那部分是不是就是所谓的离群点?那么孤立森林是如何找出这些离群点的呢?

例如:假设这批样本点有一个特征为年龄,孤立森林随机选择认为年龄>70为异常,年龄<=70为正常。此时相当于在样本空间,画出了一个超平面。接着孤立森林再选了一个特征为收入,认为收入>1w为异常,收入<=1W为正常,此时则又在样本空间画出了一个超平面......根据直觉,是不是分布稀疏位置的点可以通过较少次数的超平面划分被孤立出来,而分布密集位置的点需要更多次数的超平面划分才能被孤立。如下图所示,处于分布密集位置的xi用了11个超平面才被孤立,处于分布稀疏位置的x0用了4个超平面即被孤立。


超平面划分

假设一棵树通过这个方法认为x0是离群点,这一结果是未必准确的,因为随机选特征与阈值存在着诸多偶然性。但是如果引入bagging的思想,我用100棵树进行这样的随机分割,其中90颗的结论都是认为x0是离群点,那么这个结果就比较可信了。

算法细节

单棵树的训练
单棵树训练的伪代码
  1. 从训练数据中随机选择 Ψ 个点作为子样本,放入一棵孤立树的根节点;
  2. 随机指定一个维度,在当前节点数据范围内,随机产生一个切割点 p —— 切割点产生于当前节点数据中指定维度的最大值与最小值之间;
  3. 此切割点的选取生成了一个超平面,将当前节点数据空间切分为2个子空间:把当前所选维度下小于 p 的点放在当前节点的左分支,把大于等于 p 的点放在当前节点的右分支;
  4. 在节点的左分支和右分支节点递归步骤 2、3,不断构造新的叶子节点,直到叶子节点上只有一个数据(无法再继续切割) 或树已经生长到了所设定的高度 。
如何整合多棵树的结果?

孤立森林与随机森林相似,都是通过随机采样数据来对每棵树进行训练,从而保证构建的森林的方差足够大,即每棵树之间越不相似越好。 在构建孤立森林时,需要设定两个参数:树的数量t和每棵树采样样本大小的最大值Ψ 。

孤立森林通过引入异常值函数s(x,n)来衡量记录x 是否为异常点


s(x,n)

其中,E(h(x))为x在多棵树中的路径长度的期望值。

c(n)
H(*)

其中,c(n)为一个包含n个样本的数据集,树的平均路径长度,用来标准化记录x的路径长度。H(*)为调和数,ξ为欧拉常数,约为0.5772156649。

s(x,n)与E(h(x))的关系

s(x,n)与E(h(x))的关系2

isolation forest伪代码
一个树的最大高度

FAQ

qes: 为什么需要对树的高度做限制?
ans: 之所以对树的高度做限制,是因为我们只关心路径长度较短的点,它们更可能是异常点,而并不关心那些路径很长的正常点
qes: 树的棵树如何选择?
ans: 通过下图可以发现,当t>=100后,划分上文提到的xi和x0的平均路径长度都已经收敛了,故因此论文中推荐t设置为100。


平均路径长度与t的关系

qes: 样本采样量Ψ如何取值?
ans:论文中推荐Ψ设置为2^8或256,其能够提供足够的细节给异常检测任务。下图展示了部分采样的作用,蓝色代表正常样本,红色代表异常样本。可以看出,在采样之前,正常样本和异常样本出现了重叠,因此很难分开,但通过采样之后,异常样本和正常样本可以明显的分开。另外采样可以降低计算时间和空间上的浪费。


部分采样的效果

qes: isolation forest的复杂度如何?
ans: 训练一个iforest的时间复杂度为o(tΨlogΨ)。

实践中的参数调节

我们使用sklearn中的孤立森林,进行参数调节讲解,一般任务默认参数即可。
import sklearn.ensemble.IsolationForest as iforest

  1. n_estimators : int, optional (default=100) 指定该森林中生成的随机树数量

  2. max_samples : int or float, optional (default=”auto”)
    用来训练随机数的样本数量,即子采样的大小
    如果设置的是一个int常数,那么就会从总样本X拉取max_samples个样本来生成一棵树iTree
    如果设置的是一个float浮点数,那么就会从总样本X拉取max_samples * X.shape[0]个样本,X.shape[0]表示总样本个数
    如果设置的是"auto",则max_samples=min(256, n_samples),n_samples即总样本的数量
      如果max_samples值比提供的总样本数量还大的话,所有的样本都会用来构造数,意思就是没有采样了,构造的n_estimators棵iTree使用的样本都是一样的,即所有的样本

  3. contamination : float in (0., 0.5), optional (default=0.1)
    取值范围为(0., 0.5),表示异常数据占给定的数据集的比例
    数据集中污染的数量,其实就是训练数据中异常数据的数量,比如数据集异常数据的比例。定义该参数值的作用是在决策函数中定义阈值。如果设置为'auto',则决策函数的阈值就和论文中定义的一样
    在版本0.20中有变化:默认值从0.1变为0.22版本中的'auto'

  4. max_features : int or float, optional (default=1.0)
    指定从总样本X中抽取来训练每棵树iTree的属性的数量,默认只使用一个属性
    如果设置为int整数,则抽取max_features个属性
    如果是float浮点数,则抽取max_features * X.shape[1]个属性

  5. bootstrap : boolean, optional (default=False)
    如果为True,则各个树可放回地对训练数据进行采样。如果为False,则执行不放回的采样。

  6. n_jobs : int or None, optional (default=None)
    在运行fit()和predict()函数时并行运行的作业数量。除了在joblib.parallel_backend上下文的情况下,None表示为1。设置为-1则表示使用所有可用的处理器

  7. behaviour : str, default=’old’
    决策函数decision_function的行为,可以是'old'和'new'。设置为behaviour='new'将会让decision_function去迎合其他异常检测算法的API,这在未来将会设置为默认值。正如在offset_属性文档中详细解释的那样,decision_function变得依赖于contamination参数,以0作为其检测异常值的自然阈值。
    New in version 0.20:behaviour参数添加到了0.20版本中以实现后向兼容
    behaviour='old'在0.20版本中以经弃用,在0.22版本中将不能使用
    behaviour参数将在0.22版本中弃用,将在0.24版本中移除

  8. random_state : int, RandomState instance or None, optional (default=None)
    如果设置为int常数,则该random_state参数值是用于随机数生成器的种子
    如果设置为RandomState实例,则该random_state就是一个随机数生成器
    如果设置为None,该随机数生成器就是使用在np.random中的RandomState实例

  9. verbose : int, optional (default=0) 训练中打印日志的详细程度,数值越大越详细

  10. warm_start : bool, optional (default=False)
    当设置为True时,重用上一次调用的结果去fit,添加更多的树到上一次的森林1集合中;否则就fit一整个新的森林

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容