精华内容
下载资源
问答
  • 异常数据处理

    千次阅读 2019-07-06 09:49:44
    常用处理方法: 异常值的处理方法常用有四种: 1.删除含有异常值的记录 2.将异常值视为缺失值,...# 异常数据处理(异常数据过滤) new_df = df.replace('?', np.nan)#替换非法字符为np.nan datas = new_df.dropna(...

    常用处理方法:

    异常值的处理方法常用有四种

    1.删除含有异常值的记录

    2.将异常值视为缺失值,交给缺失值处理方法来处理

    3.用平均值来修正

    4.不处理

    需要强调的是,如何判定和处理异常值,需要结合实际

     

    # 异常数据处理(异常数据过滤)
    new_df = df.replace('?', np.nan)#替换非法字符为np.nan
    datas = new_df.dropna(axis=0,how = 'any') # 只要有一个数据为空,就进行行删除操作
    datas.describe().T#观察数据的多种统计指标

    关于replace函数

    语法:replace(self, to_replace=None, value=None, inplace=False, limit=None, regex=False, method='pad', axis=None)

    使用方法如下:

    1

    2

    3

    4

    import numpy as np

    import pandas as pd

    df = pd.read_csv('emp.csv')

    df

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    #Series对象值替换

    s = df.iloc[2]#获取行索引为2数据

    #单值替换

    s.replace('?',np.nan)#用np.nan替换?

    s.replace({'?':'NA'})#用NA替换?

    #多值替换

    s.replace(['?',r'$'],[np.nan,'NA'])#列表值替换

    s.replace({'?':np.nan,'$':'NA'})#字典映射

    #同缺失值填充方法类似

    s.replace(['?','$'],method='pad')#向前填充

    s.replace(['?','$'],method='ffill')#向前填充

    s.replace(['?','$'],method='bfill')#向后填充

    #limit参数控制填充次数

    s.replace(['?','$'],method='bfill',limit=1)

    #DataFrame对象值替换

    #单值替换

    df.replace('?',np.nan)#用np.nan替换?

    df.replace({'?':'NA'})#用NA替换?

    #按列指定单值替换

    df.replace({'EMPNO':'?'},np.nan)#用np.nan替换EMPNO列中?

    df.replace({'EMPNO':'?','ENAME':'.'},np.nan)#用np.nan替换EMPNO列中?和ENAME中.

    #多值替换

    df.replace(['?','.','$'],[np.nan,'NA','None'])##用np.nan替换?用NA替换. 用None替换$

    df.replace({'?':'NA','$':None})#用NA替换? 用None替换$

    df.replace({'?','$'},{'NA',None})#用NA替换? 用None替换$

    #正则替换

    df.replace(r'\?|\.|\$',np.nan,regex=True)#用np.nan替换?或.或$原字符

    df.replace([r'\?',r'\$'],np.nan,regex=True)#用np.nan替换?和$

    df.replace([r'\?',r'\$'],[np.nan,'NA'],regex=True)#用np.nan替换?用NA替换$符号

    df.replace(regex={r'\?':None})

    #value参数显示传递

    df.replace(regex=[r'\?|\.|\$'],value=np.nan)#用np.nan替换?或.或$原字符

    删除缺失数据
    df.dropna(axis=0, how='any')
    #any表示删除包含任何NaN值的给定轴,how=all会删除所有元素都是NaN的给定轴

    展开全文
  • ![图片说明](https://img-ask.csdn.net/upload/201902/11/1549870745_801303.jpg) 数据源是csv格式的表格,图像是用weka生成的,怎样用python或者java去掉图中圈住的异常数据,然后将异常数据还原?
  • 风电机组异常数据识别与清洗-baseline

    千次阅读 多人点赞 2020-09-23 11:34:00
    风电机组异常数据识别与清洗-baseline 比赛类型:数据挖掘 比赛数据:表格题(csv) 学习方式:无监督 主办方:国家电力投资集团有限公司科技与创新部 比赛链接 比赛任务:依据提供的8台风力电机1年的10min间隔...

    风电机组异常数据识别与清洗-baseline

    比赛类型:数据挖掘
    比赛数据:表格题(csv)
    学习方式:无监督
    主办方:国家电力投资集团有限公司科技与创新部
    

    比赛链接
    比赛任务:依据提供的8台风力电机1年的10min间隔SCADA运行数据,包括时间戳信息、风速信息和功率信息等,利用机器学习相关技术,建立鲁棒的风电机组异常数据检测模型,用于识别并剔除潜在的异常数据,提高数据质量。

      此任务未给出异常数据标签,视为聚类任务,为引导选手向赛题需求对接,现简单阐述异常数据定义。异常数据是由风机运行过程与设计运行工况出现较大偏离时产生,如风速仪测风异常导致采集的功率散点明显偏离设计风功率。

    任务概述:根据给出数据 ,12台风力电机 的 【‘风机编号’,‘时间戳’,‘风速’,‘功率’,‘风轮转速’】表格数据进行异常数据的检测,通过无监督的方式(学习方式不限)判断为异常数据进行打标签1,否则为0。
    比赛难点:首先,学习方式是无监督的方法,不是简单的二分类表格题,使得一些如xgb树、CNN网络等之类的成熟模型将无法使用,除非通过半监督的方式进行人为打标,但这样风险过大,易过拟合。
    其次,可用的方式多种多样,可以通过一定的风电机组发动机实际物理模型进行数学意义上的异常分析,或通过图像法来人为选定异常值,当然,我们也可以按照比赛要求使用经典的无监督模型进行聚类分析。
    最后,数据的特征太少了,每一个电机只有【‘时间戳’,‘风速’,‘功率’,‘风轮转速’】四种特征,对于表格题来说,仅仅四种特征无论什么模型效果都会很一般,故特征工程是一定要做的。

    :本baseline仅供共同学习使用



    前言

    在本篇您将学到:
      ● 数据分析的基本流程
      ● 四种经典无监督模型的异常检测
      ● 本比赛的基本流程

    I 数据分析

    1.1 数据读取

    一共有两个数据集,dataset.csv 以行的方式存放了12台风机的数据,submission.csv 以行的方式存放了风机编号、时间戳和标签label,一共有三列,其中标签label就是我们要建模“预测”提交的。

    注意,本数据集不再划分训练集、验证集和测试集,因为训练集和测试集的主键相同(即ID均相同),且学习方式是无监督。如果你考虑使用半监督学习的方式,可以进行数据集的划分,但这样是有一定风险的,因为你要自己打标,这个标签不一定准,且有可能过拟合A榜而导致最终B榜分数有问题,以及实际应用中这种方式将不再实用。

    data = pd.read_csv('../data/dataset.csv')
    submit = pd.read_csv('../data/submission.csv')
    
    data.columns = ['风机编号','时间戳','风速','功率','风轮转速']
    # data['label'] = 0 # 1为异常数据
    print('Data shape:{}'.format(data.shape))
    print('Submit shape:{}'.format(submit.shape))
    print('训练集与测试集主键是否相同:',(data['时间戳'] == submit['Time']).all())
    data.head()
    

    在这里插入图片描述

    1.2 数据可视化

    sns.set()
    print(data['风速'].loc[data['风机编号']==1].describe())
    data['风速'].loc[data['风机编号']==1].hist()
    

    在这里插入图片描述
    风机1号的全年风速图

    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    data.loc[data['风机编号']==1].plot(x='时间戳',y='风速',figsize=(12,6))
    

    在这里插入图片描述
    风机12号的全年风速图

    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    data.loc[data['风机编号']==12].plot(x='时间戳',y='风速',figsize=(12,6))
    

    在这里插入图片描述
    12台风机的全年风速图

    a1 = data.loc[data['风机编号']==1,'风速']
    a2 = data.loc[data['风机编号']==2,'风速']
    a3 = data.loc[data['风机编号']==3,'风速']
    a4 = data.loc[data['风机编号']==4,'风速']
    a5 = data.loc[data['风机编号']==5,'风速']
    a6 = data.loc[data['风机编号']==6,'风速']
    a7 = data.loc[data['风机编号']==7,'风速']
    a8 = data.loc[data['风机编号']==8,'风速']
    a9 = data.loc[data['风机编号']==9,'风速']
    a10 = data.loc[data['风机编号']==10,'风速']
    a11 = data.loc[data['风机编号']==11,'风速']
    a12 = data.loc[data['风机编号']==12,'风速']
    plt.figure(figsize=(15,10))
    plt.hist(a1,bins=50 , alpha=0.5,label='风机编号1')
    plt.hist(a2,bins=50 , alpha=0.5,label='风机编号2')
    plt.hist(a3,bins=50 , alpha=0.5,label='风机编号3')
    plt.hist(a4,bins=50 , alpha=0.5,label='风机编号4')
    plt.hist(a5,bins=50 , alpha=0.5,label='风机编号5')
    plt.hist(a6,bins=50 , alpha=0.5,label='风机编号6')
    plt.hist(a7,bins=50 , alpha=0.5,label='风机编号7')
    plt.hist(a8,bins=50 , alpha=0.5,label='风机编号8')
    plt.hist(a9,bins=50 , alpha=0.5,label='风机编号9')
    plt.hist(a10,bins=50 , alpha=0.5,label='风机编号10')
    plt.hist(a11,bins=50 , alpha=0.5,label='风机编号11')
    plt.hist(a12,bins=50 , alpha=0.5,label='风机编号12')
    plt.legend(loc='upper right')
    plt.xlabel('风速')
    plt.ylabel('统计')
    plt.show()
    

    在这里插入图片描述
    从上面的直方图中可以看出各个风机的全年风速的趋势类似,都是有一定正态分布的规律的,在此分析上,可以对风速进行np.log1p的数字特征处理来减低偏度等。

    1.3 特征工程

    根据比赛官方给出的不同风机各自的风轮直径、额定功率、切入风速、切出风速、风轮转速范围进行添加。

    # 官方给的每个风机的风轮直径、额定功率、切入风速、切出风速、风轮转速范围
    def wheel_diameter(id_):
        id_ = int(id_)
        if id_==5:return 100.5
        elif id_==11:return 115
        elif id_==12:return 104.8
        else:return 99 
    def rated_p(id_):
        return 2000
    def cutin_wind(id_):
        id_ = int(id_)
        if id_ == 11:return 2.5
        else:        return 3 
    def cutout_wind(id_):
        id_ = int(id_)
        if id_==5 or id_==12:return 22
        elif id_==11:        return 19
        else:                return 25
    def wheel_speed(id_):
        id_ = int(id_)
        if id_ == 5:return [5.5,19]
        elif id_ == 11:return [5,14]
        elif id_ == 12:return [5.5,17]
        return [8.33,16.8]
        
        
    data['风轮直径'] = data['风机编号'].apply(wheel_diameter)
    data['额定功率'] = data['风机编号'].apply(rated_p)
    data['切入风速'] = data['风机编号'].apply(cutin_wind)
    data['切出风速'] = data['风机编号'].apply(cutout_wind)
    data['风轮转速范围'] = data['风机编号'].apply(wheel_speed)
    data.head()
    

    在这里插入图片描述

    在此,为保证比赛竞争性,本baseline再仅提供一个二值特征,比赛群里讨论发现,风轮转速<7约有89%的异常数据,故该二值特征很有意义(能上分)。

    def speed(v):
        return 0 if v>7 else 1
    data['风轮转速_01'] = data['风轮转速'].apply(speed)
    

    提示:你可以通过时间戳做时序特征、根据功率和风轮转速做物理特征、根据切入风速、切出风速等做风速判断等等,以及对数字特征做统计特征等。

    II 建立模型

    2.1 基于聚类的异常检测

    k-means是一种广泛使用的聚类算法。 它创建了k个具有相似特性的数据组。 不属于这些组的数据实例可能会被标记为异常。 在我们开始k-means聚类之前,我们使用elbow方法来确定最佳聚类数量。

    data_num = data[['风速','功率','风轮转速']]
    n_cluster = range(1, 20)
    kmeans = [KMeans(n_clusters=i).fit(data_num) for i in n_cluster]
    scores = [kmeans[i].score(data_num) for i in range(len(kmeans))]
    
    fig, ax = plt.subplots(figsize=(10,6))
    ax.plot(n_cluster, scores)
    plt.xlabel('N_cluster')
    plt.ylabel('Score')
    plt.title('Elbow Curve')
    plt.show()
    

    在这里插入图片描述
    为了找出合理的距离中心数,我们尝试尽可能多的聚类中心数(从1个到20个聚类中心),然后我们画出Elbow曲线,通过观察Elbow曲线,我们发现当我们的聚类中心数量增加到10个以上时Elbow曲线趋于收敛,因此我们大致可以将聚类中心数定为10.

    :在此,请时刻记得我们的任务是什么,是对12台风机的全年数据进行异常数据的检测,聚类成10类仅仅是从整体数据的角度进行考虑的。可以考虑的是分成12组进行分组聚类,聚类的类别为2组,即一组正常、一组异常。

    下面我们将K-means算法的n_clusters设置为10,然后我们将数据进行3D可视化。

    X = data_num
    X = X.reset_index(drop=True)
    km = KMeans(n_clusters=10)
    km.fit(X)
    km.predict(X)
    labels = km.labels_
     
    fig = plt.figure(1, figsize=(15,15))
    ax = Axes3D(fig, rect=[0, 0, 0.95, 1], elev=48, azim=134)
    ax.scatter(X.iloc[:,0], X.iloc[:,1], X.iloc[:,2],
              c=labels.astype(np.float), edgecolor="k")
    # '风速','功率','风轮转速'
    ax.set_xlabel("风速")
    ax.set_ylabel("功率")
    ax.set_zlabel("风轮转速")
    plt.title("K Means", fontsize=14)
    

    在这里插入图片描述
    让我们再单独看看给1号风机进行类别为2种的聚类

    X = data[['风速','功率','风轮转速']].loc[data['风机编号']==1]
    X = X.reset_index(drop=True)
    km = KMeans(n_clusters=2)
    km.fit(X)
    km.predict(X)
    labels = km.labels_
     
    fig = plt.figure(1, figsize=(10,10))
    ax = Axes3D(fig, rect=[0, 0, 0.95, 1], elev=48, azim=134)
    ax.scatter(X.iloc[:,0], X.iloc[:,1], X.iloc[:,2],
              c=labels.astype(np.float), edgecolor="k")
    # '风速','功率','风轮转速'
    ax.set_xlabel("风速")
    ax.set_ylabel("功率")
    ax.set_zlabel("风轮转速")
    plt.title("风机编号1 K Means", fontsize=14)
    

    在这里插入图片描述

    接下来让我们来确定需要保留数据中的哪些主要成分(特征)

    X = data_num.values
    
    # 标准化 均值为0 标准差为1
    X_std    = StandardScaler().fit_transform(X)
    mean_vec = np.mean(X_std,axis=0)
    # 协方差,协方差矩阵反应了特征变量之间的相关性
    # 如果两个特征变量之间的协方差为正则说明它们之间是正相关关系
    # 如果为负则说明它们之间是负相关关系
    cov_mat = np.cov(X_std.T)
    
    # 特征值和特征向量
    eig_vals,eig_vecs = np.linalg.eig(cov_mat)
    # 特征值对应的特征向量
    eig_pairs = [ (np.abs(eig_vals[i]),eig_vecs[:,i]) for i in range(len(eig_vals))]
    eig_pairs.sort(key = lambda x: x[0], reverse= True)
    # 特征之求和
    eig_sum = sum(eig_vals)
    
    
    # 解释方差
    var_exp = [(i/eig_sum)*100 for i in sorted(eig_vals, reverse=True)]
    # 累计的解释方差
    cum_var_exp = np.cumsum(var_exp)
    
    plt.figure(figsize=(10,5))
    plt.bar(range(len(var_exp)), var_exp, alpha=0.3, align='center', label='独立的解释方差', color = 'g')
    plt.step(range(len(cum_var_exp)), cum_var_exp, where='mid',label='累积解释方差')
    plt.ylabel('解释方差率')
    plt.xlabel('主成分')
    plt.legend(loc='best')
    plt.show()
    

    在这里插入图片描述
    我们首先对数据进行标准化处理(StandardScaler),
      然后再计算特征变量之间的协方差矩阵,协方差矩阵反应了特征变量之间的相关性,如果两个特征变量之间的协方差为正则说明它们之间是正相关关系,如果为负则说明它们之间是负相关关系,如果为0则说明特征变量之间是相互独立的关系,不存在相关关系(有时候我们也会用相关系数矩阵来代替协方差矩阵)。
      最后在协方差矩阵的基础上又计算了协方差矩阵的特征值和特征向量,根据特征值计算出每个主成分(特征)的解释方差,以及累计解释方差,
      我们这样做的目的是为了下一步做主成分分析(PCA)挑选出特征变量中的主成分。
    我们挑选第一个主成分,因为它的累计解释方差为80%。

    从上图可知我们的三个主成分,第一个主成分(特征)解释了将近80%的方差变化,第二个主成分解释了近15%的方差变化,那么第一个主成分解释了近80%的方差。因此接下来我们将使用PCA算法进行降维并将设置参数n_components=1。

    # 标准化处理,均值为0,标准差为1
    X_std = StandardScaler().fit_transform(data_num.values)
    data_std = pd.DataFrame(X_std)
     
    #将特征维度降到1
    pca = PCA(n_components=1)
    data_std = pca.fit_transform(data_std)
    # 降维后将1个新特征进行标准化处理
    scaler = StandardScaler()
    np_scaled = scaler.fit_transform(data_std)
    data_std = pd.DataFrame(np_scaled)
     
    kmeans = [KMeans(n_clusters=i).fit(data_std) for i in n_cluster]
    data['cluster'] = kmeans[9].predict(data_std) # 刚才Elbow曲线10类基本收敛了,故还是选择10类
    data.index = data_std.index
    data['principal_feature1'] = data_std[0]
    data.head()
    

    在这里插入图片描述
    基于聚类的异常检测中的假设是,如果我们对数据进行聚类,则正常数据将属于聚类,而异常将不属于任何聚类或属于小聚类。 我们使用以下步骤来查找和可视化异常值。

    计算每个数据点与其最近的聚类中心之间的距离。 最大的距离被认为是异常的。设定一个异常值的比例outliers_fraction为40%,这样设置是因为在标准正太分布的情况下(N(0,1))我们一般认定3个标准差以外的数据为异常值,3个标准差以内的数据包含了数据集中99%以上的数据,所以剩下的1%的数据可以视为异常值。

    根据异常值比例outliers_fraction,计算异常值的数量number_of_outliers。设定一个判定异常值的阈值threshold,通过阈值threshold来判定数据是否为异常值。以及对数据进行可视化(包含正常数据和异常数据)

    # 计算每个数据点到其聚类中心的距离
    def getDistanceByPoint(data, model):
        distance = pd.Series()
        for i in range(0,len(data)):
            Xa = np.array(data.loc[i])
            Xb = model.cluster_centers_[model.labels_[i]]
            distance.set_value(i, np.linalg.norm(Xa-Xb))
        return distance
     
    #设置异常值比例
    outliers_fraction = 0.4
     
    # 得到每个点到取聚类中心的距离,我们设置了10个聚类中心,kmeans[9]表示有10个聚类中心的模型
    distance = getDistanceByPoint(data_std, kmeans[9])
     
    #根据异常值比例outliers_fraction计算异常值的数量
    number_of_outliers = int(outliers_fraction*len(distance))
     
    #设定异常值的阈值
    threshold = distance.nlargest(number_of_outliers).min()
     
    #根据阈值来判断是否为异常值
    data['anomaly1'] = (distance >= threshold).astype(int)
    
    #数据可视化
    fig, ax = plt.subplots(figsize=(10,6))
    colors = {0:'blue', 1:'red'}
    ax.scatter(data['principal_feature1'],data['风速'],c=data["anomaly1"].apply(lambda x: colors[x]))
    plt.xlabel('principal feature1')
    plt.ylabel('风速')
    plt.show()
    

    在这里插入图片描述
    上图中红色的点即是被认定的异常值,它们大约占总数据量的40%。
    下述代码也证实了这一点。
    在这里插入图片描述

    fig, ax = plt.subplots(figsize=(12,6))
     
    a = data.loc[data['anomaly1'] == 1, ['时间戳', '风轮转速']] #anomaly
     
    ax.plot(data['时间戳'], data['风轮转速'], color='blue', label='正常值')
    ax.scatter(a['时间戳'],a['风轮转速'], color='red', label='异常值')
    plt.xlabel('时间戳')
    plt.ylabel('风轮转速')
    plt.legend()
    plt.show()
    

    在这里插入图片描述
    从上图可知,经过PCA和KMeans计算出的异常值,它们的风轮转速大多位于区间的最高点和最低点处,这应该是合理的。

    2.2 孤立森林(IsolationForest)异常检测

    IsolationForest算法它是一种集成算法(类似于随机森林)主要用于挖掘异常(Anomaly)数据,或者说离群点挖掘,总之是在一大堆数据中,找出与其它数据的规律不太符合的数据。该算法不采样任何基于聚类或距离的方法,因此他和那些基于距离的的异常值检测算法有着根本上的不同,孤立森林认定异常值的原则是异常值是少数的和不同的数据。它通常用于网络安全中的攻击检测和流量异常等分析,金融机构则用于挖掘出欺诈行为。

      ●当我们使用IsolationForest算法时需要设置一个异常值比例的参数contamination, 该参数的作用类似于之前的outliers_fraction。
      ●使用 fit 方法对孤立森林模型进行训练
      ●使用 predict 方法去发现数据中的异常值。返回1表示正常值,-1表示异常值。

    # 训练孤立森林模型
    model =  IsolationForest(contamination=outliers_fraction)
    model.fit(data_std)
     
    #返回1表示正常值,-1表示异常值
    data['anomaly2'] = pd.Series(model.predict(data_std)) 
     
    fig, ax = plt.subplots(figsize=(10,6))
    a = data.loc[data['anomaly2'] == -1, ['时间戳', '风轮转速']] #异常值
    ax.plot(data['时间戳'], data['风轮转速'], color='blue', label = '正常值')
    ax.scatter(a['时间戳'],a['风轮转速'], color='red', label = '异常值')
    plt.legend()
    plt.show()
    

    在这里插入图片描述
    从上图可知,使用孤立森林预测的异常值,它们的风轮转速大多位于区间的最高点或最低点处。

    2.3 支持向量机(SVM)的异常检测

    SVM通常应用于监督式学习,但OneClassSVM算法可用于将异常检测这样的无监督式学习,它学习一个用于异常检测的决策函数其主要功能将新数据分类为与训练集相似的正常值或不相似的异常值。

    SVM使用大边距的方法,它用于异常检测的主要思想是:将数据密度较高的区域分类为正,将数据密度较低的区域分类为负

      ●在训练OneClassSVM模型时,我们需要设置参数nu = outliers_fraction,它是训练误差分数的上限和支持向量分数的下限,并且必须在0和1之间。基本上它代表了我们期望的异常值在我们的数据集中的比例。
      ●指定要在算法中使用的核类型:rbf。 它使SVM能够使用非线性函数将超空间投影到更高维度。
      ●gamma是RBF内核类型的参数,并控制各个训练样本的影响 - 这会影响模型的“平滑度”。
      ●predict 对数据进行分类,因为我们的模型是单类模型,所以返回+1或-1,-1表示是异常值,1表示是正常值。

    # 训练 oneclassSVM 模型
    model = OneClassSVM(nu=outliers_fraction, kernel="rbf", gamma=0.01)
    model.fit(data_std)
     
    data['anomaly3'] = pd.Series(model.predict(data_std))
    fig, ax = plt.subplots(figsize=(10,6))
     
    a = data.loc[data['anomaly3'] == -1, ['时间戳', '风轮转速']] #异常值
    
    ax.plot(data['时间戳'], data['风轮转速'], color='blue', label = '正常值')
    ax.scatter(a['时间戳'],a['风轮转速'], color='red', label = '异常值')
    plt.legend()
    plt.show()
    

    在这里插入图片描述
    从上图可知,使用OneClassSVM预测的异常值,它们的风轮转速大多位于区间的最高点或最低点处。

    2.4 基于高斯概分布的异常检测

    高斯分布也称为正态分布。 它可以被用来进行异常值检测,不过我们首先要假设我们的数据是正态分布的。 不过这个假设不能适应于所有数据集。但如果我们做了这种假设那么它将会有一种有效的方法来发现异常值。

    Scikit-Learn的EllipticEnvelope模型,它在假设我们的数据是多元高斯分布的基础上计算出高斯分布的一些关键参数过程。过程大致如下:

      ●根据前面定义的类别创建两个不同的数据集 : search_Sat_night和Search_Non_Sat_night。
      ●在每个类别应用EllipticEnvelope(高斯分布)。
      ●我们设置contamination参数,它表示我们数据集中异常值的比例。
      ●使用decision_function来计算给定数据的决策函数。 它等于移位的马氏距离(Mahalanobis distances)。 异常值的阈值为0,这确保了与其他异常值检测算法的兼容性。
      ●使用predict 来预测数据是否为异常值(1 正常值, -1 异常值)

    # 基于高斯概分布的异常检测
    df_class0 = data.loc[data['风轮转速'] >7, '风轮转速']
    df_class1 = data.loc[data['风轮转速'] <=7, '风轮转速']
     
    envelope =  EllipticEnvelope(contamination = outliers_fraction) 
    X_train = df_class0.values.reshape(-1,1)
    envelope.fit(X_train)
    df_class0 = pd.DataFrame(df_class0)
    df_class0['deviation'] = envelope.decision_function(X_train)
    df_class0['anomaly'] = envelope.predict(X_train)
     
    envelope =  EllipticEnvelope(contamination = outliers_fraction) 
    X_train = df_class1.values.reshape(-1,1)
    envelope.fit(X_train)
    df_class1 = pd.DataFrame(df_class1)
    df_class1['deviation'] = envelope.decision_function(X_train)
    df_class1['anomaly'] = envelope.predict(X_train)
     
    df_class = pd.concat([df_class0, df_class1])
    
    data['anomaly4'] = df_class['anomaly']
    fig, ax = plt.subplots(figsize=(10, 6))
    a = data.loc[data['anomaly4'] == -1, ('时间戳', '风轮转速')] 
    ax.plot(data['时间戳'], data['风轮转速'], color='blue', label = '正常值')
    ax.scatter(a['时间戳'],a['风轮转速'], color='red', label = '异常值')
    plt.show()
    

    在这里插入图片描述
    从上图可知,使用EllipticEnvelope预测的异常值,它们的风轮转速大多位于区间的最高点处,而在最低点处没有出现异常值。

    到目前为止,我们已经用四种不同的方法进行了风轮数据异常检测。 因为我们的异常检测是无监督学习。 在构建模型之后,我们不知道他们的异常检测效果怎么样,因为我们没有办法可以对他们进行测试。 通常异常检测只有在实际的应用场景中才能测试出它的效果。

    III “预测”提交

    让我们先来看一下我们的训练集data
    在这里插入图片描述
    根据上述四种不同模型的异常检测我们得到了anomaly1-4的检测值,在此基础上,你可以选择投票的方式得到最终的结果“预测”,或一票决定。

    data['sum'] = data['风轮转速_01'] + data['anomaly1'] + data['anomaly2'] + data['anomaly3'] + data['anomaly4']
    ## 注意,请选择以下两种方式的一种进行运行,直接运行将会使一票决定覆盖投票
    # 投票
    submit.loc[:,'label'] = data.loc[:,'sum'].map({0:0,1:0,2:0,3:1,4:1,5:1})
    # 一票决定
    submit.loc[:,'label'] = data.loc[:,'sum'].map({0:0,1:1,2:1,3:1,4:1,5:1})
    

    最终提交,并评测

    submit.to_csv('../output/baseline.csv',index=False)
    submit.head()
    



    完整ipynb代码文件和比赛数据可见Github
    https://github.com/AmangAris/Abnormal-data-identification-and-cleaning-of-wind-turbine

    数据集放在了Q群,群文件免费下载:782589269

    展开全文
  • 对于异常数据的分析,剔除异常数据的方法,有哪些?求各位大神的指点!
  • Python异常数据处理——箱型图分析

    万次阅读 2020-08-05 15:35:51
    在数据分析中,利用箱型图的方法对异常数据进行过滤,是一种很快速、很有效的异常数据处理方法。 箱形图(英文:Box plot),又称为盒须图、盒式图、盒状图或箱线图,是一种用作显示一组数据分散情况资料的统计图。...

    在数据分析中,利用箱型图的方法对异常数据进行过滤,是一种很快速、很有效的异常数据处理方法。
    箱形图(英文:Box plot),又称为盒须图、盒式图、盒状图或箱线图,是一种用作显示一组数据分散情况资料的统计图。因型状如箱子而得名。在各种领域也经常被使用,常见于品质管理,快速识别异常值。
    箱形图最大的优点就是不受异常值的影响,能够准确稳定地描绘出数据的离散分布情况,同时也利于数据的清洗。

    箱型图可以通过程序设置一个识别异常值的标准,即大于或小于箱型图设定的上下界的数值则识别为异常值,箱型图如下图所示:
    在这里插入图片描述
    其中,有5个重要的因素需要理解:

    1. 上四分位数U:表示所有样本中只有1/4的数值大于U ,即从大到小排序时U处于25%处。
    2. 下四分位数 L:表示所有样本中只有1/4的数值小于L,即从大到小排序时L处于75%处。
    3. 中位数Q:表示一组数由小到大排列处于中间位置的数,若序列数为偶数个,该组的中位数为中间两个数的平均数。
    4. 上限:表示非异常范围内的最大值,四分位距为 IQR=U-L,则上限为 U+1.5IQR。
    5. 下限:表示非异常范围内的最小值,下限为 L-1.5IQR。

    不过箱型图进行异常数据处理也有它的局限性,比如并不适合巨量且时间跨度很长的数据,因为箱型图实在太客观了,只关注整体数据的分布,但并不会跟踪数据整体的变化趋势,所以这时候可以把数据分段后再逐步进行异常数据处理。

    下面就用Python来实现箱型图异常数据处理,主要代码如下:

    import pandas as pd
    
    
    def box_plot_outliers(data_ser, box_scale):
        """
        利用箱线图去除异常值
        :param data_ser: 接收 pandas.Series 数据格式
        :param box_scale: 箱线图尺度,默认用 box_plot(scale=3)进行清洗
        :return:
        """
        iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
        # 下阈值
        val_low = data_ser.quantile(0.25) - iqr*1.5
        # 上阈值
        val_up = data_ser.quantile(0.75) + iqr*1.5
        # 异常值
        outlier = data_ser[(data_ser < val_low) | (data_ser > val_up)]
        # 正常值
        normal_value = data_ser[(data_ser > val_low) & (data_ser < val_up)]
        return outlier, normal_value, (val_low, val_up)
    
    
    # 过滤异常值
    outlier, normal_value, value = box_plot_outliers(data[sensor], 3)
    outlier = pd.DataFrame(outlier)   # 异常数据
    normal_value = pd.DataFrame(normal_value)   # 正常数据
    

    以实际数据进行测试,正常值和异常值的分布如图所示:
    在这里插入图片描述
    完整代码如下:

    import numpy as np
    import pandas as pd
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdate
    from datetime import datetime, timedelta
    from def_files_data import get_all_files, get_path_data
    
    
    def box_plot_outliers(data_ser, box_scale):
        """
        利用箱线图去除异常值
        :param data_ser: 接收 pandas.Series 数据格式
        :param box_scale: 箱线图尺度,取3
        :return:
        """
        iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
        # 下阈值
        val_low = data_ser.quantile(0.25) - iqr*0.5
        # 上阈值
        val_up = data_ser.quantile(0.75) + iqr*0.5
        # 异常值
        outlier = data_ser[(data_ser < val_low) | (data_ser > val_up)]
        # 正常值
        normal_value = data_ser[(data_ser > val_low) & (data_ser < val_up)]
        return outlier, normal_value, (val_low, val_up)
    
    
    '''数据处理'''
    def read_data(sensor, begin_time, end_time):
        path = '../../data/SHMData/梁体位移/{}'.format(sensor)
        # 读取所有文件名
        files_list = get_all_files(path)
        if len(files_list) > 0:
            # 获取文件夹内的所有文件数据并拼接起来
            data = get_path_data(files_list, begin_time, end_time)
    
            # 过滤异常值
            outlier, normal_value, value = box_plot_outliers(data['displacement'], 3)
            outlier = pd.DataFrame(outlier)
            normal_value = pd.DataFrame(normal_value)
            return normal_value, outlier
    
    
    '''异常值分布图'''
    def Outliers_fig(fig_title, fig_num, col_name, xlabel, ylabel):
        # 画布大小
        fig = plt.figure(figsize=(14, 7), edgecolor='blue')
        # 标题
        plt.suptitle(fig_title, fontsize=20, x=0.5, y=0.970)
        # 调整子图在画布中的位置
        plt.subplots_adjust(bottom=0.145, top=0.9000, left=0.075, right=0.990)
        ax = fig.add_subplot(fig_num)
        ax.plot_date(normal_value.index, normal_value[col_name], 'bo', linewidth=1.5, label='正常值')
        ax.plot_date(outlier.index, outlier[col_name], 'ro', linewidth=1.5, label='异常值')
        ax.set_xlabel(xlabel, fontsize=18, labelpad=7)
        ax.set_ylabel(ylabel, fontsize=18, labelpad=7)
        ax.tick_params(labelsize=18, direction='out')
        ax.grid(linestyle='--')
        ax.legend(fontsize=15)
        # 中文显示
        mpl.rcParams['font.sans-serif'] = ['SimHei']
        mpl.rcParams['axes.unicode_minus'] = False
        return ax
    
    
    '''设置刻度'''
    def set_axis(ax):
        plt.xlim([begin_time + timedelta(days=-1), end_time + timedelta(days=1)])  # 日期上下限
        ax.xaxis.set_major_formatter(mdate.DateFormatter('%m-%d'))
        dayLoc = mpl.dates.DayLocator(interval=5)
        ax.xaxis.set_major_locator(dayLoc)
        ax.xaxis.set_tick_params(rotation=0, labelsize=18)
    
    
    if __name__ == '__main__':
        sensor_list = ['B03-WY-001']
        begin_time = datetime(2020, 1, 1, 0, 0, 0)
        end_time = datetime(2020, 3, 31, 23, 59, 59)
        title_time_begin = begin_time.strftime('%Y-%m')
        title_time_end = end_time.strftime('%Y-%m')
    
        # 绘图
        for sensor in sensor_list:
            normal_value, outlier = read_data(sensor, begin_time, end_time)
    
            fig_title = "{}纵向位移异常值分布图,数据时间:{}——{}".format(sensor, title_time_begin, title_time_end)
            Displacement_ax = Outliers_fig(fig_title, 111, 'displacement', '时间(month-day)', '位移(mm)')
            set_axis(Displacement_ax)
            plt.show()
    
    展开全文
  • Spring MVC全局异常后返回JSON异常数据

    万次阅读 热门讨论 2015-08-29 18:37:19
    Spring MVC全局异常后返回JSON异常数据 问题:  当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发。后台服务与手机端交互是发送JSON数据。如果后台发生异常,会直接返回异常页面,显示...

    Spring MVC全局异常后返回JSON异常数据

    问题:

            当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发。后台服务与手机端交互是发送JSON数据。如果后台发生异常,会直接返回异常页面,显示异常内容,如果是404请求不到资源或者500这类服务器的问题,可能会导致返回404和500异常页面,手机端的处理就非常麻烦,为了解决这个问题,就需要做全局的异常处理。

    解决方案:

    (1)自定义或者使用spring自带的各种异常处理器

           例如spring基于注解的异常解析器AnnotationHandlerMethodExceptionResolver 、spring自带全局异常处理器SimpleMappingExceptionResolver、自定义实现spring的全局异常解析器HandlerExceptionResolver来处理。

           AnnotationHandlerMethodExceptionResolver目前我所知道的是需要在方法上定义异常的类型,如果异常类型多了,写起代码太麻烦,所以我认为不好用。(那位大侠知道不用定义异常类型就处理所有异常,可以留言告诉我,谢谢!)

           spring自带全局异常处理器SimpleMappingExceptionResolver也是比较繁琐的,需要配置的地方太多了,不喜欢用。

           自定义实现spring的全局异常解析器HandlerExceptionResolver来处理我认为是最方便的,当然,这个是针对我目前的业务场景而言,并不是绝对的。

            由于java的异常机制,如果发生大量异常,对jvm的性能会产生很大的影响,轻则性能下降10%,重则导致jvm内存溢出,我个人认为能不抛异常就最好不抛,所以,我主要使用自定义实现spring的全局异常解析器HandlerExceptionResolver来处理业务问题。

          

    (2)自定义实现spring的全局异常解析器HandlerExceptionResolver

           2.1 只需要在spring-mvc的配置文件中定义一个全局异常处理类

            <!-- 全局异常处理 -->
            <bean id="exceptionHandler" class="com.aaa.bbb.exception.DefaultExceptionHandler" />
          2.2  实现HandlerExceptionResolver(第一种实现方式)

                 这种方式需要下载温少写的fastjson,我用的是1.2.6版本,可以百度后自己下载。

    public class DefaultExceptionHandler implements HandlerExceptionResolver {  
    	private static Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
        
    	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,  Exception ex) {  
    	        ModelAndView mv = new ModelAndView();
    	        /*	使用FastJson提供的FastJsonJsonView视图返回,不需要捕获异常	*/
    	        FastJsonJsonView view = new FastJsonJsonView();
    	        Map<String, Object> attributes = new HashMap<String, Object>();
    	        attributes.put("code", "1000001");
    	        attributes.put("msg", ex.getMessage());
    	        view.setAttributesMap(attributes);
    	        mv.setView(view); 
    	        log.debug("异常:" + ex.getMessage(), ex);
    	        return mv;
        }
    } 
           2.2  实现HandlerExceptionResolver(第二种实现方式)

    public class DefaultExceptionHandler implements HandlerExceptionResolver {  
    	private static Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
        
    	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,  Exception ex) {  
    	        ModelAndView mv = new ModelAndView();	        
    	        /*	使用response返回	*/
    	        response.setStatus(HttpStatus.OK.value()); //设置状态码
    	        response.setContentType(MediaType.APPLICATION_JSON_VALUE); //设置ContentType
    	        response.setCharacterEncoding("UTF-8"); //避免乱码
    	        response.setHeader("Cache-Control", "no-cache, must-revalidate");
    	        try {
    	            response.getWriter().write("{\"success\":false,\"msg\":\"" + ex.getMessage() + "\"}");
    	        } catch (IOException e) {
    	           log.error("与客户端通讯异常:"+ e.getMessage(), e);
    	        }
    
    	        log.debug("异常:" + ex.getMessage(), ex);
    	        return mv;
        }
    }

    到此,spring mvc全局异常处理返回json就搞定了,发生异常后,返回的都是json数据,不会再有烦人的异常内容。不过这还不算完整,需要在web.xml中加入异常代码404或者500的处理才能算完。

    (1)web页面异常处理配置

     1.1  <exception-type>java.lang.Throwable</exception-type>表示发生java.lang.Throwable类型的异常,<location>/error_500</location>表示到/error_500地址处理,

        例如用户请求【http://www.a.com/user/login/getUser】 ,应用名称是user,如果请求发生java.lang.Throwable,那么请求会转到【http://www.a.com/user/error_500】

     1.2 <error-code>404</error-code>表示发生404请求失败,<location>/error_404</location>表示到/error_404处理,

        例如用户请求【http://www.a.com/user/login/getUser】,应用名称是user ,如果用户请求发生404异常,请求资源找不到,那么请求会转到【http://www.a.com/user/error_404】

    	<!-- web异常页面处理 -->
    	<error-page>
    		<exception-type>java.lang.Throwable</exception-type>
    		<location>/error_500</location>
    	</error-page>
    	<error-page>
    		<exception-type>java.lang.Exception</exception-type>
    		<location>/error_404</location>
    	</error-page>
    	<error-page>
    		<error-code>500</error-code>
    		<location>/error_500</location>
    	</error-page>
    	<error-page>
    		<error-code>501</error-code>
    		<location>/error_500</location>
    	</error-page>
    	<error-page>
    		<error-code>502</error-code>
    		<location>/error_500</location>
    	</error-page>
    	<error-page>
    		<error-code>404</error-code>
    		<location>/error_404</location>
    	</error-page>
    	<error-page>
    		<error-code>403</error-code>
    		<location>/error_404</location>
    	</error-page>
    	<error-page>
    		<error-code>400</error-code>
    		<location>/error_404</location>
    	</error-page>

    (2)后台处理

      如果发生以上异常,请求会转到【http://www.a.com/user/error_404】,那么在后台就需要做相应的处理,处理方式就是在Controller层定义处理异常的方法

    	/**
    	 * 请求异常
    	 * @return
    	 * @throws Exception
    	 * String
    	 */
    	@RequestMapping(value = "/error_404", produces = "text/html;charset=UTF-8")
    	@ResponseBody
    	public String error_404() throws Exception { 
    		 return "{\"msg\":\"找不到页面\",\"code\":\"1000001\"}";
    	}
    	/**
    	 * 服务器异常
    	 * @return
    	 * String
    	 */
    	@RequestMapping(value ="/error_500", produces = "text/html;charset=UTF-8")
    	public String error_500() {		<pre name="code" class="java">                return "{\"msg\":\"服务器处理失败\",\"code\":\"1000002\"}";
    	}

    
    
    最后,基本上所有的异常都能被捕获,能够出现异常时,友好的提示用户端,也能避免服务器端抛异常导致的问题。




    展开全文
  • 异常数据剔除

    万次阅读 2017-08-30 18:07:03
    1.在SPSS中做箱型图,图中可以显示异常值,然后剔除。但问题是大数据,采用箱形图已经不显示了 2.拉依达准则法(3δ):简单,无需查表。测量次数较多或要求不高时用。是最常用的异常值判定与剔除准则。但当测量...
  • 要求用MATLAB写一个可以实现异常数据检测的程序,急求大神回复。
  • 在统计学中,Dixon的Q检验或简单的Q检验用于识别和拒绝异常值。假设正态分布,根据Robert Dean和Wilfrid Dixon以及其他人的说法,这个测试应该在数据集中谨慎使用,并且不要超过一次。要对错误数据应用Q测试,请按...
  • 介绍: 在统计理论中,肖维勒准则(以William ...通过这样做,来自位于该概率带之外的n个样本的任何数据点可以被认为是异常值,从数据集中移除,并且可以计算基于剩余值和新样本大小的新的均值和标准偏差。 ...
  • pandas添加、删除DataFrame行、列 处理异常数据
  • 现在有这样一组数据,希望去除掉里面的异常数据。其中,异常数据可能比正常数据大也可能比正常数据小,可能是正的也可能是负的。 数据为deg=[] import numpy as np if(True): #new_nums = list(set(deg)) #...
  • Peirce准则是消除异常值的统计程序。
  • R语言:异常数据处理

    千次阅读 2019-06-05 14:36:42
    为了有效的避免这些异常点造成的损失,我们需要采取一定的方法对其进行处理,而处理的第一步便是找到异常点在数据中的位置。   什么是异常值?如何检测异常值? 目录  1. 单变量异常值检测  2. 使用LOF(...
  • 去除异常数据的思路

    千次阅读 2013-08-16 16:34:13
    在对大量数据进行分析时 如果有些数值不符合正常情况 可以用以下方法尝试 去异常值: 求出所有数值的均值m(主要不要去重) m=(x1+x2+....xn)/n 求出所有数值的标准差 s 标准差计算公式 : s=Math.Sqrt((x1...
  • 在19世纪,统计分析方法主要应用在生物数据分析,是习惯的研究人员假设观察遵循正态分布,如乔治·艾里先生和梅里曼教授,其作品被批评卡尔·皮尔逊在他的1900纸。 直到19世纪末,皮尔森注意到在一些生物观察中...
  • 在jquery datagrid 中可以添加下面红色字体部分,对异常数据进行过滤,解决jquery easyui报错的问题 $('#dg').datagrid( {  url : ctx+ '/SysUserSelectByPage', title : '用户列表', pageSize : 20, fit : ...
  • 第一次发表博客,先发一个简单的...最近在做一个项目(android端),需要剔除异常数据,就是根据之前一组数据判断新来的数据是否为合理数据,在相差过大的时候予以剔除,找到了格拉布斯准则,具体内容和步骤参见链接...
  • 拉依达准则去除异常数据

    千次阅读 2020-07-25 17:07:15
    拉依达准侧(Pau’ta Criteron)是先假设一组数据中只含有随机误差,首先按照一定准侧计算标准偏差,按照一定概率确定一定区间,认为不在这个区间的为异常值。 使用数据类型:数据呈正太分布或者近似正太分布。 2....
  • 在使用springboot配置了统一异常处理,也可以捕获到异常信息,但是就是返回的数据还是老样子 关键错误信息: Failed to invoke @ExceptionHandler method: public org.springframework.web....
  • 2.消费异常数据库回滚 @Transactional(rollbackFor = RollbackException.class) @Override public Object icCardDataSave(List<CardTrade> list) throws BusinessException { //业务 } 3.配置文件 ...
  • 如何清除 DBA_DATAPUMP_JOBS 视图中的异常数据泵作业? 解决方案 用于这个例子中的作业: - 导出作业 SCOTT.EXPDP_20051121 是一个正在运行的 schema 级别的导出作业 - 导出作业 SCOTT.SYS_EXPORT_T...
  • 拉依达准则是指先假设一组检测数据只含有随机误差,对其进行计算处理得到标准偏差,按一定概率确定一个区间,认为凡超过这个区间的误差,就不属于随机误差而是粗大误差,含有该误差的数据应予以剔除。 这种判别处理...
  • 利用格拉布斯准则,剔除异常数据

    千次阅读 2018-08-13 15:31:02
    4、用这个Gi 值 与 格拉布斯临界表表中的 临界值比较,越大,越异常,需剔除 注: 这个临界值 与 顶尖水平(alpha)有关 在0.01 - 0.99中选,越小越严格 ,以及测量次数(数组集合长度) 查格拉布斯...
  • 包括三个数据字段: gender:性别,1为男性,2为女性 Temperature:体温 HeartRate:心率 要解决的问题如下: 人体体温的总体均值是否为98.6华氏度? 人体的温度是否服从正态分布? 人体体温中存在...
  • 作者:时之沙全文共 2164 字 4 图,阅读需要 5 分钟———— / BEGIN / ————数据异常分析,是数据分析工作中最常见且重要的分析主题,通过一次次的异常分...
  • 异常数据处理——箱型图分析原理

    千次阅读 2018-09-13 12:41:59
    箱型图可以通过程序设置一个识别异常值的标准,即大于或小于箱型图设定的上下界的数值则识别为异常值,箱型图如下图所示: 首先我们定义下上四分位和下四分位: 上四分位我们设为 U,表示的是所有样本中只有1/4...
  • 关于SpringMVC统一异常处理的问题,网搜一大把。网上搜的关于如何进行统一异常处理不外乎如下三种方式:Spring MVC处理异常有3种方式: 然而,我的需求不是这样咯.........
  • wireshark 学习更进一步 之wireshark异常数据解读

    万次阅读 多人点赞 2017-07-19 19:56:57
    wireshark异常数据,软件本身会以特殊颜色底纹标识。或者可以通过Analyze-->Expert Information分析。 1、TCP Previous segment not captured 、TCP Out-Of-Order [TCP Previous segment not captured]在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,684,538
精华内容 673,815
关键字:

异常数据