孤立森林(Isolation Forest)是经典的异常检测算法(论文网址)。本文用python对其进行实现,以及与常用的异常检测包PyOD进行效果对比。

  简单来说,孤立森林(IForest)中包含若干孤立树(ITree),每颗树的创建是独立的,与其它树无关。假设数据集包含$n$个样本,每个样本都包含$m$个实数特征。在创建每颗孤立树时,根节点首先包含所有$n$个样本。对于每个节点,随机抽取一个特征,在该特征的最大与最小值之间随机取一数$p$,将小于$p$的样本划分在左子节点,将大于$p$的样本划分在右子节点。划分直到叶节点只包含一个样本,或达到树高为止,文中树高定义为$\text{ceil}(\log_2n)$。构建好IForest后的测试阶段,就是计算样本在每颗孤立树上被划分到叶节点的平均路径长度,作为计算异常分数的依据。显然,划分路径越短,异常的可能性越高。

  实现代码如下:

#%% 函数定义
import torch
import numpy as np
import matplotlib.pyplot as plt def iTree(X:torch.Tensor, e, l):
# X数据集,e当前路径长,l树高最大值
if e >= l or len(X) <= 1:
return [0, len(X)] # 0 非叶子节点
q = np.random.randint(0, len(X[0]))
M, m = X[:, q].max(), X[:, q].min()
p = np.random.rand()*(M - m) + m
lchild = iTree(X[X[:,q] < p,:], e+1, l)
rchild = iTree(X[X[:,q] >= p,:], e+1, l)
return [1, lchild, rchild, q, p]
def c(n):
c = 0 if n == 1 else 2*(np.log(n-1)+0.5772156649) - (2*(n-1)/n)
return c
def PathLength(x, T, e):
# x样本,T树,e当前路径长
if T[0] == 0:
return e + c(T[1])
if x[T[3]] < T[4]:
return PathLength(x, T[1], e+1)
return PathLength(x, T[2], e+1)
def myIForest(X, t, psi):
# X训练集,t树数量,psi子采样
Ts = []
l = np.ceil(np.log(psi))
for i in range(t):
x_i = np.random.choice(range(len(X)), [psi], replace=False)
Ts .append(iTree(X[x_i], 0, l))
return Ts
def anomalyScore(x, Ts, psi):
length = 0
for T in Ts:
length += PathLength(x, T, 0)
length /= len(Ts)
s = 2**(-length/c(psi))
return s
#%% 定义正常分布、超参数、绘图矩阵
torch.manual_seed(0)
np.random.seed(0)
points = torch.randn([512, 2])
points[-80:] = torch.randn([80, 2])/3+4
t, psi = 100, 256
x, y = np.arange(-4.5, 5.5, 0.1), np.arange(-4.5, 5.5, 0.1)
X, Y = np.meshgrid(x, y)
XY = np.stack([X,Y], -1)
Z = np.zeros_like(X)
#%% 自定义孤立森林、异常值可视化、决策边界
myTs = myIForest(points, t, psi)
for i in range(XY.shape[0]):
for j in range(XY.shape[1]):
Z[i,j] = anomalyScore(XY[i, j], myTs, psi)
plt.plot(points[:,0],points[:,1], '.', c = "purple", alpha = 0.3)
plt.contourf(X,Y,Z)
cont = plt.contour(X,Y,Z, levels=[0.55])
plt.clabel(cont, inline=True, fontsize=10)
plt.show()
#%% pyOD孤立森林、异常值可视化、决策边界
from pyod.models.iforest import IForest
ifor = IForest(t, psi, 0.1, random_state=0)
ifor.fit(points)
h, w = XY.shape[0], XY.shape[1]
XY = XY.reshape(-1, 2)
Z = Z.reshape(-1)
Z = ifor.decision_function(XY)
Z = Z.reshape(h, w)
XY = XY.reshape(h,w,2) plt.plot(points[:,0],points[:,1], '.', c = "purple", alpha = 0.3)
plt.contourf(X,Y,Z)
cont = plt.contour(X,Y,Z, levels=[0]) #决策边界为0
plt.clabel(cont, inline=True, fontsize=10)
plt.show()

  自定义孤立森林和PyOD定义的孤立森林可视化结果分别如下左右图所示:

  效果相似。其中自定义代码完全按照论文伪代码实现,使用二叉搜索树的平均失败搜索长度进行归一化,异常分数取值$(0,1)$。PyOD的异常分数取值似乎是$(-1,1)$,以0为区分阈值,即把自定义比例的正常样本的异常分数设置为小于0,大于0则为异常样本。此处设置10%为异常,90%正常。另外,由于自定义代码没有使用并行策略,运行时间会比PyOD长得多。

