异常检测的总结性介绍

1、异常检测

1.1 什么是异常值

        在机器学习中,异常检测和处理是一个比较小的分支,或者说,是机器学习的一个副产物,因为在一般的预测问题中,模型通常是对整体样本数据结构的一种表达方式,这种表达方式通常抓住的是整体样本一般性的性质,而那些在这些性质上表现完全与整体样本不一致的点,我们就称其为异常点,通常异常点在预测问题中是不受开发者欢迎的,因为预测问题通产关注的是整体样本的性质,而异常点的生成机制与整体样本完全不一致,如果算法对异常点敏感,那么生成的模型并不能对整体样本有一个较好的表达,从而预测也会不准确。

        从另一方面来说,异常点在某些场景下反而令分析者感到极大兴趣,如疾病预测,通常健康人的身体指标在某些维度上是相似,如果一个人的身体指标出现了异常,那么他的身体情况在某些方面肯定发生了改变,当然这种改变并不一定是由疾病引起(通常被称为噪音点),但异常的发生和检测是疾病预测一个重要起始点。相似的场景也可以应用到信用欺诈,网络攻击等等。

        样本中显著偏离其他数值的数据称为异常值(Outlier),其他预期的观测值标记为正常值或内点(Inlier)。

1.2 异常值的分类

        我们经常需要识别一些异常行为或者表现,比如 机器是否故障,产品是否合格,这类问题的特点就是 正常数据很多,异常数据很少,甚至根本没有;很多方法都可以检测一个新的检测样本,判断其是否与现有观测服从同一分布(即新观测为内围值,标记为1),相反则被认为不服从同一分布(即新观测为异常值,标记为-1)。通常,这些方法被用来对真实数据集进行清洗。这些检测方法可以分为两种:

  • 奇异点检测:训练数据中没有离群点,我们是对检测新发现的样本点感兴趣;
  • 异常点检测:训练数据中包含离群点,我们需要适配训练数据中的中心部分(密集的部分),忽视异常点;

2、 异常值的检测方法

        一般异常值的检测方法有基于统计的方法,基于聚类的方法,以及一些专门检测异常值的方法等,下面对这些方法进行相关的介绍

2.1 基于统计的方法

        单变量方法可以检测出相当多潜在异常值,但是,它不能检测那些不是极端值的异常值,即奇异点。

2.1.1 简单统计

        如果使用pandas,我们可以直接使用describe()来观察数据的统计性描述(只是粗略的观察一些统计量),不过统计数据为连续型的,如下:

df.describe()

        或者简单使用散点图也能很清晰的观察到异常值的存在。如下所示:

2.1.2 3∂原则

        这个原则有个条件:数据需要服从正态分布,它是以测量次数充分大为前提(样本>10)。在3∂原则下,异常值如超过3倍标准差,那么可以将其视为异常值。正负3∂的概率是99.7%,那么距离平均值3∂之外的值出现的概率为P(|x-u| > 3∂) <= 0.003,属于极个别的小概率事件。如果数据不服从正态分布,也可以用远离平均值的多少倍标准差来描述。

        3σ法则为:   

  • 数值分布在(μ-σ,μ+σ)中的概率为0.6827
  • 数值分布在(μ-2σ,μ+2σ)中的概率为0.9545
  • 数值分布在(μ-3σ,μ+3σ)中的概率为0.9973

        可以认为,数据样本的取值几乎全部集中在(μ-3σ,μ+3σ)区间内,超出这个范围的可能性仅占不到0.3%(很有可能是异常值或离群点)

红色箭头所指就是异常值。

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
np.random.seed(42) 
anomalies = [] 
normal = [] # 生成一些数据 
data = np.random.randn(50000) * 20 + 20 # 在一维数据集上检测离群点的函数 
def find_anomalies(random_data): 
    # 将上、下限设为3倍标准差 
    random_data_std = np.std(random_data) 
    random_data_mean = np.mean(random_data) 
    anomaly_cut_off = random_data_std * 3 
    lower_limit = random_data_mean - anomaly_cut_off 
    upper_limit = random_data_mean + anomaly_cut_off 
    print("下限: ",lower_limit) 
    print("上限: ",upper_limit) 
    # 异常 
    for outlier in random_data: 
        if outlier > upper_limit or outlier < lower_limit: 
            anomalies.append(outlier) 
        else: normal.append(outlier) 
    return pd.DataFrame(anomalies,columns=["异常值"]),pd.DataFrame(normal,columns=["正常值"]) 
