异常检测算法——孤立森林(Isolation Forest)2008年

异常检测算法

一、孤立森林(Isolation Forest)——2008年

参考

异常检测算法 – 孤立森林(Isolation Forest)剖析

《异常检测——从经典算法到深度学习》1 基于孤立森林的异常检测算法

论文地址:Isolation Forest

1 简介

孤立森林(isolation Forest)是一种高效的异常检测算法,它和随机森林类似,但每次选择划分属性和划分点(值)时都是随机的,而不是根据信息增益或基尼指数来选择。

2 算法概述

Forest算法是由南京大学的周志华和澳大利亚莫纳什大学的Fei Tony Liu,Kai Ming Ting等人共同提出,用于挖掘数据,它是适用于连续数据(Continuous numerical data)的异常检测,将异常定义为“容易被孤立的离群点(more likely to be separated)”——可以理解为分布稀疏且离密度高的群体较远的点。用统计学来解释,在数据空间里面,分布稀疏的区域表示数据发生在此区域的概率很低,因此可以认为落在这些区域里的数据是异常的。通常用于网络安全中的攻击检测和流量异常等分析,金融机构则用于挖掘出欺诈行为。对于找出的异常数据,然后要么直接清除异常数据,如数据清理中的去噪数据,要么深入分析异常数据,比如分析攻击,欺诈的行为特征。

孤立森林(Isolation Forest) 又名孤立森林,是一种从异常点出发,通过指定规则进行划分,根据划分次数进行判断的异常检测方法。由周志华教授等人提出,对原论文感兴趣的不妨下载看看。下载地址

核心思路:循环分割(孤立),越容易被分割的判定为异常可能性越大。因为异常具有“少而不同”这一特点,所以异常数据比正常数据更容易被孤立。利用孤立森林,完成分割后,在最终形成的树中,异常将更加接近于根的位置。

孤立树: 设 T T T 为孤立树的一个节点, T T T 是没有子节点的外节点,或者一个具有测试条件的内节点,它有两个子节点 ( T l , T r ) (T_l,T_r) (Tl,Tr))。测试条件由属性 q q q 和分割值 p p p 组成,根据测试条件 q < p q<p q<p 将数据点划分到 T l T_l Tl 或者 T r T_r Tr

路径长:样本点 x x x 的路径长度 h ( x ) h(x) h(x) 为从iTree的根节点到叶子节点所经过的边的数量。

异常得分:给定一个包含 n n n 个样本的数据集,树的平均路径长度为
c ( n ) = 2 H ( n − 1 ) − 2 ( n − 1 ) n c(n)=2H(n-1)-\frac{2(n-1)}{n} c(n)=2H(n1)n2(n1)
其中 H ( i ) H(i) H(i) 为调和数,可以被估计为 ln ⁡ ( i ) + 0.5772156649 \ln(i)+0.5772156649 ln(i)+0.5772156649 c ( n ) c(n) c(n) 为给定样本 n n n 时路径长度的平均值,用来标准化样本 x x x 的路径长度 h ( x ) h(x) h(x)

