datawhale 5月学习——异常检测

task 1 异常检测概述

异常检测有多种应用场景,根据任务的不同,相关技术可以用于回归/分类问题的预处理(如果这类问题要求数据全为合理值),也可以用于直接的异常检测任务(如系统故障诊断、信用卡欺诈等)。
其中,特别是在实际工程应用中,大多数情况下没有异常标签,所以无监督预测占很大比例;另外,在一些数据收集无法十分频繁的问题(如机房巡检),或者是数据集本身有严格要求的(如身份证号数据库)上,缺乏异常数据,这部分问题需要半监督预测方法。
噪音及异常数据缺乏时异常检测的难点,故一般的机器学习方法,很多没有办法直接应用。
常见的异常检测方法包括数据预处理常用的统计学方法,除此之外集成学习方法、机器学习方法也是重要的方法类型。

task 2 基于统计学的方法

基于统计学的方法是目前初学者最常用的方法。

它们假定正常的数据对象由一个统计模型产生,而不遵守该模型的数据是异常点。
异常检测的统计学方法的一般思想是:学习一个拟合给定数据集的生成模型,然后识别该模型低概率区域中的对象,把它们作为异常点。

一般分为参数方法(预先假定分布)和非参数方法(预先不假定分布,通过输入数据确定分布)两类,以下分两类展开。

参数方法

包括最常用的IQR箱型图方法(即基于正态分布假设),如:
在这里插入图片描述
和多元异常点检测(独立高斯分布,或联合高斯分布)——暂无实例

非参数方法

主要讲的是直方图检测异常点,还是需要确定箱的尺寸,防止漏查或多查
在这里插入图片描述

基于角度的方法

基于角度的方法的主要思想是:数据边界上的数据很可能将整个数据包围在一个较小的角度内,而内部的数据点则可能以不同的角度围绕着他们。如下图所示,其中点A是一个异常点,点B位于数据内部。
如果数据点与其余点离得较远,则潜在角度可能越小。因此,具有较小角度谱的数据点是异常值,而具有较大角度谱的数据点不是异常值。

可以通过计算ABOF(基于角度的异常分数)来确定是不是异常值。
暂无实例

HBOS

这是一种在大数据集中运行比较快的方法,基于直方图。不能检测局部异常值,但在全局异常值上效果良好。

HBOS全名为:Histogram-based Outlier Score。它是一种单变量方法的组合,不能对特征之间的依赖关系进行建模,但是计算速度较快,对大数据集友好。其基本假设是数据集的每个维度相互独立。然后对每个维度进行区间(bin)划分,区间的密度越高,异常评分越低。

需要划分训练集和测试集,使用pyod库的内置函数,尝试后效果如下:训练集
训练集
测试集
测试集

task 3 异常检测——线性相关方法

本次首先简单介绍了回归建模

真实数据集中不同维度的数据通常具有高度的相关性,这是因为不同的属性往往是由相同的基础过程以密切相关的方式产生的。在古典统计学中,这被称为——回归建模,一种参数化的相关性分析。
一类相关性分析试图通过其他变量预测单独的属性值,另一类方法用一些潜在变量来代表整个数据。前者的代表是 线性回归,后者一个典型的例子是 主成分分析。本文将会用这两种典型的线性相关分析方法进行异常检测。

有两个重要的假设:

假设一:近似线性相关假设。线性相关假设是使用两种模型进行异常检测的重要理论基础。
假设二:子空间假设。子空间假设认为数据是镶嵌在低维子空间中的,线性方法的目的是找到合适的低维子空间使得异常点(o)在其中区别于正常点(n)。

基于这两点假设,在异常检测的第一阶段,为了确定特定的模型是否适合特定的数据集,对数据进行探索性和可视化分析是非常关键的。

使用线性回归进行异常检测

线性回归的超定方程组可使用最小二乘法或优化方法(梯度下降法等)进行求解

异常检测中并不会对任何变量给与特殊对待,异常值的定义是基于基础数据点的整体分布,因此需要采用一种更一般的回归建模:即以相似的方式对待所有变量,通过最小化数据对该平面的投影误差确定最佳回归平面。

本质上是找到一个与数据具有最佳匹配 ( d − 1 ) (d−1) (d1) 维超平面。

使用主成分分析进行异常检测

主成分分析方法可以找到任意 k ( k < d ) k( k<d ) k(k<d) 维的最优表示超平面,从而使平方投影误差最小化。

