scikit-learn IsolationForest 异常分数

机器算法验证 Python scikit-学习 异常检测 隔离森林
2022-03-23 05:52:01

根据 IsolationForest 论文(参考文献在文档中给出),Isolation Forest 产生的分数应该在 0 到 1 之间。

scikit-learn 中的实现否定了分数(因此高分更多地位于内部)并且似乎也将其移动了一些。我试图弄清楚如何扭转它,但到目前为止还没有成功。代码有一些方法和属性,如 score_samples() 和 self.offset_ 无法从拟合对象访问。代码中关于 self.contamination 用法的文档和注释似乎相互矛盾......

我有 scikit-learn 的 19.1 版(不知道从那时起 IsolationForest 实现是否有重大变化)

任何想法/建议将不胜感激!

3个回答

所以0.19.1中对应的代码IsolationForest可以在这里找到。这使您的问题更易于管理并且更少混乱,因为当前存在于 sklearn 的 master 分支上的内容与 0.19.1 版本完全不同。

在这个版本中,我们可以直接恢复基础分数,因为decision_function它们是这样提供给我们的:

/// do the work for calculating the path lengths across the ensemble ///
scores = 2 ** (-depths.mean(axis=1) / _average_path_length(self.max_samples_))
return 0.5 - scores

scores完全按照您对原始论文的期望进行计算。要恢复我们想要的,我们只需执行以下操作:

model = sklearn.ensemble.IsolationForest()
model.fit(data)
sklearn_score_anomalies = model.decision_function(data_to_predict)
original_paper_score = [-1*s + 0.5 for s in sklearn_score_anomalies]

非常重要的注意事项:这将不是scikit-learn 未来版本的默认行为decision_function,因此请评估以后版本的文档,看看你必须做什么才能从模型中恢复原始分数!

希望这有帮助!

tm1212 答案的捷径可能是:

model = sklearn.ensemble.IsolationForest()
model.fit(data)
sklearn_score_anomalies = abs(model.score_samples(data_to_predict))

分数越大,它就越有可能是一个内点。
所以你可以通过

predict = model.score_samples(X)
proba= (predict-predict.min())/(predict.max()-predict.min())
proba = 1-proba