1. 程式人生 > >Isolation Forest算法實現詳解

Isolation Forest算法實現詳解

左右 clas 1.2 att bre 二叉 最大值和最小值 二叉樹 代碼實現

本文介紹的 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

Isolation Forest算法實現詳解