Python

時間序列的簡單異常值檢測

  • September 15, 2019

我想為時間序列生成一個非常簡單的異常檢測示例。所以我用一個非常明顯的異常值創建了樣本數據。這是數據的圖片:

在此處輸入圖像描述

問題是,到目前為止,我還沒有任何方法可以可靠地檢測異常值。我嘗試了局部異常因子、隔離森林、k 最近鄰和 DBSCAN。根據我的閱讀,至少其中一種方法應該是合適的。我也嘗試調整參數,但這並沒有真正幫助。

我在這裡犯了什麼錯誤?方法不合適嗎?

下面是一個代碼示例。

提前致謝!

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(1)

t=np.linspace(0,10,101).reshape(-1,1)
y_test=0.5+t+t**2+2*np.random.randn(len(t),1)

y_test[10]=y_test[10]*7

plt.figure(1)
plt.plot(t,y_test)
plt.show;

from sklearn.neighbors import LocalOutlierFactor

clf=LocalOutlierFactor(contamination=0.1)
pred=clf.fit_predict(y_test)

plt.figure(3)
plt.plot(t[pred==1],y_test[pred==1],'bx')
plt.plot(t[pred==-1],y_test[pred==-1],'ro')
plt.show

from sklearn.ensemble import IsolationForest

clf=IsolationForest(behaviour='new',contamination='auto')
pred=clf.fit_predict(y_test)

plt.figure(4)
plt.plot(t[pred==1],y_test[pred==1],'bx')
plt.plot(t[pred==-1],y_test[pred==-1],'ro')
plt.show

from pyod.models.knn import KNN

clf = KNN()
clf.fit(y_test)
pred=clf.predict(y_test)

plt.figure(5)
plt.plot(t[pred==0],y_test[pred==0],'bx')
plt.plot(t[pred==1],y_test[pred==1],'ro')
plt.show

from sklearn.cluster import DBSCAN

clf = DBSCAN(min_samples=10,eps=3)
pred=clf.fit_predict(y_test)

plt.figure(5)
plt.plot(t[pred==0],y_test[pred==0],'bx')
plt.plot(t[pred==1],y_test[pred==1],'ro')
plt.show

對於這種類型的異常值,過濾器應該可以工作。例如,移動平均線是一個過濾器,可以在趨勢/噪聲分解框架中應用: $$ T_i=\frac 1 n\sum_{k=0}^{n-1}x_{i-k} \N_i=x_i-T_i $$

當噪聲分量“太大”時,它表示異常值。

這是一個 Python 實現:

for i in np.arange(len(T)):
   T[i] = np.mean(y_test[np.max([0,i-m]):(i+1)])

plt.plot(t, T)
N = y_test[:,0] - T
plt.figure()
plt.plot(t,N)
plt.show()

np.std(N)

您的系列情節與趨勢: 在此處輸入圖像描述

噪聲圖: 在此處輸入圖像描述

如您所見,噪聲分量在異常值處躍升至 30,而噪聲的標準差約為 4。您還可以計算噪聲的移動窗口色散,並在噪聲超出運行波動率時檢測異常值。

此過濾器與稱為Grubbs的異常值測試非常相似。在這裡,我使用移動窗口作為 Grubbs 測試中的示例。

引用自:https://stats.stackexchange.com/questions/427327

comments powered by Disqus