天天看點

進階版拉依達準則(3sigm準則)的提出與應用

修正版拉依達準則的提出與應用

    • 前言
    • 一:基于實驗說明異常點對模型結果的影響
    • 二:異常點的判定
    • 三:修正版拉依達準則(3σ準則)
    • 四:理論驗證
    • 五:代碼實作
    • 六:總結

前言

在前兩次文章中,我們都提到異常點對此特征提取方法(模型)是有一定影響的,為了加強模型的魯棒性(穩健性),對異常點處理是必不可少的。本文就從淺顯案例說明異常點如何在實際中影響模型結果,以及如何處理異常點。

PS:歡迎各位朋友與鄙人多多交流,多多關注,鄙人從2021/7/25日起,如沒有特殊原因的話會1-2周左右更新一篇文章,寫文章目的僅為了多認識新朋友,抛磚引玉,互相取長補短~~~

點選跳轉個人知乎賬号

進階版拉依達準則(3sigm準則)的提出與應用

一:基于實驗說明異常點對模型結果的影響

  • 異常點的闡述

異常點不同于缺失值或者重複資料那麼肉眼就能觀察到,異常點的存在也不是完全沒有意義的,往往會蘊含其他内容的資訊,同時還要分析異常點出現的可能原因;異常點的判斷也是要有依據的,不能把正确資料當成異常點了。

  • 利用簡單資料集做實驗說明異常點的影響力
(PS:為了明了清晰說明問題,我們基于的原始資料集一般都為正數,這也大部分符合生産實際中的資料分布!)

我們還是利用第一篇文章的資料集,但在次元‘C’,‘D’,‘E’中各加了個異常值(異常值大小人為設定為平均值的10多),原來的敏感特征排名前3的是‘F’,‘A’,‘B’,

可以參考第一篇文章結論

含異常值後結果如下,原本敏感排名靠後的3個次元,結果就因為含了1個異常值,排名完全變了,可想而知異常點對一個模型影響是存在的,尤其是在原始資料集少的情況下。

************************************距離運算法結果*************************************
         絕對距離      相對距離
0    8.527123  0.258398
1  153.253272  0.173560
2   52.000000  1.148917
3  140.000000  0.893883
4  114.700000  1.176652
5   24.387415  0.401770
Index(['E', 'C', 'D', 'F', 'A', 'B'], dtype='object')
原本不含異常點的排序情況(都為降序):['F', 'A', 'B', 'E', 'C', 'D']
           
進階版拉依達準則(3sigm準則)的提出與應用

圖1

上圖圖1展示的是含有異常點的可視化折線圖,紅圈為異常點值。

二:異常點的判定

  • 異常點的判定目标

一般情況下,異常點指的是某一個次元下樣本的資料值出現異常情況,可視為某一樣本下的單一次元資料為異常點,

我們也可以把所有次元當做一個整體目标,判定在這些樣本中哪些樣本是異常點。

  • 異常點常用判定方法

既然判定目标不同,那麼方法也就不同,如果基于單一次元下,哪些樣本值是異常點,那麼常用的可以基于統計分布模型來檢驗,顧名思義要先知道資料集的分布情況,如果資料集分布很明确,無論對高維還是非高維資料都是很不錯的選擇,

正态分布之是以是常态分布,是因為很大程度上客觀事物随着資料量的增大都服從或者近似服從,是以在不非常明确具體資料集分布下,基于正态分布的統計假設應當作為首選。

還有些比較系統性的方法,有基于鄰近度、基于聚類等等,這些方法可以對整體次元資料進行操作,但這會涉及次元資料差異性的影響,是以如果預處理得當的話,效果也是不錯的。

三:修正版拉依達準則(3σ準則)

正态分布有個必要要求就是樣本資料量要足夠大(樣本數大于30即可)。經典的3σ準則為:

令任意第 i i i維有 m m m個資料樣本資料為

x i = ( x 1 i , x 2 i , . . . x m i ) x^{i}=\left( x_{1}^{i}, x_{2}^{i},... x_{m}^{i} \right) xi=(x1i​,x2i​,...xmi​),

簡記為

x = ( x 1 , x 2 , . . . x m ) x=\left( x_{1}, x_{2},... x_{m} \right) x=(x1​,x2​,...xm​),