anomalies,normal = find_anomalies(data)

2.1.3 箱型图

        这种方法是一维特征空间中最简单的非参数异常值检测方法,利用箱型图的四分位距(IQR)对异常值进行检测,也叫Tukey‘s test。箱型图的定义如下:

         四分位距(IQR)就是上四分位与下四分位的差值。而我们通过IQR的1.5倍为标准,规定:超过上四分位+1.5倍IQR距离,或者下四分位-1.5倍IQR距离的点为异常值。下面Python中的代码实现,主要使用了numpy的percentile方法。

Percentile = np.percentile(df['length'],[0,25,50,75,100]) 
IQR = Percentile[3] - Percentile[1] 
UpLimit = Percentile[3]+ageIQR*1.5 
DownLimit = Percentile[1]-ageIQR*1.5

        也可以使用seaborn的可视化方法boxplot来实现:

f,ax=plt.subplots(figsize=(10,8)) 
sns.boxplot(y='length',data=df,ax=ax) 
plt.show()

        红色箭头所指就是异常值。

        以上是常用到的判断异常值的简单方法。下面来介绍一些较为复杂的检测异常值算法,由于涉及内容较多,仅介绍核心思想,感兴趣的朋友可自行深入研究。

2.1.4 Z-score

        这是一维或低维特征空间中的参数异常检测方法。该技术假定数据是高斯分布,异常值是分布尾部的数据点,因此远离数据的平均值。距离的远近取决于使用公式计算的归一化数据点zi的设定阈值Zthr:

         然后经过标准化处理后,异常值也进行标准化处理,其绝对值大于Zthr: 

         Zthr值一般设置为2.5、3.0和3.5。

2.2、基于聚类的方法

2.2.1 DBSCAN

        该技术基于DBSCAN聚类方法,DBSCAN是一维或多维特征空间中的非参数,基于密度的离群值检测方法。基于聚类的离群点:一个对象是基于聚类的离群点,如果该对象不强属于任何簇,那么该对象属于离群点。虽然其它聚类算法比如 k 均值和层次聚类也可用于检测离群点。但是DBSCAN效果较好,所以往往用它。

        DBSCAN定义不同类型的点:

        核心点:A是一个核心的区域(ɛ所定义的)包含至少比参数MinPts同样多或更多的点。

        边界点:C是一个位于集群中的边界点,它的邻域并不包含比MinPts更多的点,但它仍然是集群中其他点的“密度可达”。

        离群点:N是一个离群点,在没有集群的情况下,它不是“密度可达”或“密度连接”到任何其他点。因此,这一点将有“他自己的集群”。

sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric='euclidean', metric_params=None, algorithm='auto', leaf_size=30, p=None, n_jobs=None)

        DBSCAN 优点:

        当特征空间中的值分布不是假设的时,这是一种非常有效的方法。

        如果搜索异常值的特征空间是多维的(比如:3或更多的维度),则可以很好地工作。

        DBSCAN 缺点:

        特征空间中的值需要相应地伸缩。

        选择最优参数eps,MinPts和度规可能很困难,因为它对任何三个参数都非常敏感。

        它是一个无监督的模型,需要在每次分析新的数据时重新校准。

2.3 基于分类的方法

2.3.1 KNN

        通常可以在对象之间定义邻近性度量,并且许多移仓检测方法都基于邻近度。异常对象是那些远离大部分其他对象的对象,这一邻域的许多技术都基于距离,称作基于距离的离群点检测技术,代表算法:基于KNN的密度检测算法。

        需要注意的是:离群点得分对k的取值高度敏感。如果k太小,则少量的邻近离群点可能导致较低的离群点得分;如果K太大,则点数少于k的簇中所有的对象可能都成了离群点。为了使该方案对于k的选取更具有鲁棒性,可以使用k个最近邻的平均距离。

        优点:简单;

        缺点:

  • 基于邻近度的方法需要O(m2)时间,大数据集不适用;
  • 该方法对参数的选择也是敏感的;
  • 不能处理具有不同密度区域的数据集,因为它使用全局阈值,不能考虑这种密度的变化。

