首页 > 编程知识 正文

异常点检测python(异常点检测给数据达标)

时间:2023-12-12 16:20:08 阅读:314874 作者:RVZL

本文目录一览:

Python如何检测恶意刷单行为

1、打开python。2、输入检测类的代码。将账号的订单数和ip地主数量两个变量进行异常值检测,分析出黄牛恶意下单的行为特征,多次重复下单,下单地址区间极短,甚至相同地址。

python异常和错误的区别

什么是错误?

错误分为两种情况:第一种语法错误,代码不符合解释器或者编译器语法;第二种逻辑错误,不完整或者不合法输入或者计算出现问题。

什么是异常?

所谓的异常就是执行过程中出现万体导致程序无法执行,同样分为两种情况:第一种程序遇到逻辑或者算法问题;第二种运行过程中计算机错误,内存不够或者IO错误。

Python中错误和异常有什么区别?

错误是代码运行前的语法或者逻辑错误,语法错误在执行前修改,逻辑错误无法修改;

而异常分为两个步骤,异常产生,检查到错误且解释器认为是异常,抛出异常;第二是异常处理,截获异常,忽略或者终止程序处理异常。

从软件方面来说,错误是语法或者逻辑上的问题,语法错误指示软件的结构上有错误,导致不能被解释器解释或者编译器无法编译,这些错误必须在程序执行前进行纠正;当程序语法正确后,剩下的就是逻辑错误问题,逻辑错误可能是由于不完整或不合法的输入导致,在其他情况下,可能是逻辑无法生成、计算或输出结果需要的过程无法执行。这些错误通常分别被称为域错误和范围错误。

当Python检测到一个错误时,解释器就会指出当前已经无法继续执行下去,这时就出现异常。

而异常它是因为程序出现了错误而在正常控制流以外采取的行为,这个行为分为两个阶段:首先是引起异常发生的错误,然后是检测阶段;

第一个阶段是在发生了一个异常条件后发生的,只要检测到错误并且意识到异常条件,解释器会引发一个异常,引发也可以叫作触发或生成,解释器通过它通知当前控制流有错误发生;

Python也允许程序员自己引发异常,无论是Python解释器还是程序员引发的,异常就是错误发生的信号,当前流将被打断,用来处理这个错误并采取相应的操作,这就是第二个阶段。

对异常的处理发生在第二阶段,异常引发后,可以调用很多不同的操作,可以是忽视错误,或是减轻问题的影响后设法继续执行程序,所以的这些操作都代表一种继续,或是控制的分支,关键是程序员在错误发生时可以指示程序如何执行。

类似Python这样支持引发和处理异常的语言,可以让开发人员在错误发生时更直接地控制它们,程序员不仅仅有了检测错误的能力,还可以在它们发生时采取更可靠的补救措施。

异常检测统计学方法

1. 概述

2. 参数方法

3. 非参数方法

4. HBOS

5. 总结

span id="1"/span

统计学方法对数据的正常性做出假定。 它们假定正常的数据对象由一个统计模型产生,而不遵守该模型的数据是异常点。 统计学方法的有效性高度依赖于对给定数据所做的统计模型假定是否成立。

具体方法:先基于统计学方法确定一个概率分布模型,然后判断各个离散点有多大概率符合该模型。

难点在于如何得到概率分布模型。首先是识别数据集的具体分布:数据的真实分布是否是现在手里的数据集完全体现的。尽管许多类型的数据都可以用常见的分布(高斯分布、泊松分布或者二项式分布)来描述,但是具有非标准分布的数据集非常常见。如果选择了错误的模型,则对象可能会被错误地识别为异常点。其次,如何确定使用属性的个数,基于统计学的方法,数据的属性一般具有一个或多个,那么在建立概率分布模型的过程中究竟是用一个属性还是多个属性需要分析和尝试。最后,当使用数据属性很多时,模型比较复杂并且难以理解,会涉及到EM算法。

