首页 / 资讯中心 / 文章详情

在 H2O-3 中使用扩展隔离森林(Extended Isolation Forest)进行异常检测:原理、参数与实战

在 H2O-3 中使用扩展隔离森林(Extended Isolation Forest)进行异常检测:原理、参数与实战 ★ FEATURED ARTICLE
机器学习深度学习AutoML大数据后端【免费下载链接】h2o-3H2O is an Open Source, Distributed, Fast Scalable Machine Learning Platform: Deep Learning, Gradient Boosting (GBM) XGBoost, Random Forest, Generalized Linear Modeling (GLM with Elastic Net), K-Means, PCA, Generalized Additive Models (GAM), RuleFit, Support Vector Machine (SVM), Stacked Ensembles, Automatic Machine Learning (AutoML), etc.项目地址https://gitcode.com/gh_mirrors/h2/h2o-3点击查看免费下载导读扩展隔离森林Extended Isolation ForestEIF是经典隔离森林Isolation Forest的推广算法通过为每个切分点引入随机斜率来消除传统隔离森林因“切分面始终平行于坐标轴”而产生的分支偏差。本文以 H2O-3 官方文档 eif.rst 为主体结合仓库内 Java 实现、Python/R 客户端封装与测试用例系统讲解 EIF 的算法原理、extension_level等核心参数、异常分数anomaly_score的计算公式、MOJO 导出支持以及用前列腺癌数据集构建异常检测模型的完整 R / Python 代码示例。读完本文你将能够独立地在 H2O-3 中配置并训练 EIF 模型理解并正确解读anomaly_score与mean_length两个预测输出并能根据数据特征选择合理的extension_level。算法原理从隔离森林到扩展隔离森林传统隔离森林的偏差来源H2O-3 官方文档指出扩展隔离森林是其前身算法 隔离森林 的推广。传统隔离森林提出了一种全新的异常检测思路异常点“更容易被隔离”因此从根节点到叶子节点所需的切分路径更短。然而该算法存在一个固有缺陷——由树分支方式引入的偏差bias。产生偏差的根源在于传统隔离森林的分支规则以二叉搜索树BST为类比来定义。在每一个分支节点上算法选择一个特征feature并选择一个取值value由于切分面总是平行于某一坐标轴切分边界与数据分布之间就可能产生系统性偏差。扩展隔离森林的核心改进随机斜率切分扩展隔离森林通过调整分支方式来缓解上述偏差并且将原算法变为自身的一个特例当扩展级别为 0 时EIF 行为退化为标准 IF。与“选择特征 选择取值”不同EIF 为每个分支点生成一个随机斜率slope:math:n从 :math:\mathcal{N(0,1)}高斯分布中生成一个随机截距intercept:math:p从以“待切分数据子样本”取值范围为边界的均匀分布中生成。对于给定的数据点 :math:x数据切分的分支判定准则为(x - p) * n ≤ 0其中 :math:x、:math:p、:math:n均为维度为 P特征数的向量。当判定式成立时数据进入左分支否则进入右分支。在仓库的 Java 实现中这一判定逻辑被直接落地。训练阶段IsolationTree.java 中的extendedIsolationForestSplit方法对每个节点逐行计算res[row] (data[col][row] - p[col]) * n[col]然后按res[row] 0与否将数据划分到左右两个分支。而在推理/打分阶段ExtendedIsolationForestMojoModel.java 中的scoreTree0同样通过subAndMul(row, p, n) 0决定路径走向两侧逻辑保持一致。随机斜率向量的生成细节也体现在 IsolationTree.java 的gaussianVector方法中先生成一个服从 :math:\mathcal{N(0,1)}的高斯向量再根据extension_level的值随机将其中若干分量置零该方法注释明确说明zeroNum即data.length - extensionLevel - 1。为什么能消除偏差标准 IF 的分支面平行于坐标轴本质上是 EIF 的特例当所有斜率分量中只有一个非零时判定式(x - p) * n ≤ 0等价于“仅沿单个特征轴进行切分”。EIF 通过允许切分面带有任意方向的斜率使分支不再受坐标轴方向束缚从而显著降低高维数据中的分支偏差。extension_level 参数控制切分推广程度的超参数取值范围与含义extension_level是 EIF 区别于 IF 的核心超参数其取值范围为 :math:[0, P-1]其中 P 为特征数最小值 0默认值对应 Isolation Forest 的行为。此时切分面的斜率平行于所有坐标轴即随机向量 :math:n的所有分量都被置零仅保留一个轴方向退化为标准 IF最大值 P-1全扩展full extension切分面的斜率始终被完全随机化取值越大标准 IF 的偏差越小。从源码看该参数的校验逻辑位于 ExtendedIsolationForest.java 的init方法中训练时extension_level必须落在[0, _train.numCols() - 1]区间内否则抛出H2OModelBuilderIllegalArgumentException。测试 ExtendedIsolationForestTest.java 中专门覆盖了负扩展级别、过高扩展级别等非法取值场景。此外由于像OneHotExplicit这样的分类编码方式会改变特征维度扩展级别的上限校验是在expensive初始化阶段、编码完成后基于实际列数numCols() - 1进行的代码注释中对此有明确说明。如何选择扩展级别官方参数文档 extension_level.rst 给出了一条重要的选参经验在特征取值范围差异很大的场景下例如一个特征以毫米计量、另一个特征以米计量较低的扩展级别更为合适。这是因为当各特征尺度差异悬殊时完全随机的斜率会在尺度更大的特征方向上引入不必要的敏感性。extension_level 0 与全扩展的对照示例参数文档提供了用同一份前列腺数据集对比extension_level 0模拟 IF 行为与extension_level P-1全扩展的完整示例这里给出 Python 版本R 版本与之等价详见下文实战一节import h2o from h2o.estimators import H2OExtendedIsolationForestEstimator h2o.init() # Import the prostate dataset h2o_df h2o.import_file(https://raw.github.com/h2oai/h2o/master/smalldata/logreg/prostate.csv) # Set the predictors predictors [AGE, RACE, DPROS, DCAPS, PSA, VOL, GLEASON] # Simulate Isolation Forest behavior with Extended Isolation Forest algorithm eif_if H2OExtendedIsolationForestEstimator(model_ideif_if.hex, ntrees100, extension_level0) # Use full-extension eif_full H2OExtendedIsolationForestEstimator(model_ideif_full.hex, ntrees100, extension_levellen(predictors) - 1) eif_if.train(xpredictors, training_frameh2o_df) eif_full.train(xpredictors, training_frameh2o_df) # Calculate score eif_if_result eif_if.predict(h2o_df) eif_full_result eif_full.predict(h2o_df) print(eif_if_result[anomaly_score]) print(eif_full_result[anomaly_score])定义扩展隔离森林模型参数全解析官方文档对参数的组织分为“算法特有参数”“树算法共享参数”“通用参数”三层。下面按此脉络逐项展开并补充仓库源码中可确认的默认值与校验规则。算法特有参数参数默认值说明extension_level0扩展级别取值 :math:[0, P-1]控制切分斜率的随机化程度详见上文sample_size256每棵 EIF 树训练时随机采样的观测数disable_training_metricsTrue是否关闭训练指标的计算在大数据集上该计算开销较大关于sample_size的更多细节参数文档 sample_size.rst 说明该选项指定每棵隔离树训练所用的随机采样观测数EIF 与 IF 的默认值均为 256。同时源码在 ExtendedIsolationForest.java 中对该参数做了双重约束取值必须在[2, 100000]MAX_SAMPLE_SIZE区间内且不能超过训练集总行数。每棵树的高度上限也与sample_size直接相关——heightLimit ceil(log2(sample_size))即树高被限制为子采样规模的以 2 为底的对数这一设计沿袭自隔离森林的经典理论。disable_training_metrics的默认值为True。从 ExtendedIsolationForest.java 的训练驱动逻辑可见当该开关开启时模型训练完成后只生成 Model Summary 摘要表而不做全量打分当关闭时最终一轮评分final scoring会被强制执行并产出training_metrics与评分历史。树算法共享参数参数默认值说明ntrees100森林中树的数量score_tree_interval0禁用每训练多少棵树后对模型进行一次打分ntrees在源码中同样有边界约束合法区间为[1, 100000]MAX_NTREES见 ExtendedIsolationForest.java。测试 ExtendedIsolationForestTest.java 中的testBasicTrainErrorTrain0Trees验证了ntrees 0会触发参数错误。score_tree_interval与score_each_iteration、disable_training_metrics共同决定训练过程中的打分节奏。在 ExtendedIsolationForest.java 中可以看到完整的评分触发逻辑除了score_each_iteration与score_tree_interval两个显式开关外训练启动后的前_initial_score_interval默认 4000 毫秒内会持续打分此后受_score_interval默认 4000 毫秒和“打分耗时不超过训练耗时 10%”的占空比限制。测试testScoreTreeIntervalSmokentrees5, score_tree_interval2与testScoreTreeIntervalntrees100, score_tree_interval30验证了评分历史中树编号分别为 0、2、4、5 及 0、30、60、90、100且中间打分点的指标与单独训练到对应树数的模型指标一致。通用参数categorical_encoding默认auto/AUTO分类特征的编码方案。EIF 中仅使用编码的序数ordinal性质进行切分源码中gaussianVector与切分判定均作用于数值化后的特征向量。可选方案auto/AUTO默认由算法决定。对 EIF/IF算法会自动执行enum编码enum/Enum每个分类特征保留 1 列enum_limited/EnumLimited训练时自动将分类水平缩减仅保留最常出现的 T10个水平one_hot_explicit/OneHotExplicit对有 N 个水平的分类特征生成 N1 个新列binary/Binary每个分类特征不超过 32 列eigen/Eigen每个分类特征 k 列仅保留 one-hot 编码矩阵在 k 维特征空间上的投影label_encoder/LabelEncoder将每个枚举值转换为对应索引的整数如 level 0 → 0level 1 → 1 等。测试 ExtendedIsolationForestTest.java 使用OneHotExplicit编码在含分类特征的合成数据上验证了训练与打分的正确性pyunit_isoforextended_categorical.py 也从 Python 侧覆盖了分类数据场景。ignore_const_cols默认True是否忽略取值恒定的训练列因为这类列无法提供任何判别信息。ignored_columns仅 Python 与 Flow 可用指定要从建模中排除的列。在 Flow 中可通过列名复选框操作点击All添加全部列、点击None移除全部列、使用Search字段搜索列名、在“Only show columns with more than 0% missing values”字段中按缺失比例过滤、以及通过Select Visible/Deselect Visible修改隐藏列的选择。model_id为模型指定自定义名称以便引用默认由 H2O 自动生成目标 key。score_each_iteration默认禁用是否在训练的每一轮迭代都进行打分。seed默认-1即基于时间的随机数随机数生成器种子用于依赖随机化的算法组件。种子对每个 H2O 实例保持一致因此可以在不同配置下复现相同起始条件的模型。training_frame必需用于构建模型的数据集。注意在 Flow 中如果从Parse单元格点击Build a model按钮训练框会自动填入。x模型中预测变量的字符名称向量。这些参数在 REST API 层面对应的 schema 定义见 ExtendedIsolationForestV3.java其中ntrees、sample_size、extension_level、seed均标记为可网格搜索gridable truescore_tree_interval为次级参数level secondary。Python 与 R 客户端中的默认值Python 端封装 extended_isolation_forest.py 与 R 端封装 extendedisolationforest.R 中列出的参数默认值与官方文档完全一致均通过 REST 接口算法名extendedisolationforest调用后端模型构建器。异常分数Anomaly Score的计算与解读输出结构EIF 模型的预测输出包含两列见 ExtendedIsolationForestModel.java 的makeScoringNamesMOJO 侧输出名一致见 ExtendedIsolationForestMojoModel.javaanomaly_score异常分数取值在 [0, 1] 区间mean_length数据点在隔离树中从根到叶的平均路径长度。计算公式EIF 算法的输出严格遵循 Hariri 等人发表于 IEEE TKDE 的论文Extended Isolation ForestDOI: 10.1109/TKDE.2019.2947676该论文同时收录于文档的 References 一节。简言之异常分数是森林中平均mean_length经二叉搜索树BST“不成功搜索”的平均路径长度归一化后的结果。核心公式anomaly_score(x, sample_size) 2^(-mean_length(x) / c(sample_size))其中 :math:c(i)是大小为 :math:i的数据集在 BST 中不成功搜索的平均路径长度c(i) 2H(i-1) - 2(i-1)/i i 2 c(i) 1 i 2 c(i) 0 其他情况:math:H(\cdot)为调和数用欧拉常数近似估计H(·) ln(·) 0.5772156649而mean_length(x)是点 x 在森林中的平均路径长度mean_length(x) (path_length(x) c(Node.num_rows)) / ntrees当点 x 尚未被完全隔离时即落在一个包含多行数据的叶子节点上这在正常点形成的密集簇中尤其常见会使用公式 :math:c(i)依据节点行数估计树高从而对路径长度进行补偿。这一逻辑在源码中也有体现MOJO 的scoreTree0在到达叶子节点时计算pathLength height averagePathLengthOfUnsuccessfulSearch(tempNumRows)其中tempNumRows即叶子节点包含的行数。仓库中的实现细节与公式完全对应ExtendedIsolationForestMojoModel.java 中的anomalyScore与averagePathLengthOfUnsuccessfulSearch两个静态方法直接实现了上述两个公式测试 ExtendedIsolationForestTest.java 的avgPathLengTest对公式做了数值验证c(256) ≈ 10.24477、c(500) ≈ 11.58364且c(2) 1、c(1) c(0) c(-1) 0在线推理阶段非 MOJOExtendedIsolationForestModel.java 的score0方法遍历所有压缩隔离树累加路径长度并求均值最终调用同一个anomalyScore静态方法保证在线打分与 MOJO 打分结果一致。异常分数的解读规则官方文档给出了三条明确的解读准则若实例的anomaly_score非常接近 1则基本可以确定是异常点若实例的anomaly_score远小于 0.5则相当安全地视为正常实例若所有实例的anomaly_score都在 0.5 附近则说明整个样本中不存在明显的异常。烟雾测试 pyunit_isoforextended_smoke.py 恰好演示了这一解读方式的实战校验在single_blob.csv异常数据集上训练 99 棵树后断言“异常点第 0 行的 anomaly_score ≥ 0.70而普通点的得分 ≤ 0.55”并校验整体均值落在 0.36~0.40 区间。训练指标当disable_training_metrics False时模型会输出ModelMetricsAnomaly训练指标其中包含两个核心统计量见 ModelMetricsAnomaly.java_mean_score全数据集的平均路径长度均值原始分数_mean_normalized_score归一化后的平均异常分数约在 [0, 1] 区间数值越高表示越异常。计算过程由 ScoreExtendedIsolationForest.java 中的 MRTask 分布式任务完成它对训练数据分块并行打分并聚合指标。测试testFinalScoringIsCorrect验证了最终打分的 mean anomaly score 与 mean length 与ModelMetricsAnomaly中记录的指标一致。实战示例用前列腺数据集构建 EIF 模型官方文档提供了 R 与 Python 两套完整示例下面完整给出。模型在 prostate 数据集上训练用于依据 AGE、RACE、PSA 水平等特征检测异常并为每个数据点计算异常分数与隔离树中的平均路径长度。R 示例library(h2o) h2o.init() # Import the prostate dataset prostate - h2o.importFile(path https://raw.github.com/h2oai/h2o/master/smalldata/logreg/prostate.csv) # Set the predictors predictors - c(AGE, RACE, DPROS, DCAPS, PSA, VOL, GLEASON) # Build an Extended Isolation forest model model - h2o.extendedIsolationForest(x predictors, training_frame prostate, model_id eif.hex, ntrees 100, sample_size 256, extension_level length(predictors) - 1) # Calculate score score - h2o.predict(model, prostate) # Number in [0, 1] explicitly defined in Equation (1) from Extended Isolation Forest paper # or in paragraph 2 Isolation and Isolation Trees of Isolation Forest paper anomaly_score - score$anomaly_score # Average path length of the point in Isolation Trees from root to the leaf mean_length - score$mean_lengthPython 示例import h2o from h2o.estimators import H2OExtendedIsolationForestEstimator h2o.init() # Import the prostate dataset h2o_df h2o.import_file(https://raw.github.com/h2oai/h2o/master/smalldata/logreg/prostate.csv) # Set the predictors predictors [AGE, RACE, DPROS, DCAPS, PSA, VOL, GLEASON] # Define an Extended Isolation forest model eif H2OExtendedIsolationForestEstimator(model_ideif.hex, ntrees100, sample_size256, extension_levellen(predictors) - 1) # Train Extended Isolation Forest eif.train(xpredictors, training_frameh2o_df) # Calculate score eif_result eif.predict(h2o_df) # Number in [0, 1] explicitly defined in Equation (1) from Extended Isolation Forest paper # or in paragraph 2 Isolation and Isolation Trees of Isolation Forest paper anomaly_score eif_result[anomaly_score] # Average path length of the point in Isolation Trees from root to the leaf mean_length eif_result[mean_length]注意两段示例都把extension_level设为len(predictors) - 1即 P-1使用的是全扩展配置。若要模拟标准 IF 行为将其改为0即可见上文 extension_level 对照示例。训练过程中的摘要信息训练完成后模型的 Model Summary 表格会输出丰富的统计信息见 ExtendedIsolationForest.java 的createModelSummaryTable包括Number of Trees、Size of Subsample、Extension Level、Seed以及由 IsolationTreeStats 统计的树深Min/Max/Mean Depth、叶子数Min/Max/Mean Leaves、被隔离点数Min/Max/Mean Isolated Point、未被隔离点数Min/Max/Mean Not Isolated Point与零切分数Min/Max/Mean Zero Splits等。这些统计量可以用于诊断模型结构与数据可分离性。分布式训练与网格搜索EIF 属于无监督异常检测模型ModelCategory.AnomalyDetection见 ExtendedIsolationForest.java不支持 POJO 导出havePojo()返回 false但支持 MOJO 导出haveMojo()返回 true。同时它也是可网格搜索的算法extension_level、sample_size、ntrees、seed均为gridable仓库中 pyunit_isoforextended_grid.py 提供了网格搜索的测试参考。MOJO 支持模型的导入导出扩展隔离森林支持 MOJO 的导入与导出MOJO 是 H2O 的轻量级模型导出格式支持在 Java/Python 等环境中无需 H2O 集群即可进行低延迟打分相关格式说明见 保存与加载模型文档 中“Supported MOJOs”一节。MOJO 的生成由 ExtendedIsolationForestMojoWriter.java 完成MOJO 版本号 1.00它将ntrees与sample_size写入元数据并将每一棵压缩隔离树序列化为独立的二进制 blob 文件trees/t%02d.bin。MOJO 的读取与打分由 ExtendedIsolationForestMojoModel.java 与配套的 ExtendedIsolationForestMojoReader.java 完成。在训练过程中每棵构建好的树都会被压缩存储为CompressedIsolationTree对象并放入分布式键值存储DKV其 key 保存在模型输出的_iTreeKeys数组中见 ExtendedIsolationForest.java。压缩树节点CompressedNode.java只保留打分所需的随机斜率 :math:n、随机截距 :math:p与高度信息并在序列化时以NODE/LEAF类型标识符开头写出从而显著节省内存CompressedIsolationTree.java 的注释明确说明这是“内存性能更优、仅保存打分所需数据”的隔离树结构。在线打分的测试ExtendedIsolationForestTest.java 的testBasicTrainAndScore通过model.testJavaScoring(train, out, 1e-3)验证了在线打分与 MOJO 打分的数值一致性容差 1e-3。此外pyunit_generic_model_mojo_eif.py 从 Python 侧覆盖了 EIF 模型的 MOJO 导出验证。内存估算与大规模数据注意事项在构建 EIF 模型之前算法会进行内存占用预检见 ExtendedIsolationForest.java 的checkMemoryFootPrint_impl。其估算逻辑为树高上限heightLimit ceil(log2(sample_size))内部节点数估算为 :math:2^{heightLimit} - 1每个内部节点需存储两组双精度数组斜率与截距即2 × numCols × 8 字节叶子节点数估算为 :math:2^{heightLimit}每个叶子节点占用Integer.BYTES字节由于隔离树在大数据下是稀疏的单棵树内存仅按满树内存的 25% 估算总估算内存estimatedComputingMemory 5 × ntrees × 单树内存超过 driver 节点可用内存时会报错并提示减少列数、减少树数或减小sample_size。该内存检查可通过设置系统属性debug.noMemoryCheck关闭。缺失值处理FAQ一个重要的实操注意事项官方 FAQ 明确说明EIF 算法无法处理缺失值。如果训练数据中含有缺失值必须先将缺失值替换为 0 再进行训练。参考资料官方算法文档主体eif.rst相关参数文档extension_level.rst、sample_size.rst核心 Java 实现ExtendedIsolationForest.java、IsolationTree.java、ExtendedIsolationForestModel.javaMOJO 实现ExtendedIsolationForestMojoWriter.java、ExtendedIsolationForestMojoModel.java客户端封装extended_isolation_forest.py、extendedisolationforest.R测试用例ExtendedIsolationForestTest.java、pyunit_isoforextended_smoke.py论文原文S. Hariri, M. Carrasco Kind and R. J. Brunner, Extended Isolation Forest, in IEEE Transactions on Knowledge and Data Engineering, doi: 10.1109/TKDE.2019.2947676Liu, Fei Tony, Ting, Kai Ming, and Zhou, Zhi-Hua, Isolation ForestICDM 2008赞分享机器学习深度学习AutoML大数据后端【免费下载链接】h2o-3H2O is an Open Source, Distributed, Fast Scalable Machine Learning Platform: Deep Learning, Gradient Boosting (GBM) XGBoost, Random Forest, Generalized Linear Modeling (GLM with Elastic Net), K-Means, PCA, Generalized Additive Models (GAM), RuleFit, Support Vector Machine (SVM), Stacked Ensembles, Automatic Machine Learning (AutoML), etc.项目地址https://gitcode.com/gh_mirrors/h2/h2o-3点击查看免费下载相关推荐【亲测免费】 深度隔离森林Deep Isolation Forest实战指南深度隔离森林Deep Isolation Forest实战指南 欢迎来到深度隔离森林Deep iForest的实战教程本项目是基于IEEE Trans为什么 Pigar 比其他依赖管理工具更智能完整对比分析为什么 Pigar 比其他依赖管理工具更智能完整对比分析 Pigar 是一款智能的 Python 依赖管理工具它能够自动为 Python 项目生成 requCANN/asc-devkitL0C到GM配置设置asc_set_l0c2gm_config 产品支持情况 |产品 | 是否支持 | | |: :| | cann filter npu_type950人工智能深度学习算子库CANNAscend上一篇Vue CLI 快速入门安装、项目创建与系统架构全解析下一篇GLMOpenGL Mathematics头文件数学库全解析从 GLSL 兼容设计到 Gaussian Splatting 光栅化器中的实战应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站