孤立森林(IForest)代码实现及与PyOD对比的更多相关文章

  1. 异常检测-基于孤立森林算法Isolation-based Anomaly Detection-1-论文学习

    论文http://202.119.32.195/cache/10/03/cs.nju.edu.cn/da2d9bef3c4fd7d2d8c33947231d9708/tkdd11.pdf 1. INT ...

  2. 26.异常检测---孤立森林 | one-class SVM

    novelty detection:当训练数据中没有离群点,我们的目标是用训练好的模型去检测另外发现的新样本 outlier  dection:当训练数据中包含离群点,模型训练时要匹配训练数据的中心样 ...

  3. 孤立森林(isolation forest)

    1.简介 孤立森林(Isolation Forest)是另外一种高效的异常检测算法,它和随机森林类似,但每次选择划分属性和划分点(值)时都是随机的,而不是根据信息增益或者基尼指数来选择. 在建树过程中 ...

  4. 异常值检测方法(Z-score,DBSCAN,孤立森林)

     机器学习_深度学习_入门经典(博主永久免费教学视频系列) https://study.163.com/course/courseMain.htm?courseId=1006390023&sh ...

  5. 【异常检测】孤立森林(Isolation Forest)算法简介

    简介 工作的过程中经常会遇到这样一个问题,在构建模型训练数据时,我们很难保证训练数据的纯净度,数据中往往会参杂很多被错误标记噪声数据,而数据的质量决定了最终模型性能的好坏.如果进行人工二次标记,成本会 ...

  6. 异常检测-基于孤立森林算法Isolation-based Anomaly Detection-2-实现

    参考https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html#sklearn.en ...

  7. 孤立森林(Isolation Forest)

    前言随着机器学习近年来的流行,尤其是深度学习的火热.机器学习算法在很多领域的应用越来越普遍.最近,我在一家广告公司做广告点击反作弊算法研究工作.想到了异常检测算法,并且上网调研发现有一个算法非常火爆, ...

  8. 异常检测-基于孤立森林算法Isolation-based Anomaly Detection-3-例子

    参考:https://scikit-learn.org/stable/auto_examples/ensemble/plot_isolation_forest.html#sphx-glr-auto-e ...

  9. 使用VAE、CNN encoder+孤立森林检测ssl加密异常流的初探——真是一个忧伤的故事!!!

    ssl payload取1024字节,然后使用VAE检测异常的ssl流. 代码如下: from sklearn.model_selection import train_test_split from ...

  10. K:树、二叉树与森林之间的转换及其相关代码实现

    相关介绍:  二叉树是树的一种特殊形态,在二叉树中一个节点至多有左.右两个子节点,而在树中一个节点可以包含任意数目的子节点,对于森林,其是多棵树所组成的一个整体,树与树之间彼此相互独立,互不干扰,但其 ...

随机推荐

  1. LaTeX 生成黑底白字的 PDF

    最近需要深夜看论文,然而白底的 PDF 看久了眼睛很难受,想转换成黑底的.正好我有论文的 LaTeX 源码,因此可以直接编译黑底的 PDF 出来. 使用 darkmode 宏包 CTAN 上有一个 L ...

  2. 基于 Quanto 和 Diffusers 的内存高效 transformer 扩散模型

    过去的几个月,我们目睹了使用基于 transformer 模型作为扩散模型的主干网络来进行高分辨率文生图 (text-to-image,T2I) 的趋势.和一开始的许多扩散模型普遍使用 UNet 架构 ...

  3. 【YashanDB知识库】字段加上索引后,SQL查询不到结果

    [标题]字段加上索引后,SQL查询不到结果 [问题分类]索引功能使用 [关键字]索引,SQL查询,时间类型,vachar字符类型 [问题描述]字段加上索引后,SQL查询不到结果. [问题原因分析]当前 ...

  4. 开源大模型占GPU显存计算方法

    运行大模型GPU占用计算公式: \(M=\frac{(P * 4B)}{32 / Q} * 1/2\) M : 以GB标识的GPU内存 P : 模型中的参数数量,例如一个7B模型有70亿参数 4B : ...

  5. 关于 Splay 树

    前置芝士 $\LARGE {关于二叉搜索树及平衡树无聊的一大串子定义}$ 二叉搜索树(BST树) 定义 二叉搜索树是一种二叉树的树形数据结构,其定义如下: 空树是二叉搜索树. 若二叉搜索树的左子树不为 ...

  6. SpringMVC —— 日期类型参数传递

    日期类型参数传递    相关注解    类型转换器   

  7. Avalonia upgrade from 0.10 to 11.x

    Avalonia 从0.10版本升级到11.x版本.由于11.x新版本与旧版本对比发生了破坏性的变化,因此官方给出了升级的攻略可以参考. https://docs.avaloniaui.net/doc ...

  8. 76.最小覆盖子串 Golang实现

    题目描述: 给你一个字符串 s .一个字符串 t .返回 s 中涵盖 t 所有字符的最小子串.如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" . 注意: 对于 t ...

  9. 七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用)

    七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用) @ 目录 七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用) ...

  10. 35. vue响应式的get和set如何触发或者过程

    首先 ,vue 内部使用  Object.defineProperty 给data中的数据添加了 getter 和 setter 函数  : 当我们访问数据的时候,会触发getter 函数 retur ...