异常检测的统计学方法,有两种具体的方法:参数方法和非参数方法。

span id="2"/span

假定正常的数据对象被一个以 为参数的参数分布产生。该参数分布的概率密度函数 给出对象 被该分布产生的概率。该值越小, 越可能是异常点。

span id="2.1"/span

仅涉及一个属性或变量的数据称为一元数据。我们假定数据分布符合正态分布,然后通过现有的数据得到正态分布的关键参数,把低概率的点识别为异常点。

假定输入的数据集为 ,数据集中的样本服从正态分布,即存在一个 和 ,使得 。这里的 和 可以通过计算求得。

计算公式如下:

求出上述的参数后,我们就可以根据概率密度函数计算每个数据点服从正态分布的概率,或者说离散数据点的概率。

概率计算公式为:

需要确定一个阈值,这个阈值一般是经验值,可以选择在验证集上使得评估指标值最大的阈值取值作为最终阈值。如果计算出来的概率低于阈值,就可以认为该数据点为异常点。

例如常用的3sigma原则,如果数据点超过范围 ,那么这些点可能是异常点。

这个方法还可以用于可视化。参考箱型图,以数据集的上下四分位数(Q1和Q3)、中点等参数,异常点常被定义为小于 和 。其中, 。

利用python画一个箱型图:

span id="2.2"/span

涉及两个或多个属性或变量的数据称为多元数据。分为两种情况,一种是特征相互独立,一种是特征间不相互独立。

span id="2.2"/span

当数据是多元数据的时候,核心思想是把多元异常点检测任务转换为一元异常点检测问题。例如基于正态分布的一元异常点检测扩充到多元情形时,可以求出每一维度的均值和标准差。对于第 维:

计算概率密度函数:

span id="2.2.2"/span

span id="2.3"/span

当实际数据很复杂时,可以考虑建立混合参数模型,假定数据集 包含来自两个概率分布: 是大多数(正常)对象的分布,而 是异常对象的分布。数据的总概率分布可以记作

其中, 是一个数据对象; 是0和1之间的数,给出离群点的期望比例。

span id="3"/span

相比参数方法,非参数方法对数据做较少的假定,不做先验概率分布,因而在更多情况下被使用。

直方图是一种频繁使用的非参数统计模型,可以用来检测异常点。该过程包括如下两步:

步骤1:构造直方图。使用输入数据(训练数据)构造一个直方图。该直方图可以是一元的,或者多元的(如果输入数据是多维的)。

尽管非参数方法并不假定任何先验统计模型,但是通常确实要求用户提供参数,以便由数据学习。例如,用户必须指定直方图的类型(等宽的或等深的)和其他参数(直方图中的箱数或每个箱的大小等)。与参数方法不同,这些参数并不指定数据分布的类型。

步骤2:检测异常点。为了确定一个对象是否是异常点,可以对照直方图检查它。在最简单的方法中,如果该对象落入直方图的一个箱中,则该对象被看作正常的,否则被认为是异常点。

对于更复杂的方法,可以使用直方图赋予每个对象一个异常点得分。例如令对象的异常点得分为该对象落入的箱的容积的倒数。

使用直方图作为异常点检测的非参数模型的一个缺点是, 很难选择一个合适的箱尺寸 。一方面,如果箱尺寸太小,则许多正常对象都会落入空的或稀疏的箱中,因而被误识别为异常点。另一方面,如果箱尺寸太大,则异常点对象可能渗入某些频繁的箱中,因而“假扮”成正常的。

span id="4"/span

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

HBOS算法流程:

推导过程如下:

span id="5"/span

对于异常值的检测

离群点,是一个数据对象,它显著不同于其他数据对象,与其他数据分布有较为显著的不同。有时也称非离群点为“正常数据”,离群点为“异常数据”。

离群点跟噪声数据不一样,噪声是被观测变量的随机误差或方差。一般而言,噪声在数据分析(包括离群点分析)中不是令人感兴趣的,需要在数据预处理中剔除的,减少对后续模型预估的影响,增加精度。

