sklearn:使用隔离森林进行异常检测

时间:2017-07-12 09:41:36

标签: scikit-learn outliers anomaly-detection

我有一个不包含异常值的训练数据集:

train_vectors.shape
(588649, 896)

并且,我有另一组测试向量(test_vectors),并且它们都是异常值。

这是我尝试进行异常值检测:

from sklearn.ensemble import IsolationForest
clf = IsolationForest(max_samples=0.01)
clf.fit(train_vectors)
y_pred_train = clf.predict(train_vectors)
print(len(y_pred_train))
print(np.count_nonzero(y_pred_train == 1))
print(np.count_nonzero(y_pred_train == -1))

Output:
 588649
 529771
 58878

因此,此处异常值百分比约为10%,这是sklearn中用于隔离森林的默认污染参数。请注意,训练集中没有任何异常值。

测试代码和结果:

y_pred_test = clf.predict(test_vectors)
print(len(y_pred_test))
print(np.count_nonzero(y_pred_test == 1))
print(np.count_nonzero(y_pred_test == -1))

Output:
 100
 83
 17

因此,它只检测到100个中的17个异常。有人可以告诉我如何提高性能。我完全不确定为什么算法要求用户指定污染参数。我很清楚它被用作阈值,但我如何事先知道污染程度。谢谢!

2 个答案:

答案 0 :(得分:1)

IsolationForest与你描述的有点不同:)。 contamination是:

The amount of contamination of the data set, i.e. the proportion of outliers in the data set. Used when fitting to define the threshold on the decision function. link

这意味着您的火车组应该包含大约10%的异常值。理想情况下,您的测试集也应包含大约相同数量的异常值 - 并且仅包含异常值。

train set and test set proportions
------------------------------------------------
|  normal ~ 90%                  | outliers 10%|
------------------------------------------------

尝试按照描述更改数据集比例,然后使用您发布的代码再试一次!

希望这有帮助,祝你好运!

P.S。您也可以尝试使用正常实例训练的OneClassSVM - 测试集也应该与上面非常相似,不仅仅是异常值。

答案 1 :(得分:0)

尽管这个问题已经存在了两年之久,但由于我目前处于类似情况,因此我将其发布以供将来参考和提出类似问题的人们。

在Scikit学习文档中它指出:

异常检测:     训练数据包含离群值,离群值定义为与其他观测值相距甚远的观测值。因此,离群检测估计器会尝试拟合训练数据最集中的区域,而忽略了异常观察。

新颖性检测:     训练数据不受异常值的污染,我们有兴趣检测新观察值是否是异常值。在这种情况下,离群值也称为新颖性。

从问题的这一部分判断“(..),其中异常值百分比约为10%,这是用于sklearn中的隔离林的默认污染参数。请注意,异常值中没有任何异常值训练集。”,这表明您实际上想使用的是新颖检测

正如@mkaran所建议的,OneClassSVM可以用于新颖性检测,但是,由于它有点慢,因此我建议在这种情况下的任何人都应尝试使用本地异常值。 另外,从sklearn 0.22版开始,IsolationForest算法不需要污染,这可能非常有用。