sklearn:使用隔离森林进行异常检测
sklearn: Anomaly detection using Isolation Forests
我有一个不包含异常值的训练数据集:
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 个。有人能告诉我如何提高性能吗?我完全不确定为什么该算法要求用户指定污染参数。我很清楚它被用作阈值,但我如何事先知道污染水平。谢谢!
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,它仅使用正常实例进行训练 - 测试集也应该与上面非常相似,而不仅仅是异常值。
虽然这个问题已经有几年了,但我将其发布以供将来参考和提出类似问题的人使用,因为我目前处于类似情况。
在 Scikit Learn 文档中指出:
离群值检测:
训练数据包含离群值,这些离群值被定义为与其他观察值相差甚远的观察值。因此,异常值检测估计器会尝试拟合训练数据最集中的区域,而忽略异常观察值。
新奇检测:
训练数据没有被离群值污染,我们有兴趣检测新观察是否是离群值。在这种情况下,离群值也称为新奇事物。
从问题的这一部分判断“(..)这里的异常值百分比约为 10%,这是 sklearn 中用于隔离森林的默认污染参数。请注意,没有训练集中的任何异常值。”这表明您可能想要使用的实际上是 Novelty Detection。
正如@mkaran 所建议的,OneClassSVM 可用于新颖性检测,但是,由于它有点慢,我建议在这种情况下的任何人都尝试使用 Local Outlier Factor。
此外,从 sklearn 版本 0.22 开始,IsolationForest 算法不需要污染,这可能非常有用。
我有一个不包含异常值的训练数据集:
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 个。有人能告诉我如何提高性能吗?我完全不确定为什么该算法要求用户指定污染参数。我很清楚它被用作阈值,但我如何事先知道污染水平。谢谢!
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,它仅使用正常实例进行训练 - 测试集也应该与上面非常相似,而不仅仅是异常值。
虽然这个问题已经有几年了,但我将其发布以供将来参考和提出类似问题的人使用,因为我目前处于类似情况。
在 Scikit Learn 文档中指出:
离群值检测: 训练数据包含离群值,这些离群值被定义为与其他观察值相差甚远的观察值。因此,异常值检测估计器会尝试拟合训练数据最集中的区域,而忽略异常观察值。
新奇检测: 训练数据没有被离群值污染,我们有兴趣检测新观察是否是离群值。在这种情况下,离群值也称为新奇事物。
从问题的这一部分判断“(..)这里的异常值百分比约为 10%,这是 sklearn 中用于隔离森林的默认污染参数。请注意,没有训练集中的任何异常值。”这表明您可能想要使用的实际上是 Novelty Detection。
正如@mkaran 所建议的,OneClassSVM 可用于新颖性检测,但是,由于它有点慢,我建议在这种情况下的任何人都尝试使用 Local Outlier Factor。 此外,从 sklearn 版本 0.22 开始,IsolationForest 算法不需要污染,这可能非常有用。