离群点检测是有意义的,因为怀疑产生它们的分布不同于产生其他数据的分布。因此,在离群点检测时,重要的是搞清楚是哪种外力产生的离群点。

常见的异常成因:

通常,在其余数据上做各种假设,并且证明检测到的离群点显著违反了这些假设。如统计学中的假设检验,基于小概率原理,对原假设进行判断。一般检测离群点,是人工进行筛选,剔除不可信的数据,例如对于房屋数据,面积上万,卧室数量过百等情况。而在面对大量的数据时,人工方法耗时耗力,因此,才有如下的方法进行离群点检测。

统计学方法是基于模型的方法,即为数据创建一个模型,并且根据对象拟合模型的情况来评估它们。大部分用于离群点检测的统计学方法都是构建一个概率分布模型,并考虑对象有多大可能符合该模型。

离群点的概率定义:离群点是一个对象,关于数据的概率分布模型,它具有低概率。这种情况的前提是必须知道数据集服从什么分布,如果估计错误就造成了重尾分布。

a. 参数法:

当数据服从正太分布的假设时在正态分布的假定下,u±3σ区域包含99.7%的数据,u±2σ包含95.4%的数据,u±1σ包含68.3%的数据。其区域外的数据视为离群点。

当数据是非正态分布时,可以使用切比雪夫不等式,它对任何分布形状的数据都适用。根据 切比雪夫不等式 ,至少有(1-1/k 2 )的数据落在±k个标准差之内。所以,有以下结论:

计算得到:通过绘制箱线图可以直观地找到离群点,或者通过计算四分位数极差(IQR)定义为Q3-Q1。比Q1小1.5倍的IQR或者比Q3大1.5倍的IQR的任何对象都视为离群点,因为Q1-1.5IQR和Q3+1.5IQR之间的区域包含了99.3%的对象。

涉及两个或多个属性或变量的数据称为多元数据。核心思想是把多元离群点检测任务转换成一元离群点检测问题。

- 卡方统计量的多元离群点检测 :正态分布的假定下,卡方统计量也可以用来捕获多元离群点,对象 ,卡方统计量是: , 是 在第i维上的值, 是所有对象在第i维上的均值,而n是维度。如果对象的卡方统计量很大,则该对象是离群点。

b. 非参数法:

构造直方图

为了构造一个好的直方图,用户必须指定直方图的类型和其他参数(箱数、等宽or等深)。最简单的方法是,如果该对象落入直方图的一个箱中,则该对象被看做正常的,否则被认为是离群点。也可以使用直方图赋予每个对象一个离群点得分,比如对象的离群点得分为该对象落入的箱的容积的倒数。但这个方法很难选择一个较好的直方图参数。

注意 :

传统的观点都认为孤立点是一个单独的点,然而很多的现实情况是异常事件具有一定的时间和空间的局部性,这种局部性会产生一个小的簇.这时候离群点(孤立点)实际上是一个小簇(图下图的C1和C3)。

一个对象是异常的,如果它远离大部分点。这种方法比统计学方法更一般、更容易使用,因为确定数据集的有意义的邻近性度量比确定它的统计分布更容易。不依赖统计检验,将基于邻近度的离群点看作是那些没有“足够多“邻居的对象。这里的邻居是用 邻近度(距离) 来定义的。最常用的距离是绝对距离(曼哈顿)和欧氏距离等等。

一个对象的离群点得分由到它的k-最近邻的距离给定。离群点得分对k的取值高度敏感。如果k太小,则少量的邻近离群点可能导致离群点较少;如果K太大,则点数少于k的簇中所有的对象可能都成了离群点,导致离群点过多。为了使该方案对于k的选取更具有鲁棒性,可以使用k个最近邻的平均距离。