其中 x x x的均值為 μ \mu μ ,标準差為 σ \sigma σ ,則如果

∣ x j − μ ∣ ≥ 3 σ |x_{j}-\mu|\geq 3\sigma ∣xj​−μ∣≥3σ,

那麼 x j x_{j} xj​ 視為異常值。

  • 以上準則在我看來需要修正

我們假設如果出現某一個或幾個(有限個,因為畢竟異常點的存在是少量的)特别“大”的異常值,那麼由二階原點距(方差)公式:

σ 2 = ∑ i m ( x i − μ ) 2 m \sigma^{2}=\frac{\sum_{i}^{m}{(x_{i}-\mu)^{2}}}{m} σ2=m∑im​(xi​−μ)2​(全資料集)

我們有 :

σ μ = ( x 1 − u ) 2 + ( x 2 − u ) 2 + . . . + ( x m − u ) 2 m u \frac{\sigma}{\mu}=\frac{\sqrt{(x_{1}-u)^{2}+(x_{2}-u)^{2}+...+(x_{m}-u)^{2}}}{\sqrt{m}u} μσ​=m

​u(x1​−u)2+(x2​−u)2+...+(xm​−u)2

​​

= [ ( m − 1 ) x 1 − ( x 2 + x 3 + . . . + x m ) m ] 2 + [ ( m − 1 ) x 2 − ( x 1 + x 3 + . . . + x m ) m ] 2 + [ ( m − 1 ) x m − ( x 1 + x 2 + . . . + x m − 1 ) m ] 2 ( m ) − 1 ( x 1 + x 2 + . . . + x m ) =\frac{\sqrt{\left[ \frac{(m-1)x_{1}-(x_{2}+x_{3}+...+x_{m})}{m} \right]^{2}+\left[ \frac{(m-1)x_{2}-(x_{1}+x_{3}+...+x_{m})}{m} \right]^{2}+\left[ \frac{(m-1)x_{m}-(x_{1}+x_{2}+...+x_{m-1})}{m} \right]^{2}}}{(\sqrt{m})^{-1}(x_{1}+x_{2}+...+x_{m})} =(m

​)−1(x1​+x2​+...+xm​)[m(m−1)x1​−(x2​+x3​+...+xm​)​]2+[m(m−1)x2​−(x1​+x3​+...+xm​)​]2+[m(m−1)xm​−(x1​+x2​+...+xm−1​)​]2

​​

= [ ( m − 1 ) x 1 − ( x 2 + x 3 + . . . + x m ) ] 2 + [ ( m − 1 ) x 2 − ( x 1 + x 3 + . . . + x m ) ] 2 + [ ( m − 1 ) x m − ( x 1 + x 2 + . . . + x m − 1 ) ] 2 m ( x 1 + x 2 + . . . + x m ) ) ( ∗ 1 ) = \frac{\sqrt{\left[ (m-1)x_{1}-(x_{2}+x_{3}+...+x_{m}) \right]^{2}+\left[ (m-1)x_{2}-(x_{1}+x_{3}+...+x_{m}) \right]^{2}+\left[ (m-1)x_{m}-(x_{1}+x_{2}+...+x_{m-1}) \right]^{2}}}{\sqrt{m}(x_{1}+x_{2}+...+x_{m})})(*1) =m

​(x1​+x2​+...+xm​)[(m−1)x1​−(x2​+x3​+...+xm​)]2+[(m−1)x2​−(x1​+x3​+...+xm​)]2+[(m−1)xm​−(x1​+x2​+...+xm−1​)]2

​​)(∗1)

接下來我們設異常點是第 k ( k ∈ [ 1 , m ] ) k\left( k\in[1,m] \right) k(k∈[1,m]) 個,則對第 k k k 個樣本我們同理有表達式 :

[ ( m − 1 ) x k − ( x 1 + x 2 + . . . + x k − 1 + x k + 1 + . . . + x m ) ] 2 \left[ (m-1)x_{k}-(x_{1}+x_{2}+...+x_{k-1}+x_{k+1}+...+x_{m}) \right]^{2} [(m−1)xk​−(x1​+x2​+...+xk−1​+xk+1​+...+xm​)]2。

由開始假設異常點值足夠大,可令 x k → ∞ x_{k}\rightarrow\infty xk​→∞ ,那麼上面 (*1) 式變為

