孤立森林:大数据背景下的最佳异常检测算法之一

本文涉及的产品
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: 孤立森林:大数据背景下的最佳异常检测算法之一

孤立森林或“iForest”是一个非常漂亮和优雅简单的算法,可以用很少的参数来识别异常。原始的论文对广大的读者来说是容易理解的,并且包含了很少的数学知识。在这篇文章中,我将解释为什么iForest是目前最好的大数据异常检测算法,提供算法的总结,算法的历史,并分享一个代码实现。

640.jpg

为什么iForest是目前最好的大数据异常检测算法

iForest有着基于ROC性能和精度的一流的综合性能。iForest在各种数据集上的性能均优于大多数其他异常值检测(OD)算法。我从Python离群值检测包(PyOD)的作者那里获取了基准数据,并在Excel中应用了行向绿-红渐变条件格式。深绿色表示数据集的最佳算法,深红色表示性能最差的算法:

640.png

我们看到,iForest在大多数数据集中均处于领先地位,如我所计算的均值,中位数和标准差行的颜色所示。iForest的相同优异结果也适用于N次精度:

640.png

可扩展性。iForest是性能最快的算法。预期在所有数据集中,基于PCA和基于直方图的离群值(HBOS)都更快。k最近邻(KNN)慢得多,并且随着更多的观测值N而扩展得非常厉害。

我已经成功建立了孤立森林,其中包含在集群环境中以分钟为单位的包含100M个观测值和36列的数据集。这样的数据如果使用sk-learn的KNN()速度上简直无法忍受。

640.png

算法要点总结

一下可以认为是10页原始论文的总结,如果不想深入研究,看一下要点就可以了。

  1. 大多数其他离群值检测(OD)算法试图构建“正常”实例的配置文件,然后标记不符合该配置文件的实例。iForest通过利用异常的固有特性明确地孤立异常记录:它们的协变量集合具有不寻常的值。
  2. 由于计算量大,现有方法仅限于低维数据和小数据大小。举例:尝试对大数据使用sklearn.neighbor.KNeighborsClassifier吗?
  3. 另外,iForest具有低开销的特点。细节:外部节点的数量为n,因为每个观测值n都是独立的。内部节点的总数显然为n-1,而节点的总数为2n-1。因此,我们了解了为什么内存需求是有界的并且随n线性增长。
  4. 孤立树节点定义:T是无子外部节点或具有一个测试且恰好有两个子节点(Tₗ,Tᵣ)的内部节点。要构建iTree,我们通过随机选择属性q和拆分值p递归地将X划分为:(i)树达到高度限制,(ii)所有观测值都孤立在其自己的外部节点上,或者(iii) 所有数据的所有属性值都相同。
  5. 路径长度。观测值x的路径长度h(x)通过从根节点横穿iTree直到横向终止于外部节点的边数x来度量。E(h(x))是来自孤立树集合的h(x)的平均值。可以从平均路径长度E(h(x))得出异常分数s(x,n):s(x,n)= 2 ^ [-E(h(x))/ c(n )]。基本上,s和E(h(x))之间存在单调关系(有关详细信息,请参见附录末尾)。我不会涉及术语c(n),所以我可以保持简短,但是对于任何给定的静态数据集来说,它都是常数。
  6. 仅要求用户设置两个变量:要构建的树数和子采样大小。作者利用生成的高斯分布数据进行了实验,这些实验表明如何在很少的树和较小的子样本的情况下相对快速地实现平均路径长度的收敛。
  7. 小的次抽样(样本的样本)解决了沼泽化和掩蔽问题。对于异常检测而言,输入数据太大而造成了沼泽化和掩蔽。沼泽化是指将“正常”观测结果误认为“异常”观测结果,因为它被异常所包围,而掩蔽则相反。换句话说,当为一棵树提供包含大部分异常的样本时,一个正常的数据点可能看起来异常。作者用x光检查的数据提供了这种现象的例子。
  8. 小的子样本允许每个孤立树被特殊化,因为每个子样本包含一组不同的异常或甚至没有异常
  9. iForest不依赖于任何距离或基于密度的测量来识别异常,所以它速度快,计算成本低,这就引出了下一个问题
  10. 线性时间复杂度,O(n)通俗地说,这意味着运行时间随着输入的大小线性增加。