从基于密度的观点来说,离群点是在低密度区域中的对象。一个对象的离群点得分是该对象周围密度的逆。基于密度的离群点检测与基于邻近度的离群点检测密切相关,因为密度通常用邻近度定义。

定义密度

一种常用的定义密度的方法是,定义密度为到k个最近邻的平均距离的倒数 。如果该距离小,则密度高,反之亦然。

另一种密度定义是使用DBSCAN聚类算法使用的密度定义,即一个对象周围的密度等于该对象指定距离d内对象的个数。 需要小心的选择d,如果d太小,则许多正常点可能具有低密度,从而离群点较多。如果d太大,则许多离群点可能具有与正常点类似的密度(和离群点得分)无法区分。 使用任何密度定义检测离群点具有与基于邻近度的离群点方案类似的特点和局限性。特殊地,当数据包含不同密度的区域时,它们不能正确的识别离群点。

定义相对密度

为了正确的识别这种数据集中的离群点,我们需要与对象邻域相关的密度概念,也就是定义相对密度。常见的有两种方法:

(1)使用基于SNN密度的聚类算法使用的方法;

(2)用点x的密度与它的最近邻y的平均密度之比作为相对密度。使用相对密度的离群点检测( 局部离群点要素LOF技术 ):

一种利用聚类检测离群点的方法是丢弃远离其他簇的小簇。这个方法可以和其他任何聚类技术一起使用,但是需要最小簇大小和小簇与其他簇之间距离的阈值。这种方案对簇个数的选择高度敏感。使用这个方案很难将离群点得分附加到对象上。

一种更系统的方法,首先聚类所有的点,对某个待测点评估它属于某一簇的程度。(基于原型的聚类可用离中心点的距离来评估,对具有目标函数(例如kmeans法时的簇的误差平方和)的聚类技术,该得分反映删除对象后目标函数的改进),如果删去此点能显著地改善此项目标函数,则可以将该点定位为孤立点。

基于聚类的离群点:一个对象是基于聚类的离群点,如果该对象不强属于任何簇。离群点对初始聚类的影响:如果通过聚类检测离群点,则由于离群点影响聚类,存在一个问题:结构是否有效。为了处理该问题,可以使用如下方法:

对象是否被认为是离群点可能依赖于簇的个数(如k很大时的噪声簇)。该问题也没有简单的答案。一种策略是对于不同的簇个数重复该分析。另一种方法是找出大量小簇,其想法是(1)较小的簇倾向于更加凝聚,(2)如果存在大量小簇时一个对象是离群点,则它多半是一个真正的离群点。不利的一面是一组离群点可能形成小簇而逃避检测。

根据已有训练集检测新样本是否异常

异常检测根据原始数据集的不同可分为两类:

novelty detection: 训练集中没有异常样本

outlier detection: 训练集中有异常样本

异常样本:

数量少,比较分散

novelty detection和outlier detection的区别:

Sklearn异常检测模型一览

5.1 奇异点检测(Novelty Detection)

奇异点检测,就是判断待测样本到底是不是在原来数据的概率分布内。概率学上认为,所有的数据都有它的隐藏的分布模式,这种分布模式可以由概率模型来具象化。

5.1 离群点检测(Outlier Detection)

不同与奇异点检测是,现在我们没有一个干净的训练集(训练集中也有噪声样本)。下面介绍的三种离群点检测算法其实也都可以用于奇异点检测。

如果我们认为,可达密度小的目标样本点就是异常点,这样未尝不可。但是,LOF算法更进一步。

LOF可以用来判断经纬度的异常。

使用python进行异常值(outlier)检测实战:KMeans + PCA + IsolationForest + SVM + EllipticEnvelope

文章引用: 数据挖掘:数据清洗——异常值处理

谁有孤立森林python代码

你好,下面是一个孤立森林的源代码, 他是根据周志华老师团队提出的孤立森林算法,用于进行异常点检测。

from random import sample, random, choice, randint

from math import ceil, log

#from utils import run_time