⇒ lim ⁡ x k → ∞ ( m − 1 ) x k 2 + [ ( m − 1 ) x k ] 2 m x k = m − 1 + o ( m ) ( m ≥ 1 ) ( ∗ 2 ) \Rightarrow\lim_{x_{k} \rightarrow \infty}{}\frac{\sqrt{(m-1)x_{k}^{2}+\left[ (m-1)x_{k} \right]^{2}}}{\sqrt{m}x_{k}}=\sqrt{m-1}+o(m)(m\geq1)(*2) ⇒limxk​→∞​m

​xk​(m−1)xk2​+[(m−1)xk​]2

​​=m−1

​+o(m)(m≥1)(∗2)

由上面簡單推導發現,當存在異常大的樣本值後, σ μ \frac{\sigma}{\mu} μσ​ 的結果完全跟 m m m 的大小有關,且 m m m 越大,這比值就會越大,對于存在非單個且少量異常點時 ( 1 < τ ≪ m ) (1<\tau\ll m) (1<τ≪m) ,其中 τ \tau τ 為異常點個數,同理很容易得到(*2 ) 式的變形結果

( m − τ ) / τ + o ( m ) ( m ≫ τ , x k → ∞ ) \sqrt{(m-\tau)/\tau}+o(m)(m\gg \tau ,x_{k}\rightarrow\infty) (m−τ)/τ

​+o(m)(m≫τ,xk​→∞)。

進階版拉依達準則(3sigm準則)的提出與應用

為了結合實際論證分析有效,我們稍加程式驗證即可

#當有1個異常點值時,随樣本m增大
S1 = pd.Series([1,2,3,4,1000,2,5,5])
print(S1.std(ddof=0)/S1.mean())##2.58

S2 = pd.Series([1,2,3,4,1000,2,5,5,6,5,6,9,8,9,8,3,2,2,3])
print(S2.std(ddof=0)/S2.mean())##3.89

S3 = pd.Series([1,2,3,4,1000,2,5,5,6,5,8,8,6,9,8,9,8,9,5,6,6,6,5,4,5,5,2,2,3,8,3,2,2,3,6,1,1])
print(S3.std(ddof=0)/S3.mean())##5.09

#當存在1個異常點趨于無窮大
S6 = pd.Series([1,2,3,4,100000000,2,5,5,6,5,8,2,6,9,8,9,9,5,6,6,6,5,11,5,5,10,2,3,8,3,2,2,3,6,1,1])
print(S6.std(ddof=0)/S6.mean(),np.power((len(S6) - 1) / 1,0.5))##5.9160692 5.9160798

#當存在2個異常點趨于無窮大
S7 = pd.Series([1,2,3,4,100000000,2,5,5,1,2,6,5,1,5,8,2,6,9,8,9,9,5,6,6,6,5,100000000,5,1,5,5,2,1,3,2])
print(S7.std(ddof=0)/S7.mean(),np.power((len(S7) -2) / 2,0.5))##4.0620161 4.0620192

#當存在3個異常點趨于無窮大
S8 = pd.Series([1,2,3,4,100000000,2,5,5,1,2,6,5,1,5,8,2,100000000,9,8,9,9,5,6,6,6,5,100000000,5,1,5,5,2,1,3,2])
print(S8.std(ddof=0)/S8.mean(),np.power((len(S8) -3) / 3,0.5))##3.2659847 3.2659863

#當存在2個異常值很大,卻不是無窮大時
S7 = pd.Series([1,2,3,4,1000,2,5,5,1,2,6,5,1,5,8,2,6,9,8,9,9,5,6,6,6,5,1000,5,1,5,5,2,1,3,2])
print(S7.std(ddof=0)/S7.mean(),np.power((len(S7) -2) / 2,0.5))##3.7709924 4.062019
以上程式結果很符合我們理論分析結果。
注:在理論分析時,異常點設為的是同級别的“無窮大”,取極限結果才成立!
           
  • 修正原因理論分析