样本 x x x 的异常得分定义为:
s ( x , n ) = 2 − E ( h ( x ) ) / c ( n ) s(x,n)=2^{-{ {E(h(x))}/{c(n)}}} s(x,n)=2E(h(x))/c(n)
其中 E ( h ( x ) E(h(x) E(h(x) 为样本 x x x 在一批孤立树中的路径长度的期望。

3 原理介绍

Forest 属于Non-parametricunsupervised的方法,即不用定义数学模型也不需要有标记的训练。对于如何查找哪些点是否容易被孤立(isolated),iForest使用了一套非常高效的策略。假设我们用一个随机超平面来切割(split)数据空间(data space),切一次可以生成两个子空间(详细拿刀切蛋糕一分为二)。之后我们再继续用一个随机超平面来切割每个子空间,循环下去,直到每个子空间里面只有一个数据点为止。直观上来讲,我们可以发现那些密度很高的簇是被切分很多次才会停止切割,但是那些密度很低的点很容易很早就停到一个子空间看了。

iForest 算法得益于随机森林的思想,与随机森林由大量决策树组成一样,iForest森林也由大量的二叉树组成,iForest 中的树叫 isolation tree,简称 iTreeiTree 树和决策树不太一样,其构建过程也比决策树简单,是一个完全随机的过程。

假设数据集有 N 条数据,构建一颗 ITree时,从 N条数据中均匀抽样(一般是无放回抽样)出 n 个样本出来,作为这棵树的训练样本。在样本中,随机选出一个特征,并在这个特征的所有值范围内(最小值和最大值之间)随机选一个值,对样本进行二叉划分,将样本中小于该值的划分到节点的左边,大于等于该值的划分到节点的右边。由此得到一个分裂条件和左右两边的数据集,然后分别在左右两边的数据集上重复上面的过程,直到数据集只有一条记录或者达到了树的限定高度。

由于异常数据较小且特征值和正常数据差别很大。因此,构建 iTree的时候,异常数据离根更近,而正常数据离根更远。一颗ITree的结果往往不可信,iForest算法通过多次抽样,构建多颗二叉树。最后整合所有树的结果,并取平均深度作为最终的输出深度,由此计算数据点的异常分支。

孤立树算法

iTree(X, e, L)
Inputs: X->输入数据,e->当前生成树的高度,L->生成树的最大高度
Output: 生成树(即孤立树iTree)
(1) if e >= L or |X| <= 1 then 
		达到终止条件
(2)		return exNode{
    
    Size<-|X|} 
(3)	else 
(4)		令Q为X中的一组属性
(5)		随机选择Q中的一个属性q
(6)		对于属性q,随机在[min,max]中选一个划分点p
(7)		Xl <- fiter(X,q<p)
(8)		Xr <- fiter(X,q>=p)
(9)		return inNode{
    
     把节点添加到树
			Left<-iTree(Xl,e+1,L),
			Right<-iTree(Xr,e+1,L),
			SplitAtt<-q,
			SplitValue<-p
		}
(10) end if

孤立森林算法

iForest(X, t, w)
Inputs: X->输入数据,t->树的个数,w->子采样大小
Output: t颗 iTree
(1) 初始化 iTree
(2) 设置高度限制 L = ceiling(log2(w))
(3) for i in (t):
(4)		X0 <- sample(X,w)
(5)		Forest <- Forest ∪ iTree(X0,0,L)
(6)	end for
(7)	return Forest

路径长算法

PathLength(x,T,e)
Inputs: x->一个实例,T->一棵iTree,e->当前路径长度,初始化为0
Output: x的路径长
(1) if T是一个外节点 then
(2) 	return e + c(T.size) {
    
    c(.)已经定义过}
(3) end if
(4) a <- T.splitAtt
(5) if x_a < T.splitvalue then
(6) 	return PathLength(x,T.left,e+1)
(7) else
(8) 	return PathLength(x,T.right,e+1)
(9) end if

4 算法特点

  • 孤立森林算法是一种集成学习算法
  • 孤立森林算法将异常识别为具有短路径的节点
  • 孤立森林算法具有多个作为“专家”的树,以针对不同的异常
  • 孤立森林算法不是基于模型(model-based)的算法
  • 线性事件复杂度,低内存
  • 孤立森林算法是一种非监督学习算法

5 代码实现

参数讲解
  1. n_estimators:构建多少个itree,int,optional (default=100)指定该森林中生成的随机树数量

  2. max_samples:采样数,自动是256,int,optional(default='auto)用来训练随机树的样本数量,即子采样的大小:

    1. 如果设置的是一个int常数,那么就会从总样本 X 拉取 max_samples个样本生成一棵树 iTree
    2. 如果设置的是一个float浮点数,那么就会从总样本 X 拉取 max_samples*X.shape[0] 个样本,X.shape[0] 表示总样本个数
    3. 如果设置的是 “auto”,则max_samples=min(256, n_samples),n_samples即总样本的数量
    4. 如果max_samples 值比提供的总样本的数量还大的话,所有的样本都会用来构造数,意思就是没有采样了,构造的 n_estimators棵ITree使用的样本都是一样的,即所有的样本。
  3. contamination:c(n)默认是0.1,float in (0, 0.5),optional(default=0.1),取值范围为(0, 0.5),表示异常数据占给定的数据集的比例,就是数据集中污染的数量,定义该参数值的作用是在决策函数中定义阈值。如果设置为“auto”,则决策函数的阈值就和论文一样,在版本0.20中有变换:默认值从0.1变为0.22的auto。

  4. max_features:最大特征数,默认为1,int or float,optional,指定从总样本X中抽取来训练每棵树iTree 的属性的数量,默认只使用一个属性

    1. 如果设置为 int 整数,则抽取 max_features 个属性
    2. 如果是float浮点数,则抽取 max_features *X.shape[1] 个属性
  5. bootstrap:boolean,optional(default = False),构建Tree时,下次是否替换采样,为True为替换,则各个树可放回地对训练数据进行采样;为False为不替换,即执行不放回的采样

  6. n_jobs:int or None, optional (default = None), 在运行 fit() 和 predict() 函数时并行运行的作业数量。除了在 joblib.parallel_backend 上下文的情况下,None表示为1,设置为 -1 则表示使用所有可以使用的处理器

  7. behaviour:str,default=‘old’,决策函数 decision_function 的行为,可以是“old”和‘new’。设置为 behavior='new’将会让 decision_function 去迎合其它异常检测算法的API,这在未来将会设置为默认值。

  8. random_state:int,RandomState instance or None,optional(default=None)

    1. 如果设置为 int 常数,则该 random_state 参数值是用于随机数生成器的种子
    2. 如果设置为RandomState实例,则该 random_state 就是一个随机数生成器
    3. 如果设置为None,则该随机数生成器就是使用在 np.random中RandomState实例
  9. verbose:int,optional(default=0)控制树构建过程的冗长性

  10. warm_start:bool,optional(default=False),当设置为TRUE时,重用上一次调用的结果去 fit,添加更多的树到上一次的森林1集合中;否则就 fit一整个新的森林

指标说明
ROC

ROC指标(Receiver Operating Characteristic)是一种用于评估二分类模型性能的指标。ROC曲线是以真正率(True Positive Rate,TPR)为纵轴,假正率(False Positive Rate,FPR)为横轴的曲线。

在二分类模型中,真正率(TPR)是指所有实际为正例的样本中,被正确地判定为正例的样本占比;假正率(FPR)是指所有实际为负例的样本中,被错误地判定为正例的样本占比。

ROC曲线越接近左上角,表示模型的性能越好。通常情况下,将ROC曲线下的面积称为AUC(Area Under Curve),AUC的值越大,表示模型的性能越好。

除了AUC之外,还可以根据ROC曲线的形状来评估模型的性能。ROC曲线越凸向左上角,表示模型的性能越好;如果ROC曲线几乎是一条直线,则表示模型性能较差。

ROC指标通常用于评估样本不平衡的二分类问题,例如欺诈检测、疾病诊断等领域。

ROC指标的取值范围在0到1之间,其中,AUC的取值范围也在0到1之间。当AUC的值为1时,表示模型的性能完美,即所有正例都被正确地分类为正例,所有负例都被正确地分类为负例;当AUC的值为0.5时,表示模型的性能等同于随机猜测,即模型的预测结果没有任何意义;当AUC的值小于0.5时,表示模型的性能比随机猜测还要差。

ROC曲线上的点的坐标也在0到1之间,表示模型在不同的阈值下的真正率和假正率。通常情况下,ROC曲线越靠近左上角,表示模型的性能越好,而ROC曲线越靠近45度对角线,则表示模型性能较差。

Precision、Recall和Accuracy

在机器学习和信息检索中,Precision、Recall和Accuracy是三个常用的评估指标,它们分别衡量了模型的不同方面的性能。

Precision(精确率):用于衡量分类器预测为正类的样本中有多少个真正是正类的比例。Precision的计算公式为:

P r e c i s i o n = T P T P + F P Precision = \frac{TP}{TP+FP} Precision=TP+FPTP

其中,TP表示真正例(True Positive),FP表示假正例(False Positive)。

Recall(召回率):用于衡量正类样本中有多少个被分类器正确地预测出来了。Recall的计算公式为:

R e c a l l = T P T P + F N Recall = \frac{TP}{TP+FN} Recall=TP+FNTP

其中,TP表示真正例(True Positive),FN表示假负例(False Negative)。

Accuracy(准确率):用于衡量分类器正确预测的样本数占总样本数的比例。Accuracy的计算公式为:

A c c u r a c y = T P + T N T P + T N + F P + F N Accuracy = \frac{TP+TN}{TP+TN+FP+FN} Accuracy=TP+TN+FP+FNTP+TN

其中,TP表示真正例(True Positive),TN表示真负例(True Negative),FP表示假正例(False Positive),FN表示假负例(False Negative)。

从上述公式可以看出,Precision关注的是分类器预测的正类样本中有多少是真正的正类,而Recall关注的是真正的正类样本中有多少被分类器正确地预测出来了。Accuracy则是对整个分类器的性能进行综合考虑。需要注意的是,这三个指标并不是绝对好坏的评判标准,而是需要根据具体问题和任务来选择合适的指标。例如,在不平衡的数据集中,Precision可能更重要,而在一些强烈关注误报率的应用场景中,Precision也更为关键。

precision @ rank n

precision_n_scores是一个评估信息检索系统的指标,用于衡量系统返回的前n个结果的precision。

具体代码
from pyod.models.iforest import  IForest
import numpy as np
import pandas as pd
from pyod.utils.data import evaluate_print
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
import pickle

data_origin_train = list((pd.read_csv("./node_metric.csv")).groupby('node'))[0][1]

data_origin_test = list((pd.read_csv("./node_metric3.csv")).groupby('node'))[0][1]

data_test = data_origin_test.drop(['node','metric','label'],axis=1)
data_train = data_origin_train.drop(['node','metric','label'],axis=1)
y_test = data_origin_test['label'].values
y_train = data_origin_train['label'].values


X_train =data_train.values
X_test = data_test.values

# 孤立森林
clf_name = 'IForest'
clf = IForest(n_estimators=150, max_samples=256, contamination=0.008, random_state=42)
clf.fit(X_train)


y_train_pred = clf.labels_  # 0:正常 1:异常
y_train_scores = clf.decision_scores_  # 原始的异常分数

print("\nOn Training Data:")
print(classification_report(y_train, y_train_pred))

y_test_pred = clf.predict(X_test)  # 0:正常 1:异常
y_test_scores = clf.decision_function(X_test)  # 异常分数
print("\nOn Test Data:")
print(classification_report(y_test, y_test_pred))

On Training Data:
              precision    recall  f1-score   support

         0.0       1.00      1.00      1.00      2857
         1.0       1.00      1.00      1.00        24

    accuracy                           1.00      2881
   macro avg       1.00      1.00      1.00      2881
weighted avg       1.00      1.00      1.00      2881


On Test Data:
              precision    recall  f1-score   support

           0       1.00      0.98      0.99       342
           1       0.73      1.00      0.84        19

    accuracy                           0.98       361
   macro avg       0.87      0.99      0.92       361
weighted avg       0.99      0.98      0.98       361

猜你喜欢

转载自blog.csdn.net/weixin_47692652/article/details/131177135