class Node(object):

    def __init__(self, size):

        """Node class to build tree leaves

        Keyword Arguments:

            size {int} -- Node size (default: {None})

        """

        # Node size

        self.size = size

        # Feature to split

        self.split_feature = None

        # Split point

        self.split_point = None

        # Left child node

        self.left = None

        # Right child node

        self.right = None

class IsolationTree(object):

    def __init__(self, X, n_samples, max_depth):

        """Isolation Tree class

        Arguments:

            X {list} -- 2d list with int or float

            n_samples {int} -- Subsample size

            max_depth {int} -- Maximum height of isolation tree

        """

        self.height = 0

        # In case of n_samples is greater than n

        n = len(X)

        if n_samples  n:

            n_samples = n

        # Root node

        self.root = Node(n_samples)

        # Build isolation tree

        self._build_tree(X, n_samples, max_depth)

    def _get_split(self, X, idx, split_feature):

        """Randomly choose a split point

        Arguments:

            X {list} -- 2d list object with int or float

            idx {list} -- 1d list object with int

            split_feature {int} -- Column index of X

        Returns:

            int -- split point

        """

        # The split point should be greater than min(X[feature])

        unique = set(map(lambda i: X[i][split_feature], idx))

        # Cannot split

        if len(unique) == 1:

            return None

        unique.remove(min(unique))

        x_min, x_max = min(unique), max(unique)

        # Caution: random() - x in the interval [0, 1).

        return random() * (x_max - x_min) + x_min

    def _build_tree(self, X, n_samples, max_depth):

        """The current node data space is divided into 2 sub space: less than the

        split point in the specified dimension on the left child of the current node,

        put greater than or equal to split point data on the current node's right child.

        Recursively construct new child nodes until the data cannot be splitted in the

        child nodes or the child nodes have reached the max_depth.

        Arguments:

            X {list} -- 2d list object with int or float

            n_samples {int} -- Subsample size

            max_depth {int} -- Maximum depth of IsolationTree

        """

        # Dataset shape

        m = len(X[0])

        n = len(X)

        # Randomly selected sample points into the root node of the tree

        idx = sample(range(n), n_samples)

        # Depth, Node and idx

        que = [[0, self.root, idx]]

        # BFS

        while que and que[0][0] = max_depth:

            depth, nd, idx = que.pop(0)

            # Stop split if X cannot be splitted

            nd.split_feature = choice(range(m))

            nd.split_point = self._get_split(X, idx, nd.split_feature)

            if nd.split_point is None:

                continue

            # Split

            idx_left = []

            idx_right = []

            while idx:

                i = idx.pop()

                xi = X[i][nd.split_feature]

                if xi  nd.split_point:

                    idx_left.append(i)

                else:

                    idx_right.append(i)

            # Generate left and right child

            nd.left = Node(len(idx_left))

            nd.right = Node(len(idx_right))

            # Put the left and child into the que and depth plus one

            que.append([depth+1, nd.left, idx_left])

            que.append([depth+1, nd.right, idx_right])

        # Update the height of IsolationTree

        self.height = depth

    def _predict(self, xi):

        """Auxiliary function of predict.

        Arguments:

            xi {list} -- 1D list with int or float

        Returns:

            int -- the depth of the node which the xi belongs to

        """

        # Search xi from the IsolationTree until xi is at an leafnode

        nd = self.root

        depth = 0

        while nd.left and nd.right:

            if xi[nd.split_feature]  nd.split_point:

                nd = nd.left

            else:

                nd = nd.right

            depth += 1

        return depth, nd.size