我們再結合拉依達準則: ∣ x j − μ ∣ ≥ 3 σ |x_{j}-\mu|\geq 3\sigma ∣xj​−μ∣≥3σ ,很明确的會發現當存在過大的異常點時,那麼判定異常點的門檻值範圍非常大即 [ x j < − ( 1 + 3 C m ) μ , x j > ( 1 + 3 C m ) μ ] \left[ x_{j}<-(1+3C\sqrt{m})\mu, x_{j}>(1+3C\sqrt{m})\mu \right] [xj​<−(1+3Cm

​)μ,xj​>(1+3Cm

​)μ] (C設為變常數),那這樣就會造成除非非常異常的資料能剔除,稍微異常資料(亞異常值)有可能都落在這範圍内,導緻亞異常值根本剔除不掉,方法效率變得極為低下。

  • 修正方法

通過以上理論分析,我們知道了單純拉依達準則準則是有局限的(除非保證沒有極端異常點出現),是以我們對資料合理門檻值要有修正範圍,本篇文章主要是從 μ \mu μ 前面的系數入手,在計算 μ \mu μ 之前我們可以先對資料集進行去極值處理。接下來會結合程式和實際,做出具體修正措施。

四:理論驗證

  • 經典拉依達篩選結果
    進階版拉依達準則(3sigm準則)的提出與應用

圖2

我們從圖2中直覺感覺這些紅圈資料明顯異常于它們所在的次元的其它資料,那麼如果純粹用經典的拉依達準則,判斷的結果是:

A列:異常值範圍在區間[-44.04,63.65]之外,有[A,7]:75;
B列:異常值範圍在區間[-823.01,1315.51]之外,有[B,15]:1500;
C列:異常值範圍在區間[0.31,5.79]之外,無異常點
D列:異常值範圍在區間[5.53,18.77]之外,無異常點
E列:異常值範圍在區間[-2.79,4.25]之外,有[E,7]:5
           

這大大超乎我們的預期,是以這也驗證了第三節所說的,因為特異常點的存在,亞異常點很難被篩選出。

  • 剔除極端值的經典拉依達篩選結果

那麼就有疑問,經典的法則肯定受極端值影響,那麼我們剔除極端值之後再利用經典拉依達準則如何,結果如下:

A列:異常值範圍在區間[-22.41,35.86]之外,有[A,2]:45,[A,7]:75;
B列:異常值範圍在區間[-429.37,809.81]之外,有[B,15]:1500;
C列:異常值範圍在區間[0.63,5.38]之外,無異常點
D列:異常值範圍在區間[6.51,17.83]之外,無異常點
E列:異常值範圍在區間[-1.49,2.72]之外,有[E,2]:3,[E,7]:5
           

這結果就好很多,而且正常點區間範圍比之前縮小些,但還是有明顯的異常點沒有篩選出來。

  • 修正版拉依達篩選結果

同樣對圖2資料集操作,最終基于修正版的篩選結果如下

A列:異常點範圍在區間[1.42,12.03]之外,有[A,2]:35,[A,7]:75;[A,19]:0.02
B列:異常點範圍在區間[47.53,332.91]之外,有[B,3]:700,[B,14]:800,[B,15]:1500,[B,18]:1
C列:異常點範圍在區間[0.63,5.38]之外,無異常點
D列:異常點範圍在區間[6.51,17.83]之外,無異常點
E列:異常點範圍在區間[0.178,1.05]之外,有[E,2]:3,[E,7]:5
           

通過修正方法,我們的篩選結果符合預期,而且正常點範圍進一步縮小,顯得更加合理。

  • 異常點的替換

我們從結果上看,修正版的拉依達準則的有效性比經典版(包括去除極端值的)的好,那麼篩選出的異常點該如何處理呢,一般會做如下幾個處理

  1. 無視,把異常點的值作為正常值繼續後面模組化,
  2. 平均值處理,這裡的平均值可以是原始樣本的平均值,也可以是剔除異常點後的,但這裡有個說明,異常點絕大部分包含極值點,但也有可能會一端正常點的範圍過大而不包含極值點,
  3. 直接删除,那這個異常點位置将變為Nan值(空值),
  4. 視為缺失值,利用處理缺失值的方法進行處理。

此文的異常點替換是上述所說的方法2,結果如下:

進階版拉依達準則(3sigm準則)的提出與應用

圖3

從圖3結果我們觀察到,處理後的結果還是比較“幹淨的”。

五:代碼實作

  • 經典拉依達準則代碼如下
import pandas as pd

