0x14 异常挖掘,Isolation Forest

摘要:iForest用于挖掘异常数据,如网络安全中的攻击检测和流量异常分析,金融机构则用于挖掘出欺诈行为。算法对内存要求很低,且处理速度很快,其时间复杂度也是线性的。可以很好的处理高维数据和大数据,并且也可以作为在线异常检测。

0x14.jpg

01 孤立森林

isolation,意为孤立/隔离,是名词,其动词为isolate,forest是森林,合起来就是“孤立森林”了,也有叫“独异森林”,好像并没有统一的中文叫法。可能大家更习惯用其英文的名字isolation forest,简称iForest。

iForest算法用于挖掘异常(Anomaly)数据,或者说离群点挖掘,总之是在一大堆数据中,找出与其它数据的规律不太符合的数据。通常用于网络安全中的攻击检测和流量异常等分析,金融机构则用于挖掘出欺诈行为。对于找出的异常数据,然后要么直接清除异常数据,如数据清理中的去除噪声数据,要么深入分析异常数据,比如分析攻击、欺诈的行为特征。
算法起源于08年的一篇论文《Isolation Forest》,这论文由澳大利亚莫纳什大学的两位教授Fei Tony Liu, Kai Ming Ting(这两个名字看起来都像是华人)和南京大学的周志华教授共同完成,而这三人在2011年又发表了《Isolation-based Anomaly Detection》,这两篇论文算是确定了这个算法的基础。

论文地址:
http://cs.nju.edu.cn/zhouzh/zhouzh.files/publication/icdm08b.pdf
http://cs.nju.edu.cn/zhouzh/zhouzh.files/publication/tkdd11.pdf

关于算法 ,网上的中文资料也并不多,下面是搜索到周志华教授在2015-07-12发的信息:

ICML上遇到国际机器学习学会首任主席Dietterich教授,对我们的iForest算法大赞,说尝试了很多方法,还是这个又快又好。前段时间澳洲某startup公司也说他们发现iForest在信息安全领域的异常检测应用中表现最佳并准备做进产品。isolation Forest,推荐给有异常检测任务的同学。

从上面的评价中来看,iForest算法在实际的应用中应该具有不错的效果,得益于随机森林的思想,能快速处理大规模的数据,在当前的大数据环境下,应该很受欢迎。


知识星球.jpeg

02 算法原理

与随机森林由大量决策树组成一样,iForest森林也由大量的树组成。iForest中的树叫isolation tree,简称iTree。iTree树和决策树不太一样,其构建过程也比决策树简单,因为其中就是一个完全随机的过程。

假设数据集有N条数据,构建一颗iTree时,从N条数据中均匀抽样(一般是无放回抽样)出ψ个样本出来,作为这颗树的训练样本。

在样本中,随机选一个特征,并在这个特征的所有值范围内(最小值与最大值之间)随机选一个值,对样本进行二叉划分,将样本中小于该值的划分到节点的左边,大于等于该值的划分到节点的右边。

这样得到了一个分裂条件和左、右两边的数据集,然后分别在左右两边的数据集上重复上面的过程,直接达到终止条件。终止条件有两个,一个是数据本身不可再分(只包括一个样本,或者全部样本相同),另外一个是树的高度达到log2(ψ)。不同于决策树,iTree在算法里面已经限制了树的高度。当然不限制也可以,只是算法为了效率考虑,只需要达到log2(ψ)深度即可。

把所有的iTree树构建好了,就可以对测数据进行预测了。预测的过程就是把测试数据在iTree树上沿对应的条件分支往下走,直到达到叶子节点,并记录这过程中经过的路径长度h(x),即从根节点,穿过中间的节点,最后到达叶子节点,所走过的边的数量(path length)。

最后,将h(x)带入,计算每条待测数据的异常分数(Anomaly Score),其计算公式为:

s(x,n) = 2^{(-\frac{E( { h(x) })} { c(n) } )}

其中 c(n) = 2H(n − 1) − (2(n − 1)/n) 是二叉搜索树的平均路径长度,用来对结果进行归一化处理, 其中的H(k)可以通过公式 H(k) = ln(k) + \xi来估计,\xi是欧拉常数,其值为0.5772156649。

h(x) 为路径长度,E(h(x)) 为森林中所有iTree树的平均路径长度。