在许多涉及高维数据集的真实场景中,很大一部分特征值往往非常接近于零。这意味着大多数数据都沿着一个低维的子空间排列。从异常检测的角度来看,这是非常方便的,因为离这些投影方向非常远的观测值可以被假定为离群值。例如,对于特征值较小(方差较小)的特征向量 j j j,第 i i i 条记录的 y i j y_{ij} yij y k j y_{kj} ykj 的其他值的偏差较大,说明有离群行为。这是因为当 j j j固定而 k k k变化时, y k j y_{kj} ykj 的值应当变化不大。因此, y i j y_{ij} yij 值是不常见的。

值得注意的是,对异常得分的大部分贡献是由 λ j λ_{j} λj 值较小的主成分的偏差提供的。主成分分析比因变量回归能更稳定地处理少数异常值的存在。这是因为主成分分析是根据最优超平面来计算误差的,而不是一个特定的变量。当数据中加入更多的离群点时,最优超平面的变化通常不会大到影响离群点的选择。因此,这种方法更有可能选择正确的异常值,因为回归模型一开始就更准确。

由于受到离群点的影响较小,主成分分析法相较线性回归更稳定。

回归异常检测方法的局限性

  1. 当数据不相关,但在某些区域高度聚集时,会失效;
  2. 数据中的相关性在本质上可能不是全局性的。子空间相关性可能是特定于数据的特定位置的。在这种情况下,由主成分分析发现的全局子空间对于异常检测是次优的。因此,为了创建更一般的局部子空间模型,有时将线性模型与邻近模型结合起来是有用的。

这样看起来比较抽象,最好是使用不同的数据集进行尝试,会有更加直观的印象。(待补充)

task 4:基于相似度的方法

异常检测一个很重要的事情在于,需要衡量异常值。通常来讲,异常值即与正常值不同的值,应该可以找到一种度量方式,使得异常值点远离正常值而可以被识别出来,此时异常值也称为离群值。
定义离群值分析的邻近度的最常见方法有:

  • 基于聚类:远离类簇的应视为离群值;
  • 基于距离:类似于k近邻;
  • 基于密度:使用数据点的指定局部区域(栅格区域或基于距离的区域)内的其他点的数量来定义局部密度。聚类和基于密度的方法的主要区别在于,聚类方法划分数据点,而基于密度的方法划分数据空间。

基于距离的度量

kNN方法,使用pyod.models.knn.KNN()进行训练及预测,代码见官方文档。
根据官方说明,kNN的默认距离为闵可夫斯基距离(‘minkowski’),此外也可以为