class IsolationForest(object):

    def __init__(self):

        """IsolationForest, randomly build some IsolationTree instance,

        and the average score of each IsolationTree

        Attributes:

        trees {list} -- 1d list with IsolationTree objects

        ajustment {float}

        """

        self.trees = None

        self.adjustment = None  # TBC

    def fit(self, X, n_samples=100, max_depth=10, n_trees=256):

        """Build IsolationForest with dataset X

        Arguments:

            X {list} -- 2d list with int or float

        Keyword Arguments:

            n_samples {int} -- According to paper, set number of samples to 256 (default: {256})

            max_depth {int} -- Tree height limit (default: {10})

            n_trees {int} --  According to paper, set number of trees to 100 (default: {100})

        """

        self.adjustment = self._get_adjustment(n_samples)

        self.trees = [IsolationTree(X, n_samples, max_depth)

                      for _ in range(n_trees)]

    def _get_adjustment(self, node_size):

        """Calculate adjustment according to the formula in the paper.

        Arguments:

            node_size {int} -- Number of leaf nodes

        Returns:

            float -- ajustment

        """

        if node_size  2:

            i = node_size - 1

            ret = 2 * (log(i) + 0.5772156649) - 2 * i / node_size

        elif node_size == 2:

            ret = 1

        else:

            ret = 0

        return ret

    def _predict(self, xi):

        """Auxiliary function of predict.

        Arguments:

            xi {list} -- 1d list object with int or float

        Returns:

            list -- 1d list object with float

        """

        # Calculate average score of xi at each tree

        score = 0

        n_trees = len(self.trees)

        for tree in self.trees:

            depth, node_size = tree._predict(xi)

            score += (depth + self._get_adjustment(node_size))

        score = score / n_trees

        # Scale

        return 2 ** -(score / self.adjustment)

    def predict(self, X):

        """Get the prediction of y.

        Arguments:

            X {list} -- 2d list object with int or float

        Returns:

            list -- 1d list object with float

        """

        return [self._predict(xi) for xi in X]

#@run_time

def main():

    print("Comparing average score of X and outlier's score...")

    # Generate a dataset randomly

    n = 100

    X = [[random() for _ in range(5)] for _ in range(n)]

    # Add outliers

    X.append([10]*5)

    # Train model

    clf = IsolationForest()

    clf.fit(X, n_samples=500)

    # Show result

    print("Average score is %.2f" % (sum(clf.predict(X)) / len(X)))

    print("Outlier's score is %.2f" % clf._predict(X[-1]))

if __name__ == "__main__":

    main()

异常检测(二)——传统统计学方法

统计学方法有效性高度依赖于给定数据所做的统计的模型假设是否成立。

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

例如:正态分布的3个 之外的点为异常点,箱线图中超过2个Q的点为异常点

根据如何指定和学习模型,异常检测的统计学方法可以划分为两个主要的类型:参数方法和非参数方法

参数方法 假定正常的数据对象被一个以 为参数的参数分布产生。该参数分布的概率密度函数 给出对象 被该分布产生的概率。该值越小, 越可能成为异常点。

非参数方法 并不假定先验统计模型,而是试图从输入数据确定模型。非参数方法通常假定参数的个数和性质都是灵活的,不预先确定(所以非参数方法并不是说模型是完全无参的,完全无参的情况下从数据学习模型是不可能的)。

仅涉及一个属性或变量的数据称为一元数据。我们假定数据由正态分布产生,然后可以由输入数据学习正态分布的参数,并把低概率的点识别为异常点。

假定输入数据集为 ,数据集中的样本服从正态分布,即 ,我们可以根据样本求出参数 和 。

求出参数之后,我们就可以根据概率密度函数计算数据点服从该分布的概率。正态分布的概率密度函数为

如果计算出来的概率低于阈值,就可以认为该数据点为异常点。

阈值是个经验值,可以选择在验证集上使得评估指标值最大(也就是效果最好)的阈值取值作为最终阈值。

例如常用的3sigma原则中,如果数据点超过范围 ,那么这些点很有可能是异常点。

这个方法还可以用于可视化。箱线图对数据分布做了一个简单的统计可视化,利用数据集的上下四分位数(Q1和Q3)、中点等形成。异常点常被定义为小于Q1-1.5IQR或大于Q3+1.5IQR的那些数据。