使用异常分数,具有以下性质:

  1. 如果分数越接近1,其是异常点的可能性越高;
  2. 如果分数都比0.5要小,那么基本可以确定为正常数据;
  3. 如果所有分数都在0.5附近,那么数据不包含明显的异常样本。

上面的步骤,可以总结为两步:

  1. 训练:从训练集中进行采样,并构建iTree树;
  2. 测试:对iForest森林中的每颗iTree树进行测试,记录path length,然后根据异常分数计算公式,计算每条测试数据的anomaly score。

03 算法特点

在论文中,也比较了其它的常用异常挖掘的算法。比如常用的统计方法,基于分类的方法,和基于聚类的方法,这些传统算法通常是对正常的数据构建一个模型,然后把不符合这个模型的数据,认为是异常数据。而且,这些模型通常为正常数据作优化,而不是为异常数据作优化。而iForest可以显示地找出异常数据,而不用对正常的数据构建模型。

由于异常数据的两个特征(少且不同: few and different)

  1. 异常数据只占很少量;
  2. 异常数据特征值和正常数据差别很大。

异常数据的这两个特征,确定了算法的理论基础。因此,构建二叉树型结构的时候,异常数据离根更近,而正常数据离根更远,更深。算法为了效率考虑,也限定了树的深度:ceil(log2(n)),这个值近似于树的平均深度,因为只需要关心那些低于平均高度的数据点,而不需要树进行完全生成。

算法只需要两个参数:树的多少与采样的多少。实验发现,在100颗树的时候,路径的长度就已经覆盖得比较好了,因此选100颗也就够了。采样,是为了更好的将正常数据和异常数据分离开来。有别于其它模型,采样数据越多,反面会降低iForest识别异常数据的能力。因为,通常使用256个样本,这也是scikit-learn实现时默认使用的采样数。

由于算法只需要采样数据256条样本,并且对树的深度也有限制,因此,算法对内存要求很低,且处理速度很快,其时间复杂度也是线性的。

不像其它算法,需要计算距离或者密度来寻找异常数据,iForest算法可以很好的处理高维数据和大数据,并且也可以作为在线预测。假设采样为256条,结点最大为511个,假设一个节点占b字节,共使用t颗树,那么需要的内存只有511tb字节,基本上只需要几M到几十M的内存就够了。数据还显示,预测287,748条数据只花了7.6秒。

另外,iForest既能发现群异常数据,也能发现散点异常数据。同时也能处理训练数据中不包含异常数据的情况。

这么好的算法,你还在等什么?

04 sklearn示例

IsolationForest在scikit-learn的0.18中才有实现,scikit-learn目前的stable版本为0.17,而0.18是dev版本。需要直接去github中clone。

源码和文档地址:

https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/ensemble/iforest.py
http://scikit-learn.org/dev/modules/generated/sklearn.ensemble.IsolationForest.html

下载源码与安装:

git clone https://github.com/scikit-learn/scikit-learn.git
cd scikit-learn
python setup.py install
知识星球.jpeg

算法基本上不需要配置参数就可以直接使用,通常就以下几个(参数明显比随机森林简单):

n_estimators: 默认为100,配置iTree树的多少
max_samples: 默认为265,配置采样大小
max_features: 默认为全部特征,对高维数据,可以只选取部分特征

示例:

import pandas as pd
from sklearn.ensemble import IsolationForest
ilf = IsolationForest(n_estimators=100,
                      n_jobs=-1,          # 使用全部cpu
                      verbose=2,
    )
data = pd.read_csv('data.csv', index_col="id")
data = data.fillna(0)
# 选取特征,不使用标签(类型)
X_cols = ["age", "salary", "sex"]
print data.shape

# 训练
ilf.fit(data[X_cols])
shape = data.shape[0]
batch = 10**6

all_pred = []
for i in range(shape/batch+1):
    start = i * batch
    end = (i+1) * batch
    test = data[X_cols][start:end]
    # 预测
    pred = ilf.predict(test)
    all_pred.extend(pred)

data['pred'] = all_pred
data.to_csv('outliers.csv', columns=["pred",], header=False)

算法的训练过程需要的内存很少,但如果数据量太大,在预测的时候,可能会把内存挤爆,上面代码中的for循环便是分块对数据进行预测,最后再组合起来。

  • 参考文章

http://www.cnblogs.com/fengfenggirl/p/iForest.html
http://qf6101.github.io/machine%20learning/2015/08/01/Isolation-Forest/

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

推荐阅读更多精彩内容