异常检测算法库PyOD

前言

  • 本文介绍一种十分强大的数据异常检测算法库PyOD(Python Outlier Detection),github项目地址。官方文档说明
  • PyOD是最全面且可扩展的Python库,用于检测多元数据中的异常对象。PyOD包含 40 多种检测算法,从经典的LOF(SIGMOD 2000)到最新的ECOD(TKDE 2022)。
  • PyOD库的优点是:
    • 跨各种算法的统一API、详细文档和交互式示例。
    • 先进的模型,包括经典的距离和密度估计、最新的深度学习方法以及ECOD等新兴算法。
    • 使用numbajoblib通过JIT和并行化优化性能。
    • 使用SUOD进行快速训练和预测
  • 最近该库的作者发布了一篇45页最全面的异常检测基准论文。在57个基准数据集上比较了30种异常检测算法。总体来说,该篇论文经过实验发现在各数据集上KNNIForestECOD算法表现均不错,若对数据无任何强烈认知,可以先尝试这3种算法。
  • 本文以KNNIForestECOD算法为示例,说明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个可选项,分别为KNNIForestECOD
    • 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)

输出:

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)

输出:

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)
  • KNNECODIForest算法进行组合
# 初始化一组异常检测器
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)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羽星_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值