来自scikit-learn:[‘cityblock’,‘cosine’,‘euclidean’,‘l1’,‘l2’,‘manhattan’]
来自scipy.spatial.distance:[‘braycurtis’,‘canberra’,‘chebyshev’,‘correlation’,'dice,‘hamming’,‘jaccard’,‘kulsinski’,‘mahalanobis’,‘matching’,‘minkowski’,‘rogerstanimoto’,‘russellrao’,‘seuclidean’,‘sokalmichener’,‘sokalsneath’,‘sqeuclidean’,‘yule’]]

在这里插入图片描述在这里插入图片描述
可以将异常值检查出来,但存在真实值误查为异常值

基于距离的异常检测有这样一个前提假设,即异常点的 k k k 近邻距离要远大于正常点。解决问题的最简单方法是使用嵌套循环。 第一层循环遍历每个数据,第二层循环进行异常判断,需要计算当前点与其他点的距离,一旦已识别出多于 k k k 个数据点与当前点的距离在 D D D 之内,则将该点自动标记为非异常值。 这样计算的时间复杂度为 O ( N 2 ) O(N^{2}) O(N2),当数据量比较大时,这样计算是及不划算的。 因此,需要修剪方法以加快距离计算。

有几种常见的修剪方法:

  • 基于单元
  • 基于索引

基于单元的方法(Cell-based)

定义L1,L2两类邻域,就算某个单元格中,有一定数量的数据点,但当其与其L1、L2邻域内数据点的总个数不超过k个,也将被视为异常点。

基于索引的方法(Index-Based)

使用一些传统的索引结构来减少基于距离的计算的复杂度。

基于密度的度量

基于密度的算法主要有局部离群因子(LocalOutlierFactor,LOF),以及LOCI、CLOF等基于LOF的改进算法。
主要是各个距离衡量方法的推进。
调用pyod.models.lof.LOF()进行训练及预测

from pyod.models.lof import LOF
# train kNN detector
clf_name = 'LOF'
clf = LOF()
clf.fit(X_train)

# get the prediction labels and outlier scores of the training data
y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
y_train_scores = clf.decision_scores_  # raw outlier scores

# get the prediction on the test data
y_test_pred = clf.predict(X_test)  # outlier labels (0 or 1)
y_test_scores = clf.decision_function(X_test)  # outlier scores

结果如下图可视化所示
在这里插入图片描述
在这里插入图片描述
(后续可更换数据集进行方法比较)

task 5:集成方法

由于数据集是多维度的,单个检测方法可能会失效,有时候需要集成方法来提高异常检测的能力。

feature bagging

常选用lof作为基检测器,bagging思想和常规bagging的思想一致,在数据集中随机抽样,然后分别进行训练和检测,最后标准化分数并组合识别结果。
常用的标准化分数及组合识别结果的方法包括:广度优先法和累积求和法两种。

基探测器的设计及其组合方法都取决于特定集成方法的特定目标。很多时候,我们无法得知数据的原始分布,只能通过部分数据去学习。除此以外,算法本身也可能存在一定问题使得其无法学习到数据完整的信息。这些问题造成的误差通常分为偏差和方差两种。
方差:是指算法输出结果与算法输出期望之间的误差,描述模型的离散程度,数据波动性。
偏差:是指预测值与真实值之间的差距。即使在离群点检测问题中没有可用的基本真值

写python代码实验如下,使用累计求和法
bagging函数

def bagging(X_train,T):
    d = X_train.shape[1]
    clf_lis = []
    d_lis = []
    y_train_pred_lis = []
    for i in range(T):
        clf = LOF()
        num = random.randint(d/2,d-1)
        sample_lis = random.sample(list(range(d)),num)
        X_train_sample = X_train[:,sample_lis]
        
        clf.fit(X_train_sample)
        
        y_train_sample_pred = clf.labels_
        
        y_train_pred_lis.append(y_train_sample_pred)
        clf_lis.append(clf)
        d_lis.append(sample_lis)
    y_train_pred = score(y_train_pred_lis,T)
    clf_model = {"clf":clf_lis,"T":T,"sample":d_lis}
    return y_train_pred,clf_model

累积求和函数

def score(y_train_pred_lis,T):
    mid = np.array(y_train_pred_lis).sum(axis = 0)
    y_train_pred_bag = mid > T/2 #超过一半视为outlier
    return y_train_pred_bag.astype(int)

测试集预测函数

def bagging_predict(X_test,clf_model):
    T = clf_model["T"]
    d_lis = clf_model["sample"]
    clf_lis = clf_model["clf"]
    y_test_pred_lis = []
    for i in range(T):
        clf = clf_lis[i]
        sample_lis = d_lis[i]
        X_test_sample = X_test[:,sample_lis]
        
        y_test_sample_pred = clf.predict(X_test_sample)
        
        y_test_pred_lis.append(y_test_sample_pred)
    y_test_pred = score(y_test_pred_lis,T)
    return y_test_pred

生成二十维实验数据

contamination = 0.08
n_train = 200 
n_test = 100 
n_features = 20

# Generate sample data
X_train, y_train, X_test, y_test = generate_data(n_train=n_train, n_test=n_test, n_features=n_features,
                                                 contamination=contamination, random_state=42)

训练、测试,并任选两维度绘图

y_train_pred,clf_model = bagging(X_train,20)
y_test_pred = bagging_predict(X_test,clf_model)
visualize(clf_name, X_train[:,3:5], y_train, X_test[:,3:5], y_test, y_train_pred,
          y_test_pred, show_figure=True, save_figure=False)

在这里插入图片描述

若采用单一模型预测,则效果如下
在这里插入图片描述
bagging 一定程度上改善了效果

Isolation Forests

孤立森林简单来说就是认为异常值是少的,所以会在靠近树根节点的地方被识别出来。
使用刚刚生成的数据,调用sklearn.ensemble.IsolationForest进行实验,代码及效果如下

clf = IsolationForest(random_state=0).fit(X_train)
y_train_pred = clf.fit_predict(X_train)
y_test_pred = clf.predict(X_test)

在这里插入图片描述

参考内容:

  1. datawhale组队学习开源项目:Anomaly Detection
  2. pyod官方文档
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SheltonXiao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值