隔离森林是一种用于异常检测的无监督算法,可以快速检测数据集中的异常值。IsolationForest是一种简单但非常有效的算法,可用于快速查找数据集中的异常值。了解此算法对于处理表格数据的数据科学家来说是必须的,因此在本文中我将简要介绍算法背后的理论及其实现。因为它的算法非常简单高效,ScitkitLearn已经高效的实现了,我们可以直接调用。不过在直接上例子之前,还是有必要先介绍一下背后的理论,这样才能对算法有更深入的理解。一些理论1.什么是异常?异常(离群值)可以描述为数据集中与其他数据或观察结果有显着差异的数据点。发生这种情况的原因有多种:离群值可能表示数据不正确,或者实验可能未正确运行。离群值可能是由于随机变化引起的,或者可能表明某些科学上有趣的事情。2.为什么要进行异常检测?我们之所以要查找并深入研究异常,是因为这些数据点要么会浪费时间和精力,要么会让我们识别出一些有意义的东西。在简单线性回归的情况下,错误的异常值会增加模型的方差,进一步降低模型对数据的把握能力。离群值导致回归模型(尤其是线性模型)学习对离群值的有偏见的理解。隔离森林如何工作其他方法一直在尝试建立一个配置文件(分布、规律性等)隔离森林的优点在于它可以使用“隔离”规则直接检测异常(数据点与其余数据点的距离的数据)。这意味着该算法可以像其他距离相关模型(例如K最近邻)一样以线性时间复杂度运行。该算法以离群值最明显的特征为中心来工作:只会有少数离群值,并且会有与其他离群值明显不同的离群值。然后该特征随机选择该特征的分割值以递归地生成分区。分区过程将继续,直到将所有数据点与其余样本分开。因为在每个树实例中只选择了一个特征。可以说一棵决策树的最大深度其实就是一个,所以隔离森林的基本估计器其实是一棵极度随机的决策树(ExtraTrees),里面有各种数据子集。隔离森林中的树示例如下:上图中离群值的属性,可以观察到离群值平均需要比正常样本更少的分叉来隔离它们。每个数据点将在X轮后根据它们被隔离的难易程度得到一个分数,分数异常的数据点将被标记为异常。每个数据实例通过随机选择一个属性q和一个分割值p(在属性q的最小最大值内)递归分割,直到它们完全隔离。然后,该算法将提供一个排名,反映每个数据实例基于路径长度的异常程度。排名或分数称为异常分数,计算如下:H(x):数据实例x被完全隔离之前的步数。E[H(x)]:孤立树集合中H(x)的平均值。这些指标是有道理的,但是有一个问题:一棵树的最大可能步长是n阶,而平均步长只有logn阶。这会导致无法直接比较的步骤,因此需要引入一个随n变化的归一化常数c(n),称为路径长度归一化常数。(欧拉常数)估计谐波数。异常分数的完整公式是:因此,如果您通过隔离森林运行整个数据集,您将获得异常分数。使用异常分数s,只要存在异常分数非常接近1的实例,我们就可以推断出异常的存在。或者说任何低于0.5的分数都将被识别为正常实例。另一个警告:在sklearn的实现中,异常分数与原始论文中定义的分数相反。它减去常数0.5。这是为了方便识别异常(负分和异常一起识别),具体可以参考sklearn文档IsolationForestExample首先,我们快速导入一些有用的包,使用make_blob()函数生成一个随机数据的数据集点。importnumpyasnpiimportpandasaspdimportmatplotlib.pyplotaspltfromsklearn.datasetsimportmake_blobsdata,_=make_blobs(n_samples=500,centers=1,cluster_std=2,center_box=(0,0))plt.scatter(数据[:,0],data[:,1])plt.show()上图中很容易观察到一些异常值。这里我们使用二维用例来快速演示算法的有效性。该算法可以毫无问题地用于具有多维特征的数据集。下面通过调用IsolationForest()来初始化隔离林对象。这里使用的超参数是原论文最默认和推荐的。树的数量控制着整体的大小。路径长度通常在t=100之前收敛。除非另有说明,否则我们将使用t=100作为我们实验中的默认值。设置为256的子集样本通常可以提供足够的详细信息以在广泛的数据范围内执行异常检测。N_estimators表示树的数量,maxsamples表示用于每一轮的子集样本。max_samples='auto'将子集大小设置为min(256,num_samples)。这里的污染表示数据集中异常值的比例。默认情况下,异常分数阈值将遵循原始论文中的内容。但是,如果我们有任何先验知识,我们可以手动设置数据中异常值的比例。在本文中,它被设置为0.03。对整个数据集进行拟合和预测,返回一个[-1或1]的数组,其中-1为异常,1为正常实例。iforest=IsolationForest(n_estimators=100,contamination=0.03,max_samples='auto)prediction=iforest.fit_predict(data)print(prediction[:20])print("检测到异常值的数量:{}".format(prediction[prediction)<0].sum()))print("Numberofnormalsamplesdetected:{}".format(prediction[prediction>0].sum()))然后我们将绘制检测到的异常值。normal_data=data[np.where(prediction>0)]outliers=data[np.where(prediction<0)]plt.scatter(normal_data[:,0],normal_data[:,1])plt.scatter(outliers[:,0],outliers[:,1])plt.title("Randomdatapointswithoutliersidentified.")plt.show()你可以看到它工作得很好,识别了边缘周围的数据点。也可以调用decision_function()来计算每个数据点的异常分数。这样我们就可以了解哪些数据点更加异常。score=iforest.decision_function(data)data_scores=pd.DataFrame(list(zip(data[:,0],data[:,1],score)),columns=['X','Y','异常分数'])display(data_scores.head())按异常分数选择前5个离群值并再次绘制。top_5_outliers=data_scores.sort_values(by=['AnomalyScore']).head()plt.scatter(data[:,0],data[:,1])plt.scatter(top_5_outliers['X'],top_5_outliers['Y'])plt.title("Randomdatapointswithonly5outliersidentified.")plt.show()总结IsolationForest是一种完全不同的异常值检测模型,可以非常快速地发现异常。它具有线性时间复杂度,这使其成为处理大型数据集的最佳方法之一。它基于异常“很少且明显”的概念,因此比正常点更容易隔离。它的Python实现可以在sklearn.ensemble.IsolationForest中找到。论文地址:https://www.overfit.cn/post/079d4e026b3d42fd9131f14036a6a0f1IsolationForestbyFeiTonyLiu,KaiMingTingGippsland信息技术学院莫纳什大学,澳大利亚维多利亚。添加一名作者