640.png

算法的历史

一个伟大的新想法和更广泛的采纳之间可能有几十年的滞后性。例如,logistic 函数在1845年被发现,在1922年被重新发现,现在被现代数据科学家用于logistic 回归。近几十年来,一个新想法和它被广泛采用之间的滞后时间已经缩短了,但这仍然是一个有争议的很长的时间。iForest于2008年首次共享,直到2018年底才发布具有商业可行性的应用程序!时间表如下:

12/2008 - iForest发布的原始论文

07/2009 - iForest作者最后一次修改他们的代码实现代码

10/2018- h2o团队为R和Python用户提供iForest代码

01/2019 - PyOD发布面向Python用户的离群点检测(OD)工具包代码

08/2019 - LinkedIn工程团队发布Spark/Scala实现iForest代码

代码的实现

由于本文是关于大数据的,所以假设是AWS集群环境。代码脚手架(QA对象的代码,调试等等)大多被省略了。

我发现iForest可以轻松快速地处理750万行和36个特性,按分钟的顺序完成计算。

Python (h2o):

importh2o#h2oautomateddatacleaningwellformydatasetimportpkg_resources###################################################################printpackages+versionsfordebugging/futurereproducibility###################################################################dists= [dfordinpkg_resources.working_set] #Filteroutdistributionsyoudon't care about and use.dists.reverse()dists################################################################### initialize h2o cluster and load data##################################################################h2o.init() # http://docs.h2o.ai/h2o/latest-stable/h2o-r/docs/reference/h2o.init.htmlimport pyarrow.parquet as pq # allow loading of parquet filesimport s3fs                 # for working in AWS s3s3 = s3fs.S3FileSystem()df = pq.ParquetDataset('s3a://datascience-us-east-1/anyoung/2_processedData/stack_parquetFiles', filesystem=s3).read_pandas().to_pandas()# check input data loaded correctly; pretty print .shapeprint('('+'; '.join(map('{:,.0f}'.format,
df.shape)) +')')#ifyouneedtosampledatadf_samp_5M=df.sample(n=5000000, frac=None, replace=False, weights=None, random_state=123, axis=None)#convertPandasDataFrameobjecttoh2oDataFrameobjecthf=h2o.H2OFrame(df)#dropprimarykeycolumnhf=hf.drop('referenceID', axis=1) #referenceIDcauseserrorsinsubsequentcode#youcanomitrowswithnasforafirstpasshf_clean=hf.na_omit()#prettyprint .shapewiththousandscommaseparatorprint('('+'; '.join(map('{:,.0f}'.format,
hf.shape)) +')')fromh2o.estimatorsimportH2OIsolationForestEstimatorfromh2o.estimatorsimportH2OIsolationForestEstimatorfullX= ['v1',
'v2',
'v3'      ]#splith2oDataFrameinto80/20train/testtrain_hf, valid_hf=hf.split_frame(ratios=[.8], seed=123)#specifyiForestestimatormodelsisolation_model_fullX=H2OIsolationForestEstimator(model_id="isolation_forest_fullX.hex", seed=123)
isolation_model_fullX_cv=H2OIsolationForestEstimator(model_id="isolation_forest_fullX_cv.hex", seed=123)#trainiForestmodelsisolation_model_fullX.train(training_frame=hf, x=fullX)
isolation_model_fullX_cv.train(training_frame=train_hf, x=fullX)#savemodels (haven't figured out how to load from s3 w/o permission issues yet)modelfile = isolation_model_fullX.download_mojo(path="~/", get_genmodel_jar=True)print("Model saved to " + modelfile)# predict modelspredictions_fullX = isolation_model_fullX.predict(hf)# visualize resultspredictions_fullX["mean_length"].hist()