2.4 专门的异常检测

        解决异常检测问题的思路就是,把训练样本中一小部分数据认为是异常数据,然后训练一个非常紧凑的决策边界,把大部分被认为是正常的样本框起来,并以此边界作为衡量标准,边界外就是异常;

        如下图所示,这种算法我们称为单分类算法;

         解决单分类问题的算法有很多,如孤立森林、自编码器、OneClassSVM等。

        奇异点检测即Novelty Detection要求所有训练数据都是正常的,不包含异常点,模型用于探测新加入的点是否异常;OneClassSVM(半监督)属于此类

        而异常点检测即Outlier Detection允许训练数据中有异常点,模型会尽可能适应训练数据而忽视异常点;EllipticEnvelope、IsolationForest、LocalOutlierFactor(无监督)属于此类

        sklearn.svm.OneClassSVM:对异常值敏感,因此对于异常值检测效果不佳。当训练集不受异常值污染时,此估计器最适合新数据检测;而且,在高维空间中检测异常值,或者不对基础数据的分布进行任何假设都是非常具有挑战性的,而One-class SVM在这些情况下可能会得到有用的结果,如果超参数设置合适的话。

        sklearn.covariance.EllipticEnvelope:假定数据为高斯分布并学习一个椭圆。因此,当数据不是高斯分布的单峰时,性能会降低。但是请注意,这个模型估计对异常值具有鲁棒性。

        sklearn.ensemble.IsolationForest和sklearn.neighbors.LocalOutlierFactor对于多模(multi-modal)数据集,效果似乎还不错。

2.4.1 OneClassSVM-单类支持向量机

        考虑一个来自同一分布的数据集,以m个特征描述、有n个观测。 现在考虑我们再往该数据集中添加一个观测。 如果新观测与原有观测有很大差异,我们就可以怀疑它是否是内围值吗? (即是否来自同一分布?)或者相反,如果新观测与原有观测很相似,我们就无法将其与原有观测区分开吗? 这就是新奇检测工具和方法所解决的问题。

        一般来说,它将要学习出一个粗略且紧密的边界,界定出初始观测分布的轮廓,绘制在相互嵌入的 维空间中。 那么,如果后续的观测在边界划分的子空间内,则它们被认为来自与初始观测相同的总体。 否则,如果它们在边界之外,我们可以说就我们评估中给定的置信度而言,它们是异常值。

OneClassSVM-单类支持向量机介绍

        One Class SVM 既可以是 novelty,也可以是 Outlier,当然,严格的讲,它应该属于 novelty,但实际上训练样本都会存在噪音,我们需要绕过噪音,得到一个干净的模型,这就是 Outlier;

        One Class SVM 是一种无监督算法,它的思想是先用一个核方法,比如高斯核(RBF kernel)将原始空间映射到特征空间,寻找一个超球面,使得正常样本 在球体内,异常样本在球体外,然后 最小化这个球的半径或者体积;

sklearn.svm.OneClassSVM(*, kernel='rbf',degree=3, gamma='scale',coef0=0.0,   tol=0.001, nu=0.5, shrinking=True,cache_size=200,verbose=False,  max_iter=- 1)

        参数(kernel,gamma,nu和tol比较重要):

        kernel: string, optional (default=’rbf’),核函数(一般用高斯核rbf)

        gamma:{‘scale’, ‘auto’} or float, optional (default=’scale’),内核系数

        tol:float, optional,停止标度的度量

        nu:float, optional:训练误差分数的上限,支持向量分数的下限。 应该在间隔(0,1]中。默认情况下,取0.5。

        方法:

        fit(X):训练,根据训练样本和上面两个参数探测边界。(注意是无监督)

        predict(X):返回预测值,+1就是正常样本,-1就是异常样本。

        fit_predict(X[,y]):在X上执行拟合并返回X的标签,对于异常值,返回-1 ,对于内点,返回1。

        实例:

