此篇主要介绍以下内容:
隔离森林(Isolation Forest) 又名孤立森林,是一种从异常点出发,通过指定规则进行划分,根据划分次数进行判断的异常检测方法。由周志华教授等人提出,对原论文感兴趣的不妨下载看看。下载地址
核心思路:循环分割(隔离),越容易被分割的判定为异常可能性越大。因为异常具有“少而不同”这一特点,所以异常数据比正常数据更容易被隔离。利用隔离森林,完成分割后,在最终形成的树中,异常将更加接近于根的位置。
隔离树: 设Tshi隔离树的一个节点,T是没有子节点的外节点,或者一个具有测试条件的内节点,它有两个子节点( T l , T r T_l,T_r Tl,Tr)。测试条件由属性q和分割值p组成,根据测试条件q
T l T_l Tl或者 T r T_r Tr。
隔离树主要过程:
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 U iTree(X0,0,L)
(6) end for
(7) return Forest
隔离森林算法特点:
隔离森林(IsolationForest)在sklearn中已有实现,接下来的内容均来自于sklearn官网。详细地址为:https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html?highlight=isolationforest#sklearn.ensemble.IsolationForest
官网例子1
from sklearn.ensemble import IsolationForest
X = [[-1.1], [0.3], [0.5], [100]]
clf = IsolationForest(random_state=0).fit(X)
clf.predict([[0.1], [0], [90]])
输出内容:array([ 1, 1, -1])
简单理解就是训练集中存在一个离群点 100
,对于测试集中的 90
,很明显会最先被隔离,所以算法认为 90
是异常点。
补充:如果测试数 10
,则会输出 1 ,因为算法认为 10 不算离群点。
官网例子2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest
rng = np.random.RandomState(42)
# Generate train data
X = 0.3 * rng.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
# Generate some regular novel observations
X = 0.3 * rng.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
# Generate some abnormal novel observations
X_outliers = rng.uniform(low=-4, high=4, size=(20, 2))
# fit the model
clf = IsolationForest(max_samples=100, random_state=rng)
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
# plot the line, the samples, and the nearest vectors to the plane
xx, yy = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.title("IsolationForest")
plt.contourf(xx, yy, Z, cmap=plt.cm.Blues_r)
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white',
s=20, edgecolor='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='green',
s=20, edgecolor='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='red',
s=20, edgecolor='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([b1, b2, c],
["training observations",
"new regular observations", "new abnormal observations"],
loc="upper left")
plt.show()
输出结果如图所示:
这样更加直观,离群点可以看得非常明显。例子2和例子1区别不大,只是为了可视化,更加直观,添加了很多绘图代码。
隔离森林算法是基于两个重要假设下提出的:1. 异常是少量的;2.异常数据与正确数据有明显的区别,或者说异常数据与正常数据相比,具有非常不同的属性值。
另外算法运行时随机采样的数目非常重要,举个极端的例子,一次采样中采样10个数据,很不巧有9个是异常数据,那么,正常数据将会被认为是异常数据。对于这种情况可以考虑多次随机采样(即设置sklearn函数中的 n_estimators
参数) 与设置异常数所占的比例(即 contamination
参数),并设置为有放回的取样,若对于不同取样样本中同一个数据,多次都被认为是异常,那么就认为它是异常。若预先设定好的比例,超出比例的部分将不会被认为是异常。
参考文档
Isolation Forest 论文 下载地址
sklearn 官网
https://www.cnblogs.com/fengfenggirl/p/iForest.html
Smileyan
2020年5月21日