640.png

如果你的数据具有想要用iForest验证的标签,那么您可以比较正常实例集与异常实例集的分布,并与原始数据集进行进一步的推断。例如,你可以通过原始数据集中不同的特征组合来查看计数,如下所示:

N=df.count()
df[['v1', 'v2', 'id']].groupby(['v1', 'v2']).count() /Ndf[['v1', 'v3', 'id']].groupby(['v1', 'v3']).count() /N...

并与iForest确定的正常/异常实例集进行比较,如下图所示:

###################################################################columnbindpredictionsfromiForesttotheoriginalh2oDataFrame##################################################################hf_X_y_fullX=hf.cbind(predictions_fullX)
###################################################################Sliceusingabooleanmask. Theoutputdatasetwillincluderows#withcolumnvaluemeetingcondition##################################################################mask=hf_X_y_fullX["label"] ==0hf_X_y_fullX_0=hf_X_y_fullX[mask,:]
mask=hf_X_y_fullX["label"] ==1hf_X_y_fullX_1=hf_X_y_fullX[mask,:]
###################################################################Filtertoonlyincluderecordsthatareclearlynormal##################################################################hf_X_y_fullX_ml7=hf_X_y_fullX[hf_X_y_fullX['mean_length'] >=7]
hf_X_y_fullX_0_ml7=hf_X_y_fullX_1[hf_X_y_fullX_0['mean_length'] >=7]
hf_X_y_fullX_1_ml7=hf_X_y_fullX_3[hf_X_y_fullX_1['mean_length'] >=7]
###################################################################ConverttoPandasDataFrameforeasiercounting/familiarity##################################################################hf_X_y_fullX_ml7_df=h2o.as_list(hf_X_y_fullX_ml7, use_pandas=True)
hf_X_y_fullX_0_ml7_df=h2o.as_list(hf_X_y_fullX_0_ml7, use_pandas=True)
hf_X_y_fullX_1_ml7_df=h2o.as_list(hf_X_y_fullX_1_ml7, use_pandas=True)
###################################################################Lookatcountsbycombinationsofvariablelevelsforinference##################################################################hf_X_y_fullX_ml7_df[['v1', 'v2', 'id']].groupby(['v1', 'v2']).count()
hf_X_y_fullX_0_ml7_df=h2o.as_list(hf_X_y_fullX_0_ml7, use_pandas=True)
#Repeataboveforanomalousrecords:###################################################################Filtertoonlyincluderecordsthatareclearlyanomalous##################################################################hf_X_y_fullX_ml3=hf_X_y_fullX[hf_X_y_fullX['mean_length'] <3]
hf_X_y_fullX_0_ml3=hf_X_y_fullX_1[hf_X_y_fullX_0['mean_length'] <3]
hf_X_y_fullX_1_ml3=hf_X_y_fullX_3[hf_X_y_fullX_1['mean_length'] <3]
###################################################################ConverttoPandasDataFrameforeasiercounting/familiarity##################################################################hf_X_y_fullX_ml3_df=h2o.as_list(hf_X_y_fullX_ml3, use_pandas=True)
hf_X_y_fullX_0_ml3_df=h2o.as_list(hf_X_y_fullX_0_ml3, use_pandas=True)
hf_X_y_fullX_1_ml3_df=h2o.as_list(hf_X_y_fullX_1_ml3, use_pandas=True)

完成所有这些,并数据导出到Excel中,以快速生成一些累积分布函数,像这样:

640.png

参考文献

F. T. Liu, K. M. Ting, and Z.-H. Zhou. Isolation forest. In: Proceedings of the 8th IEEE International Conference on Data Mining (ICDM’08), Pisa, Italy, 2008, pp.413–422. [code] This paper won the Theoretical/Algorithms Runner-Up Best Paper Award at IEEE ICDM’08

Zhao, Y., Nasrullah, Z. and Li, Z., 2019. PyOD: A Python Toolbox for Scalable Outlier Detection. Journal of machine learning research (JMLR), 20(96), pp.1–7.