#!/usr/bin/python
# -*- coding:utf-8 -*-
 
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager
from sklearn import svm
 
xx, yy = np.meshgrid(np.linspace(-5, 5, 500), np.linspace(-5, 5, 500))
# Generate train data
X = 0.3 * np.random.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
# Generate some regular novel observations
X = 0.3 * np.random.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
# Generate some abnormal novel observations
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
 
# fit the model
clf = svm.OneClassSVM(nu=0.1, kernel="rbf", gamma=0.1)
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
n_error_train = y_pred_train[y_pred_train == -1].size
n_error_test = y_pred_test[y_pred_test == -1].size
n_error_outliers = y_pred_outliers[y_pred_outliers == 1].size
 
# plot the line, the points, and the nearest vectors to the plane
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
 
plt.title("Novelty Detection")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), 0, 7), cmap=plt.cm.PuBu)  #绘制异常样本的区域
a = plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='darkred')  #绘制正常样本和异常样本的边界
plt.contourf(xx, yy, Z, levels=[0, Z.max()], colors='palevioletred')   #绘制正常样本的区域
s = 40
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white', s=s, edgecolors='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='blueviolet', s=s,
                 edgecolors='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='gold', s=s,
                edgecolors='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([a.collections[0], b1, b2, c],
           ["learned frontier", "training observations",
            "new regular observations", "new abnormal observations"],
           loc="upper left",
           prop=matplotlib.font_manager.FontProperties(size=11))
plt.xlabel(
    "error train: %d/200 ; errors novel regular: %d/40 ; "
    "errors novel abnormal: %d/40"
    % (n_error_train, n_error_test, n_error_outliers))

         适用场景:

  • 由于核函数计算比较耗时,在海量数据的场景用的并不多。
  • 在数据维度很高,或者对相关数据分布没有任何假设的情况下,OneClassSVM也可以作为一种很好的outlier detection方法。
  • 其实在分类问题中,当两类样本及其不平衡时,也可以将个数比例极小的那部分当做异常点来处理,从另外一种角度来完成分类任务。

2.4.2 EllipticEnvelope-椭圆模型拟合

        异常值检测Outlier Detection类似于奇异值检测,其目的是将内围观测的中心与一些被称为 “异常值” 的污染数据进行分离。 然而,在异常值检测的情况下,我们没有干净且适用于训练任何工具的数据集来代表内围观测的总体。

        EllipticEnvelope-椭圆模型拟合介绍

        实现异常值检测的一种常见方式是假设内围数据来自已知分布(例如,数据服从高斯分布)。 从这个假设来看,我们通常试图定义数据的 “形状”,并且可以将异常观测定义为足够远离拟合形状的观测。

        scikit-learn 提供了 covariance.EllipticEnvelope对象,它能拟合出数据的稳健协方差估计,从而为中心数据点拟合出一个椭圆,忽略中心模式之外的点。

        用于检测高斯分布数据集中异常值的对象。

sklearn.covariance.EllipticEnvelope(store_precision=True, 
        assume_centered=False, support_fraction=None, contamination=0.1, 
        random_state=None)

        重要参数:

        contamination:float, default=0.1。即数据集中异常值的比例,范围是(0,0.5)。

        方法:

        fit(X):训练,根据训练样本和上面两个参数探测边界。(注意是无监督)

        predict(X):返回预测值,+1就是正常样本,-1就是异常样本。

        实例:

import numpy as np
from sklearn.covariance import EllipticEnvelope
from sklearn.svm import OneClassSVM
import matplotlib.pyplot as plt
import matplotlib.font_manager
from sklearn.datasets import load_wine

# Define "classifiers" to be used
classifiers = {
    "Empirical Covariance": EllipticEnvelope(support_fraction=1.,
                                             contamination=0.25),
    "Robust Covariance (Minimum Covariance Determinant)":
    EllipticEnvelope(contamination=0.25),
    "OCSVM": OneClassSVM(nu=0.25, gamma=0.35)}