def choosesigm_prin(df,n=3):###預設sigm前面系數為3
    for i in range(df.shape[1]):
        tt = df.iloc[:, i]
        LS = list(tt)
        Max = list(df.max())[i]
        Min = list(df.min())[i]
        while Max in LS:
            LS.remove(Max)
        while Min in LS:###處理掉樣本中的極值,如果極值重複,一直去除
            LS.remove(Min)
        m = pd.Series(LS).mean()
        s = pd.Series(LS).std()
        print('極值取出後均值:%.3f'%m)
        print('極值取出後标準差:%.3f'%s)
        t1 = m - n * s
        t2 = m + n * s
        print('\033[1;38m異常值範圍在區間[%s,%s]之外\033[0m'%(t1,t2))
        fil_S = tt[(tt < t1) | (tt > t2)]###基于資料框做條件篩選,避免for循環出現
        print(fil_S)
        fil_index = fil_S.index###異常點的橫坐标位置
        col = df.columns[i]
        DF = df[col].drop(list(fil_index), axis=0)###去除異常值後的資料框的均值代替
        df[col].loc[fil_index] = DF.mean()
    print('\033[1;33m{0:*^80}\033[0m'.format('處理後結果'))
    print(df)
matx = [[8,5,45,7,6,2,3,75,4,2,5,3,4,6,3,5,5,6,2,0.02],[100,125,124,98,102,152,88,143,145,170,156,169,89,76,800,1500,85,102,1,98],[2,4,3,2,2,3.2,1.9,3,4,5,4,3.5,2,2,3,4,3,2.4,3,4],
        [12,14,15,9,10,11,13,14,13,12,10,11,13,14,12,12,16,9,8,15],[0.5,0.4,3,0.3,0.2,0.3,0.3,5,0.4,0.3,0.5,0.2,0.2,0.2,0.8,0.6,0.4,0.2,0.3,0.5]]
Index = ['A','B','C','D','E']
df = pd.DataFrame(matx,index=Index).T
choosesigm_prin(df,3)
           
  • 修正版拉依達準則代碼(節選)如下,我們上文也提到過,當存在過大異常點時,異常點的影響過于強烈,原始資料集去除極端值隻能防止第一步,但存在多個後就很難有效,于是我們要相應改變标準差 σ \sigma σ 前面的系數,邏輯如下:
R = s / m###去除極值後的樣本标準差/均值
if 0.5 <= R < 1:
    t1 = m - (n - R) * s
    t2 = m + (n - R) * s
    print('\033[1;38m對應第%s列标準差/均值倍數%.3f,由于0.5<值<1,臨界系數為%s,其合理值範圍[%.3f,%.3f]\033[0m' %
          (i + 1, R, n - R, t1, t2))
elif R < 0.5:##此時的标準差系數不變為n
    t1 = m - n * s
    t2 = m + n * s
    print('\033[1;38m對應第%s列标準差/均值倍數%.3f,由于值<0.5,臨界系數為%s,其合理值範圍[%.3f,%.3f]\033[0m' %
          (i + 1, R, n, t1, t2))
else:###當比值>1,我們設如下規則,其中R1是未去除極值的樣本标準差/均值
    R1 = list(df_sigm)[i] / list(df_mean)[i]
    # n = (1 / R1) + (1 / R)
    # n = n / 2
    # print(R1,R)
    n = min(1 / R1, 1 / R)
    t1 = m - n * s
    t2 = m + n * s
    print('\033[1;38m對應第%s标準差/均值倍數%.3f,由于值>1,臨界系數取%.3f,其合理值範圍[%.3f,%.3f]\033[0m' %(i + 1, R, nn, t1, t2))
           

以上規則也是可以變得,可以根據實際資料分布做不同運算處理,我們的目的是尋找更合理的正常值取值範圍,剔除更多的異常點資料。

六:總結

  • 本文比較系統地闡述了修正拉依達準的必要性,并增強了準則的魯棒性,通過理論+實驗得到驗證,
  • 但我們最終要用到實際場景的,此修正方法能否在實際資料集中表現很好,需要進一步實驗,尤其對 σ \sigma σ 前面的系數選擇,要根據實際指定新規則,
  • 如果想把整體次元資料直接判定哪個樣本是異常樣本,那又會有什麼樣的模型方法,這也是要解決的問題。