附录

算法要点/小结,第5点具体内容:

E(h(x))→c(n), s→0.5(观测不明显异常)

当E(h(x))→0,s→1(异常)

当E(h(x))→n−1,s→0(不是异常)

所以用这篇论文的话来总结一下上面的内容:

(a)如果实例返回s非常接近1,那么它们肯定是异常的,

(b)如果实例的s远远小于0.5,那么它们被视为正常实例是相当安全的,并且

(c)如果所有实例返回s≈0.5,那么整个样本实际上没有任何明显的异常。

有助于说明异常得分、s和平均路径长度E(h(x))之间关系的图表

相关实践学习
基于MaxCompute的热门话题分析
本实验围绕社交用户发布的文章做了详尽的分析,通过分析能得到用户群体年龄分布,性别分布,地理位置分布,以及热门话题的热度。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
目录
相关文章
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
54 4
|
1月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于MSER和HOG特征提取的SVM交通标志检测和识别算法matlab仿真
### 算法简介 1. **算法运行效果图预览**:展示算法效果,完整程序运行后无水印。 2. **算法运行软件版本**:Matlab 2017b。 3. **部分核心程序**:完整版代码包含中文注释及操作步骤视频。 4. **算法理论概述**: - **MSER**:用于检测显著区域,提取图像中稳定区域,适用于光照变化下的交通标志检测。 - **HOG特征提取**:通过计算图像小区域的梯度直方图捕捉局部纹理信息,用于物体检测。 - **SVM**:寻找最大化间隔的超平面以分类样本。 整个算法流程图见下图。
|
1月前
|
存储 分布式计算 算法
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
58 0
|
5天前
|
缓存 算法 大数据
大数据查询优化算法
【10月更文挑战第26天】
15 1
|
12天前
|
机器学习/深度学习 数据采集 算法
大数据中缺失值处理使用算法处理
【10月更文挑战第21天】
20 3
|
11天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
10天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GA-PSO-SVM算法的混沌背景下微弱信号检测matlab仿真
本项目基于MATLAB 2022a,展示了SVM、PSO、GA-PSO-SVM在混沌背景下微弱信号检测中的性能对比。核心程序包含详细中文注释和操作步骤视频。GA-PSO-SVM算法通过遗传算法和粒子群优化算法优化SVM参数,提高信号检测的准确性和鲁棒性,尤其适用于低信噪比环境。
|
1月前
|
算法 安全
分别使用OVP-UVP和OFP-UFP算法以及AFD检测算法实现反孤岛检测simulink建模与仿真
本课题通过Simulink建模与仿真,实现OVP-UVP、OFP-UFP算法及AFD检测算法的反孤岛检测。OVP-UVP基于电压幅值变化,OFP-UFP基于频率变化,而AFD则通过注入频率偏移信号来检测孤岛效应,确保电力系统安全稳定运行。系统使用MATLAB 2013b进行建模与仿真验证。
|
15天前
|
存储 JSON 算法
TDengine 检测数据最佳压缩算法工具,助你一键找出最优压缩方案
在使用 TDengine 存储时序数据时,压缩数据以节省磁盘空间是至关重要的。TDengine 支持用户根据自身数据特性灵活指定压缩算法,从而实现更高效的存储。然而,如何选择最合适的压缩算法,才能最大限度地降低存储开销?为了解决这一问题,我们特别推出了一个实用工具,帮助用户快速判断并选择最适合其数据特征的压缩算法。
26 0
|
29天前
|
算法 计算机视觉 Python
圆形检测算法-基于颜色和形状(opencv)
该代码实现了一个圆检测算法,用于识别视频中的红色、白色和蓝色圆形。通过将图像从RGB转换为HSV颜色空间,并设置对应颜色的阈值范围,提取出目标颜色的区域。接着对这些区域进行轮廓提取和面积筛选,使用霍夫圆变换检测圆形,并在原图上绘制检测结果。
62 0