colors = ['m', 'g', 'b']
legend1 = {}
legend2 = {}

# Get data
X1 = load_wine()['data'][:, [1, 2]]  # two clusters

# Learn a frontier for outlier detection with several classifiers
xx1, yy1 = np.meshgrid(np.linspace(0, 6, 500), np.linspace(1, 4.5, 500))
for i, (clf_name, clf) in enumerate(classifiers.items()):
    plt.figure(1)
    clf.fit(X1)
    Z1 = clf.decision_function(np.c_[xx1.ravel(), yy1.ravel()])
    Z1 = Z1.reshape(xx1.shape)
    legend1[clf_name] = plt.contour(
        xx1, yy1, Z1, levels=[0], linewidths=2, colors=colors[i])

legend1_values_list = list(legend1.values())
legend1_keys_list = list(legend1.keys())

# Plot the results (= shape of the data points cloud)
plt.figure(1)  # two clusters
plt.title("Outlier detection on a real data set (wine recognition)")
plt.scatter(X1[:, 0], X1[:, 1], color='black')
bbox_args = dict(boxstyle="round", fc="0.8")
arrow_args = dict(arrowstyle="->")
plt.annotate("outlying points", xy=(4, 2),
             xycoords="data", textcoords="data",
             xytext=(3, 1.25), bbox=bbox_args, arrowprops=arrow_args)
plt.xlim((xx1.min(), xx1.max()))
plt.ylim((yy1.min(), yy1.max()))
plt.legend((legend1_values_list[0].collections[0],
            legend1_values_list[1].collections[0],
            legend1_values_list[2].collections[0]),
           (legend1_keys_list[0], legend1_keys_list[1], legend1_keys_list[2]),
           loc="upper center",
           prop=matplotlib.font_manager.FontProperties(size=11))
plt.ylabel("ash")
plt.xlabel("malic_acid")

plt.show()

 

        适用场景:

        EllipticEnvelope函数适用于有控制参数的高斯分布假设,使用时要注意:非标化的数据、二值或分类数据与连续数据混合使用可能引发错误和估计不准确。

        EllipticEnvelope函数假设全部数据可以表示成基本的多元高斯分布,当数据中有多个分布时,算法试图将数据适应一个总体分布,倾向于寻找最偏远聚类中的潜在异常值,而忽略了数据中其他可能受异常值影响的区域

2.4.3 IsolationForest-孤立森林

        孤立森林(Isolation Forest)是另外一种高效的异常检测算法,它和随机森林类似,但每次选择划分属性和划分点(值)时都是随机的,而不是根据信息增益或者基尼指数来选择。在建树过程中,如果一些样本很快就到达了叶子节点(即叶子到根的距离d很短),那么就被认为很有可能是异常点。因为那些路径d比较短的样本,都是因为距离主要的样本点分布中心比较远的。也就是说,可以通过计算样本在所有树中的平均路径长度来寻找异常点。

        本质是一种无监督算法,其主要用于异常点检测,在工业界有广泛应用;

        基本思想

        异常点总是稀疏的,而且异常点总是离密集点较远;

        在整个数据空间中,随机拿一个超平面进行切割,把数据集一分为二,然后继续随机切割子空间,迭代下去,直到每个子空间内只有一个样本;

        直观上讲,密集区域要被切割很多次才能分开到不同空间,而稀疏点很容易很早停在一个子空间;

sklearn.ensemble. IsolationForest ( n_estimators=100 ,  max_samples=’auto’,
      contamination=0.1 ,  max_features=1.0 ,  bootstrap=False ,  n_jobs=1,
      random_state=None ,  verbose=0 )

        主要参数:

        n_estimators : int, optional (default=100),森林中树的棵数

        max_samples : int or float, optional (default=”auto”),对每棵树,样本个数或比例

        contamination : float in (0., 0.5), optional (default=0.1),这是最关键的参数,用户设置样本中异常点的比例

        max_features : int or float, optional (default=1.0),对每棵树,特征个数或比例

        方法:

        fit(X):训练,无监督

        predict(X):返回值:+1 表示正常样本, -1表示异常样本。

        decision_function(X): 返回样本的异常评分。 值越小表示越有可能是异常样本。

        实例:

