【python 機器學習】正態分佈檢驗以及異常值處理3σ原則

正態曲線呈鍾型,兩頭低,中間高,左右對稱因其曲線呈鐘形,因此人們又經常稱之爲鐘形曲線。

使用K-S檢驗一個數列是否服從正態分佈、兩個數列是否服從相同的分佈。

在這裏插入圖片描述

下面介紹 Python 中常用的幾種正態性檢驗方法:

scipy.stats.kstest

異常值是指樣本中的個別值,其數值明顯偏離其餘的觀測值。異常值也稱離羣點,異常值的分析也稱爲離羣點的分析。
在進行機器學習過程中,需要對數據集進行異常值剔除或者修正,以便後續更好地進行信息挖掘。
對於異常值的處理,3σ原則是最常使用的一種處理數據異常值的方法。那麼,什麼叫3σ原則呢?
3σ原則,又叫拉依達原則,它是指假設一組檢測數據中只含有隨機誤差,需要對其進行計算得到標準偏差,按一定概率確定一個區間,對於超過這個區間的誤差,就不屬於隨機誤差而是粗大誤差,需要將含有該誤差的數據進行剔除。
其侷限性:僅侷限於對正態或近似正態分佈的樣本數據處理,它是以測量次數充分大爲前提(樣本>10),當測量次數少的情形用準則剔除粗大誤差是不夠可靠的。在測量次數較少的情況下,最好不要選用該準則。
3σ原則:
數值分佈在(μ-σ,μ+σ)中的概率爲0.6827
數值分佈在(μ-2σ,μ+2σ)中的概率爲0.9545
數值分佈在(μ-3σ,μ+3σ)中的概率爲0.9973
其中,μ爲平均值,σ爲標準差。
一般可以認爲,數據Y的取值幾乎全部集中在(μ-3σ,μ+3σ)區間內,超出這個範圍的可能性僅佔不到0.3%,這些超出該範圍的數據可以認爲是異常值。

具體步驟如下:

  1. 首先需要保證數據列大致上服從正態分佈;
  2. 計算需要檢驗的數據列的平均值和標準差;
  3. 比較數據列的每個值與平均值的偏差是否超過3倍,如果超過3倍,則爲異常值;
  4. 剔除異常值,得到規範的數據。

方法一、KS檢驗3σ異常點檢測:

# -*- coding: utf-8 -*-

import numpy as np
import pandas as pd
from scipy.stats import kstest


def KsNormDetect(df):
    # 計算均值
    u = df['value'].mean()
    # 計算標準差
    std = df['value'].std()
    # 計算P值
    res=kstest(df, 'norm', (u, std))[1]
    # 判斷p值是否服從正態分佈,p<=0.05 則服從正態分佈,否則不服從。
    if res<=0.05:
        print('該列數據服從正態分佈------------')
        print('均值爲:%.3f,標準差爲:%.3f' % (u, std))
        print('------------------------------')
        return 1
    else:
        return 0



def OutlierDetection(df,ks_res):
    # 計算均值
    u = df['value'].mean()
    # 計算標準差
    std = df['value'].std()
    if ks_res==1:
        # 定義3σ法則識別異常值
        # 識別異常值
        error = df[np.abs(df['value'] - u) > 3 * std]
        # 剔除異常值,保留正常的數據
        data_c = df[np.abs(df['value'] - u) <= 3 * std]
        # 輸出異常數據
        # print(error)
        return error

    else:
        print('請先檢測數據是否服從正態分佈-----------')
        return None


if __name__ == '__main__':
    # 創建數據
    data = [1222, 87, 77, 92, 68, 80, 78, 84, 77, 81, 80, 80, 77, 92, 86, 76, 80, 81, 75, 77, 72, 81, 72, 84, 86, 80,
            68, 77, 87, 76, 77, 78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    ks_res=KsNormDetect(df)
    result=OutlierDetection(df, ks_res)
    print(result)
    
該列數據服從正態分佈------------
均值爲:164.850,標準差爲:306.289
------------------------------
    value
0    1222
38   1223
39   1232

方法二、箱線圖發現異常值:

# -*- coding: utf-8 -*-

import numpy as np
import pandas as pd


def OutlierDetection(df):
    # 計算下四分位數和上四分位
    Q1 = df.quantile(q=0.25)
    Q3 = df.quantile(q=0.75)

    # 基於1.5倍的四分位差計算上下須對應的值
    low_whisker = Q1 - 1.5 * (Q3 - Q1)
    up_whisker = Q3 + 1.5 * (Q3 - Q1)

    # 尋找異常點
    kk = df[(df > up_whisker) | (df < low_whisker)]
    data1 = pd.DataFrame({'id': kk.index, '異常值': kk})
    return data1



if __name__ == '__main__':
    # 創建數據
    data = [1222, 87, 77, 92, 68, 80, 78, 84, 77, 81, 80, 80, 77, 92, 86, 76, 80, 81, 75, 77, 72, 81, 72, 84, 86, 80,
            68, 77, 87, 76, 77, 78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    df=df.iloc[:,0]
    result=OutlierDetection(df)
    print('箱線圖檢測到的異常值如下---------------------')
    print(result)
箱線圖檢測到的異常值如下---------------------
    id   異常值
0    0  1222
36  36   123
37  37     3
38  38  1223
39  39  1232
發佈了653 篇原創文章 · 獲贊 795 · 訪問量 188萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章