本文介绍的 Isolation Forest 算法原理请参看我的博客:Isolation Forest异常检测算法原理详解,本文中我们只介绍详细的代码实现过程。

1、ITree的设计与实现

首先,我们参看原论文中的ITree的构造伪代码:

这里写图片描述

1.1 设计ITree类的数据结构

由原论文[1,2]以及上述伪代码可知,ITree是一个二叉树,并且构建ITree的算法采用的是递归构建。同时构造的结束条件是:

当前节点的高度超过了算法设置的阈值 l ;
当前子树只包含一个叶节点;
当前子树的所有节点值的所有属性完全一致。
并且在递归的时候,我们需要随机的选择属性集 Q 中的一个属性Qi以及该属性在给出的输入数据上对应的最大值和最小值之间的一个值 q ,来将当前节点包含的样本分为左右子树。因此我们为了后续算法设计的方便,需要记录被选中的属性Qi的索引值 attrIndex,以及算出来的q值attrValue,因为后面算法需要根据该节点为根节点的子树包含的叶节点总数估计该节点总高度,因此我们还需要定义一个变量leafNodes记录树的叶子节点总数,同时我们还需要一个成员变量curHeight来记录该节点的实际高度。当然,二叉树少不了定义左右子树指针 lTree 和 rTree。

因此,我设计了如下的数据结构ITree:

public class ITree {

// 被选中的属性索引
public int attrIndex;

// 被选中的属性的一个具体的值
public double attrValue;

// 树的总叶子节点数
public int leafNodes;

// 该节点在树种的高度
public int curHeight;

// 左右孩子书
public ITree lTree, rTree;

// 构造函数,初始化ITree中的值
public ITree(int attrIndex, double attrValue) {
// 默认高度,树的高度从0开始计算
this.curHeight = 0;

this.lTree = null;
this.rTree = null;
this.leafNodes = 1;
this.attrIndex = attrIndex;
this.attrValue = attrValue;

1.2 递归地构造二叉树ITree

根据原论文中的算法2的伪代码,我们知道递归地构造二叉树ITree分为两个部分:

第一,首先判断是否满足1.1节列出的三个递归结束条件;

第二,随机的选取属性集中的一个属性以及该属性集下的一个具体的值,然后根据该属性以及生成的属性值将父节点中包含的样本数据划分到左右子树,并递归地创建左右子树。

同时记录每个节点包含的叶子节点数和当前节点在整个树中的实际高度。

参看如下的详细代码实现:

/**
* 根据samples样本数据递归的创建 ITree 树
*/
public static ITree createITree(http://www.wmyl15.com/ double[][] samples, int curHeight,
int limitHeight)
{

ITree iTree = null;

/*************** 第一步:判断递归是否满足结束条件 **************/
if (samples.length == 0) {
return iTree;
} else if (curHeight >= limitHeight || samples.length == 1) {
iTree = new ITree(0, samples[0][0]);
iTree.leafNodes = 1;
iTree.curHeight = curHeight;
return iTree;
}

int rows = samples.length;
int cols = samples[0].length;

// 判断是否所有样本都一样,如果都一样构建也终止
boolean isAllSame = true;
break_label:
for (int i = 0; i < rows - 1; i++) {
for (int j = 0; j < cols; http://www.wmyl11.com/ j++) {
if (samples[i][j] != samples[i + 1][j]) {
isAllSame = false;
break break_label;
}
}
}

// 所有的样本都一样,构建终止,返回的是叶节点
if (isAllSame == true) {
iTree = new ITree(0, samples[0][0]);
iTree.leafNodes = samples.length;
iTree.curHeight = curHeight;
return iTree;
}

/*********** 第二步:不满足递归结束条件,继续递归产生子树 *********/
Random random = new Random(System.currentTimeMillis());
int attrIndex = random.nextInt(cols);

// 找这个被选维度的最大值和最小值
double min, max;
min = samples[0][attrIndex];
max = min;
for (int i = 1; i < rows; i++) {
if (samples[i][attrIndex] < min) {
min = samples[www.zhouyajinguawang.cn i][attrIndex];
}
if (samples[i][attrIndex] > max) {
max = samples[i][attrIndex];
}
}

// 计算划分属性值
double attrValue = random.nextDouble() * (max - min) + min;

// 将所有的样本的attrIndex对应的属性与
// attrValue 进行比较以选出左右子树对应的样本
int lnodes = 0, rnodes = 0;
double curValue;
for (int i = 0; i < rows; i++) {
curValue = samples[i www.wmylcs.com ][attrIndex];
if (curValue < attrValue) {
lnodes++;
} else {
rnodes++;
}
}

double[][] lSamples = new double[lnodes][cols];
double[][] rSamples = new double[rnodes][cols];

lnodes = 0;
rnodes = 0;
for (int i = 0; i < rows; i++) {
curValue = samples[i][attrIndex];
if (curValue < attrValue) {
lSamples[lnodes++] = samples[i];
} else {
rSamples[rnodes++] = samples[i];
}
}

// 创建父节点
ITree parent = new ITree( www.feifanshifan8.cn attrIndex, attrValue);
parent.leafNodes = rows;
parent.curHeight = curHeight;
parent.lTree = createITree(lSamples, curHeight + 1, limitHeight);
parent.rTree = createITree(rSamples, curHeight + 1, limitHeight);

return parent;
今天已晚,我要下班,未完待续……
这里写图片描述

这里写图片描述

参考文献:

http://www.yongshiyule178.com /zhouzh.files/publication/icdm08b.pdf
http://cs.nju.edu.cn/zhouzh/zhouzh.files/publication/tkdd11.pdf

最新文章

  1. angularjs中provider,factory,service的区别和用法
  2. 数据导出Excel中文乱码
  3. 3D数学 ---- 矩阵和线性变换[转载]
  4. dos下mysql登陆
  5. 23.C#Queryable的扩展方法(十二章12.1-12.2)
  6. 开启Ubuntu Linux下VirtualBox访问USB功能
  7. MongoDB介绍及下载与安装
  8. php文本操作方法集合
  9. bzoj3091
  10. linux i2c驱动架构-dm368 i2c驱动分析
  11. hdu 5183(hash)
  12. Java 三目运算符表达式的一些问题
  13. win10下配置php环境变量
  14. Oracle:SQL语句--对表的操作——修改表名
  15. php缓存机制
  16. 24.API爬天气预报数据
  17. 用MFC(C++)实现拼音搜索
  18. SPI SWD Protocol Implement
  19. java关于类加载的面试题
  20. javascript---对象和函数的引用、浅拷贝、深拷贝、递归

热门文章

  1. SWFObject是什么
  2. js修改css时如何考虑兼容性问题es5+es6
  3. BEC listen and translation exercise 39
  4. Python解决中文字符的问题
  5. tbody scroll
  6. ffmpeg处理RTMP流媒体的命令和发送流媒体的命令(UDP,RTP,RTMP)
  7. ACM学习历程—HDU 5536 Chip Factory(xor &amp;&amp; 字典树)
  8. PUN介绍(干货)
  9. 【转】 Pro Android学习笔记(三四):Menu(5):动态菜单
  10. JavaScript-Tool:jquery.cookie.js