前言
- 本文介绍一种十分强大的数据异常检测算法库
PyOD
(Python Outlier Detection
),github项目地址。官方文档说明。 -
PyOD
是最全面且可扩展的Python
库,用于检测多元数据中的异常对象。PyOD
包含 40 多种检测算法,从经典的LOF
(SIGMOD 2000)到最新的ECOD
(TKDE 2022)。 -
PyOD
库的优点是:- 跨各种算法的统一
API
、详细文档和交互式示例。 - 先进的模型,包括经典的距离和密度估计、最新的深度学习方法以及
ECOD
等新兴算法。 - 使用
numba
和joblib
通过JIT
和并行化优化性能。 - 使用
SUOD
进行快速训练和预测
- 跨各种算法的统一
- 最近该库的作者发布了一篇45页最全面的异常检测基准论文。在57个基准数据集上比较了30种异常检测算法。总体来说,该篇论文经过实验发现在各数据集上
KNN
、IForest
、ECOD
算法表现均不错,若对数据无任何强烈认知,可以先尝试这3种算法。 - 本文以
KNN
、IForest
、ECOD
算法为示例,说明PyOD
库的使用方法
环境安装
- 若有预先安装
git
可以使用以下代码安装依赖库
!git clone https://github.com/yzhao062/pyod.git
%cd pyod
!pip install .
!pip install -r requirements_ci.txt
%cd ..
- 若没有
git
工具,可以使用pip
安装依赖库
!pip install pyod
!pip install combo
!pip install joblib
!pip install pythresh
!pip install suod
- 导入必要包
import numpy as np
from pyod.models.knn import KNN
from pyod.models.ecod import ECOD
from pyod.models.iforest import IForest
from pyod.utils.data import generate_data
from pyod.utils.example import visualize
from pyod.utils.data import evaluate_print
from pyod.utils.utility import standardizer
from pyod.models.combination import aom, moa, average, maximization, median
from pyod.models.thresholds import FILTER
from pyod.models.suod import SUOD
单算法对比
- 我们首先创建一个数据集,可以使用
PyOD
库的generate_data
函数,n_features
参数为特征数,这里为了方便可视化,所以设为2,及二维特征。
# 异常值比例
contamination = 0.1
# 训练集样本数
n_train = 2000
# 测试集样本数
n_test = 200
X_train, X_test, y_train, y_test = generate_data(n_train=n_train, n_test=n_test, contamination=contamination, n_features = 2, random_state = 2023)
- 为了减少代码冗余,构造函数将模型训练、测试、输出精度指标、可视化这些工作融合到一起
def create_clf(model_name, X_train, X_test, y_train, y_test, contamination=None, **kwargs):
model_mapping = {
'KNN': KNN,
'ECOD': ECOD,
'IForest': IForest
}
model_class = model_mapping.get(model_name)
# 自动确定异常阈值
if contamination == None:
contamination = FILTER()
print("Auto calculate contamination!!")
clf = model_class(contamination = contamination, **kwargs)
clf.fit(X_train)
# 获取训练数据的预测标签和异常值分数
# 标签(0:正常值,1:异常值)
y_train_pred = clf.labels_
# 样本异常值分数
y_train_scores = clf.decision_scores_
# 获取测试数据的预测
y_test_pred = clf.predict(X_test)
# 预测标签(0:正常值,1:异常值)
y_test_scores = clf.decision_function(X_test)
# 预测置信度
# 标签(0,1)和[0,1]范围内的置信度
y_test_pred, y_test_pred_confidence = clf.predict(X_test, return_confidence=True)
# 评估模型在训练集上的指标
print("\nOn Training Data:")
evaluate_print(model_name, y_train, y_train_scores)
# 评估模型在测试集上的指标
print("\nOn Test Data:")
evaluate_print(model_name, y_test, y_test_scores)
# 可视化检测效果
visualize(model_name, X_train, y_train, X_test, y_test, y_train_pred,
y_test_pred, show_figure=True, save_figure=False)
- 函数参数说明:
-
model_name
:要选择训练的模型,只有3个可选项,分别为KNN
、IForest
、ECOD
-
X_train
,X_test
,y_train
,y_test
:训练集、测试集以及对应的标签 -
contamination
:异常样本阈值,一般情况下这个值是未知的,可能需要凭借经验。但PyOD
库结合PyThresh
库实现自动确定阈值(根据统计分析避免主观意识对结果的影响)。当函数不传入该参数时,由算法自动确定该参数(阈值)
-
-
PyThresh
库旨在对异常值检测器生成的似然分数进行阈值处理。它包含30多种阈值算法。这些算法的范围从使用Z分数等简单的统计分析到涉及图论和拓扑的更复杂的数学方法。github项目地址
KNN异常检测算法
- 根据上述函数参数,代码如下:
create_clf('KNN', X_train, X_test, y_train, y_test, contamination=contamination)
输出:
On Training Data:
KNN ROC:0.9994, precision @ rank n:0.99
On Test Data:
KNN ROC:0.9903, precision @ rank n:0.95
ECOD异常检测算法
create_clf('ECOD', X_train, X_test, y_train, y_test, contamination=contamination)
输出:
On Training Data:
ECOD ROC:0.9648, precision @ rank n:0.69
On Test Data:
ECOD ROC:0.9311, precision @ rank n:0.55
IForest异常检测算法
create_clf('IForest', X_train, X_test, y_train, y_test, contamination=contamination)
输出:
On Training Data:
IForest ROC:0.9997, precision @ rank n:0.99
On Test Data:
IForest ROC:0.9908, precision @ rank n:0.95
KNN自动确定阈值
- 根据前面说的函数参数,当我们需要算法自动确定阈值时,不传入
contamination
参数
create_clf('KNN', X_train, X_test, y_train, y_test)
输出:文章来源:https://www.toymoban.com/news/detail-645296.html
Auto calculate contamination!!
On Training Data:
KNN ROC:0.9994, precision @ rank n:0.99
On Test Data:
KNN ROC:0.9903, precision @ rank n:0.95
- 可以看到精度指标基本上和传入
contamination
参数时一致,说明了自动阈值确定算法的有效性。
组合模型异常检测
- 由于各模型无监督的性质,异常值检测经常会受到模型不稳定的影响。因此,建议组合各种检测器输出,例如通过平均,以提高其鲁棒性。
- 本文主要展示四种分数组合机制:
-
Average
:所有模型的平均分数。 -
Maximization
:所有模型的最大分数。 -
Average of Maximum (AOM)
:将模型分为子组,并取每个子组的最大分数。最终成绩为所有小组成绩的平均分。 -
Maximum of Average (MOA)
:将模型分为子组,并取每个子组的平均分数。最终得分为所有小组得分中的最高分。
-
- 因为各模型对数据变化的敏感性不同,所以在进行组合模型异常检测时,要先进行数据标准化
- 我们将不同
n_neighbors
参数的KNN
模型组合,然后将其训练集、测试集得分整合到一起
# 数据标准化
X_train_norm, X_test_norm = standardizer(X_train, X_test)
k_list = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140,
150, 160, 170, 180, 190, 200]
n_clf = len(k_list)
train_scores = np.zeros([X_train.shape[0], n_clf])
test_scores = np.zeros([X_test.shape[0], n_clf])
for i in range(n_clf):
k = k_list[i]
clf = KNN(n_neighbors=k, method='largest')
clf.fit(X_train_norm)
train_scores_norm, test_scores_norm = standardizer(train_scores, test_scores)
train_scores[:, i] = clf.decision_scores_
test_scores[:, i] = clf.decision_function(X_test_norm)
- 对各模型的得分进行标准化,然后进行组合
train_scores_norm, test_scores_norm = standardizer(train_scores, test_scores)
comb_by_average = average(test_scores_norm)
comb_by_maximization = maximization(test_scores_norm)
comb_by_median = median(test_scores_norm)
# 分为5组
comb_by_aom = aom(test_scores_norm, 5)
comb_by_moa = moa(test_scores_norm, 5)
- 评估组合模型的检测精度
evaluate_print('Combination by Average', y_test, comb_by_average)
evaluate_print('Combination by Maximization', y_test, comb_by_maximization)
evaluate_print('Combination by Median', y_test,comb_by_median)
evaluate_print('Combination by AOM', y_test, comb_by_aom)
evaluate_print('Combination by MOA', y_test, comb_by_moa)
输出:文章来源地址https://www.toymoban.com/news/detail-645296.html
Combination by Average ROC:0.99, precision @ rank n:0.95
Combination by Maximization ROC:0.9886, precision @ rank n:0.95
Combination by Median ROC:0.9897, precision @ rank n:0.95
Combination by AOM ROC:0.9894, precision @ rank n:0.95
Combination by MOA ROC:0.9892, precision @ rank n:0.95
- 因为数据为低纬,小样本数据,所以检测难度不高,用单一的
KNN
模型已经可以达到很好的精度了,所以使用组合模型提升的效果不明显。
异模型组合SUDO
-
PyOD
库还提供了不同模型间组合的SUDO
通道,也非常便捷
def suod_clf(detector_list, X_train, X_test, y_train, y_test, contamination=None):
# 自动确定异常阈值
if contamination == None:
contamination = FILTER()
print("Auto calculate contamination!!")
clf = SUOD(base_estimators=detector_list, n_jobs=1, combination='average', verbose=False)
clf.fit(X_train)
# 获取训练数据的预测标签和异常值分数
# 标签(0:正常值,1:异常值)
y_train_pred = clf.labels_
# 样本异常值分数
y_train_scores = clf.decision_scores_
# 获取测试数据的预测
y_test_pred = clf.predict(X_test)
# 预测标签(0:正常值,1:异常值)
y_test_scores = clf.decision_function(X_test)
# 预测置信度
# 标签(0,1)和[0,1]范围内的置信度
y_test_pred, y_test_pred_confidence = clf.predict(X_test, return_confidence=True)
# 评估模型在训练集上的指标
print("\nOn Training Data:")
evaluate_print(model_name, y_train, y_train_scores)
# 评估模型在测试集上的指标
print("\nOn Test Data:")
evaluate_print(model_name, y_test, y_test_scores)
# 可视化检测效果
visualize(model_name, X_train, y_train, X_test, y_test, y_train_pred,
y_test_pred, show_figure=True, save_figure=False)
- 将
KNN
、ECOD
、IForest
算法进行组合
# 初始化一组异常检测器
detector_list = [KNN(n_neighbors=10), KNN(n_neighbors=20),
KNN(n_neighbors=30), KNN(n_neighbors=40),
ECOD(), IForest(n_estimators=100),
IForest(n_estimators=200)]
# 决定并行进程的数量,以及组合方法
suod_clf(detector_list, X_train, X_test, y_train, y_test)
到了这里,关于异常检测算法库PyOD的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!