用Python画一个简单的箱线图:

涉及两个或多个属性或变量的数据称为多元数据。许多一元异常点检测方法都可以扩充,用来处理多元数据。其核心思想是把多元异常点检测任务转换成一元异常点检测问题。例如基于正态分布的一元异常点检测扩充到多元情形时,可以求出每一维度的均值和标准差。对于第 维:

计算概率时的概率密度函数为

这是在各个维度的特征之间相互独立的情况下。如果特征之间有相关性,就要用到多元高斯分布了。

在许多情况下假定数据是由正态分布产生的。当实际数据很复杂时,这种假定过于简单,可以假定数据是被混合参数分布产生的。

在异常检测的非参数方法中,“正常数据”的模型从输入数据学习,而不是假定一个先验。通常,非参数方法对数据做较少假定,因而在更多情况下都可以使用。

例子:使用直方图检测异常点。

直方图是一种频繁使用的非参数统计模型,可以用来检测异常点。该过程包括如下两步:

步骤1:构造直方图。使用输入数据(训练数据)构造一个直方图。该直方图可以是一元的,或者多元的(如果输入数据是多维的)。

尽管非参数方法并不假定任何先验统计模型,但是通常确实要求用户提供参数,以便由数据学习。例如,用户必须指定直方图的类型(等宽的或等深的)和其他参数(直方图中的箱数或每个箱的大小等)。与参数方法不同,这些参数并不指定数据分布的类型。

步骤2:检测异常点。为了确定一个对象是否是异常点,可以对照直方图检查它。在最简单的方法中,如果该对象落入直方图的一个箱中,则该对象被看作正常的,否则被认为是异常点。

对于更复杂的方法,可以使用直方图赋予每个对象一个异常点得分。例如令对象的异常点得分为该对象落入的箱的容积的倒数。

使用直方图作为异常点检测的非参数模型的一个缺点是,很难选择一个合适的箱尺寸。一方面,如果箱尺寸太小,则许多正常对象都会落入空的或稀疏的箱中,因而被误识别为异常点。另一方面,如果箱尺寸太大,则异常点对象可能渗入某些频繁的箱中,因而“假扮”成正常的。

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

HBOS算法流程:

1.为每个数据维度做出数据直方图。对分类数据统计每个值的频数并计算相对频率。对数值数据根据分布的不同采用以下两种方法:

静态宽度直方图:标准的直方图构建方法,在值范围内使用k个等宽箱。样本落入每个桶的频率(相对数量)作为密度(箱子高度)的估计。时间复杂度:

2.动态宽度直方图:首先对所有值进行排序,然后固定数量的 个连续值装进一个箱里,其 中N是总实例数,k是箱个数;直方图中的箱面积表示实例数。因为箱的宽度是由箱中第一个值和最后一个值决定的,所有箱的面积都一样,因此每一个箱的高度都是可计算的。这意味着跨度大的箱的高度低,即密度小,只有一种情况例外,超过k个数相等,此时允许在同一个箱里超过 值。

时间复杂度:

2.对每个维度都计算了一个独立的直方图,其中每个箱子的高度表示密度的估计。然后为了使得最大高度为1(确保了每个特征与异常值得分的权重相等),对直方图进行归一化处理。最后,每一个实例的HBOS值由以下公式计算:

推导过程:

假设样本p第 i 个特征的概率密度为 ,则p的概率密度可以计算为: 两边取对数: 概率密度越大,异常评分越小,为了方便评分,两边乘以“-1”: 最后可得:

1.异常检测的统计学方法由数据学习模型,以区别正常的数据对象和异常点。使用统计学方法的一个优点是,异常检测可以是统计上无可非议的。当然,仅当对数据所做的统计假定满足实际约束时才为真。

2.HBOS在全局异常检测问题上表现良好,但不能检测局部异常值。但是HBOS比标准算法快得多,尤其是在大数据集上。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。