#!/usr/bin/python
# -*- coding:utf-8 -*-
 
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest
from scipy import stats
 
rng = np.random.RandomState(42)
 
# 构造训练样本
n_samples = 200  #样本总数
outliers_fraction = 0.25  #异常样本比例
n_inliers = int((1. - outliers_fraction) * n_samples)
n_outliers = int(outliers_fraction * n_samples)
 
X = 0.3 * rng.randn(n_inliers // 2, 2)
X_train = np.r_[X + 2, X - 2]   #正常样本
X_train = np.r_[X_train, np.random.uniform(low=-6, high=6, size=(n_outliers, 2))]  #正常样本加上异常样本
 
# fit the model
clf = IsolationForest(max_samples=n_samples, random_state=rng, contamination=outliers_fraction)
clf.fit(X_train)
# y_pred_train = clf.predict(X_train)
scores_pred = clf.decision_function(X_train)
threshold = stats.scoreatpercentile(scores_pred, 100 * outliers_fraction)  #根据训练样本中异常样本比例,得到阈值,用于绘图
 
# plot the line, the samples, and the nearest vectors to the plane
xx, yy = np.meshgrid(np.linspace(-7, 7, 50), np.linspace(-7, 7, 50))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
 
plt.title("IsolationForest")
# plt.contourf(xx, yy, Z, cmap=plt.cm.Blues_r)
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), threshold, 7), cmap=plt.cm.Blues_r)  #绘制异常点区域,值从最小的到阈值的那部分
a = plt.contour(xx, yy, Z, levels=[threshold], linewidths=2, colors='red')  #绘制异常点区域和正常点区域的边界
plt.contourf(xx, yy, Z, levels=[threshold, Z.max()], colors='palevioletred')  #绘制正常点区域,值从阈值到最大的那部分
 
b = plt.scatter(X_train[:-n_outliers, 0], X_train[:-n_outliers, 1], c='white',
                    s=20, edgecolor='k')
c = plt.scatter(X_train[-n_outliers:, 0], X_train[-n_outliers:, 1], c='black',
                    s=20, edgecolor='k')
plt.axis('tight')
plt.xlim((-7, 7))
plt.ylim((-7, 7))
plt.legend([a.collections[0], b, c],
           ['learned decision function', 'true inliers', 'true outliers'],
           loc="upper left")
plt.show()

         应用:

        常用于 网络安全中的攻击检测、金融交易欺诈检测、疾病侦测、噪声数据过滤等 

        适用场景:

        IForest目前是异常点检测最常用的算法之一,它的优点非常突出,具有线性时间复杂度。因为是随机森林的方法,所以可以用在含有海量数据的数据集上面。通常树的数量越多,算法越稳定。由于每棵树都是互相独立生成的,因此可以部署在大规模分布式系统上来加速运算。对于目前大数据分析的趋势来说,它的好用是有原因的。

        但是IForest也有一些缺点,比如不适用于特别高维的数据。由于每次切数据空间都是随机选取一个维度和该维度的随机一个特征,建完树后仍然有大量的维度没有被使用,导致算法可靠性降低。此时推荐降维后使用,或者考虑使用One Class SVM。

        另外iForest仅对即全局稀疏点敏感,不擅长处理局部的相对稀疏点,这样在某些局部的异常点较多的时候检测可能不是很准。

        而One Class SVM对于中小型的数据分析,尤其是训练样本不是特别海量的时候用起来经常会比iforest顺手,因此比较适合做原型分析。

2.4.5 LocalOutlierFactor-局部异常因子

        在中等高维数据集上执行异常值检测的另一种有效方法是使用局部异常因子(Local Outlier Factor ,LOF)算法。

        算法思想:

        LOF通过计算一个数值score来反映一个样本的异常程度。这个数值的大致意思是:一个样本点周围的样本点所处位置的平均密度比上该样本点所在位置的密度。比值越大于1,则该点所在位置的密度越小于其周围样本所在位置的密度,这个点就越有可能是异常点。

sklearn.neighbors. LocalOutlierFactor ( n_neighbors=20 , algorithm=’auto’ ,
      leaf_size=30 ,  metric=’minkowski’ ,  p=2 ,  metric_params=None ,  
      contamination=0.1 ,  n_jobs=1 )

        主要参数:

         n_neighbors : 设置k个紧邻数,default=20

         contamination : 设置样本中异常点的比例,default=0.1

        方法:

        fit(X):训练模型

        fit_predict(X) :返回一个数组,-1表示异常点,1表示正常点。

        实例:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor

np.random.seed(42)

# Generate train data
X_inliers = 0.3 * np.random.randn(100, 2)
X_inliers = np.r_[X_inliers + 2, X_inliers - 2]

# Generate some outliers
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
X = np.r_[X_inliers, X_outliers]

n_outliers = len(X_outliers)
ground_truth = np.ones(len(X), dtype=int)
ground_truth[-n_outliers:] = -1

# fit the model for outlier detection (default)
clf = LocalOutlierFactor(n_neighbors=20, contamination=0.1)
# use fit_predict to compute the predicted labels of the training samples
# (when LOF is used for outlier detection, the estimator has no predict,
# decision_function and score_samples methods).
y_pred = clf.fit_predict(X)
n_errors = (y_pred != ground_truth).sum()
X_scores = clf.negative_outlier_factor_

plt.title("Local Outlier Factor (LOF)")
plt.scatter(X[:, 0], X[:, 1], color="k", s=3.0, label="Data points")
# plot circles with radius proportional to the outlier scores
radius = (X_scores.max() - X_scores) / (X_scores.max() - X_scores.min())
plt.scatter(
    X[:, 0],
    X[:, 1],
    s=1000 * radius,
    edgecolors="r",
    facecolors="none",
    label="Outlier scores",
)
plt.axis("tight")
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.xlabel("prediction errors: %d" % (n_errors))
legend = plt.legend(loc="upper left")
legend.legendHandles[0]._sizes = [10]
legend.legendHandles[1]._sizes = [20]
plt.show()

         适用场景:

        LOF 算法的优点是考虑到数据集的局部和全局属性:即使在异常样本具有不同潜在密度的数据集中,它也能够表现得很好。 问题不在于样本是如何被分离的,而是样本与周围近邻的分离程度有多大。

2.4.6 算法比较

        1)对于聚合比较好的数据集,OneClassSVM不太适用

        2)对于双峰的数据集,EllipticEnvelope不太适用,其他三个都可以,其OneClassSVM易过拟合

        3)对于强烈非高斯分布的,EllipticEnvelope非常不使用,其他三个可以

2.5 基于时间序列的异常检测

2.5.1 自编码器

        自编码是一个BP神经网络,模型的输入层和输出层的神经元数量一致,中间层可以有多层,一般中间层的节点个数比输出层少,中间层相当于是对数据进行压缩和抽象,到恢复重建,实现无监督方式学习数据的抽象特征。

         训练自编码只需要正样本数据,没有负样本数据,或者说模型只关注正样本的规律,利用正样本从输入数据-提取特征-恢复数据的方式训练一个自编码器,编码器相当于单分类的模型,对全量数据进行预测时,然后比较输入层和输出层的相似度就可以判断是否属于异常样本,相似度阈值自行设置。

3、异常值的处理方法

        检测到了异常值,我们需要对其进行一定的处理。而一般异常值的处理方法可大致分为以下几种:

  • 删除含有异常值的记录:直接将含有异常值的记录删除;
  • 视为缺失值:将异常值视为缺失值,利用缺失值处理的方法进行处理;
  • 平均值修正:可用前后两个观测值的平均值修正该异常值;
  • 不处理:直接在具有异常值的数据集上进行数据挖掘;

        是否要删除异常值可根据实际情况考虑。因为一些模型对异常值不很敏感,即使有异常值也不影响模型效果,但是一些模型比如逻辑回归LR对异常值很敏感,如果不进行处理,可能会出现过拟合等非常差的效果。

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值