Python
時間序列的簡單異常值檢測
我想為時間序列生成一個非常簡單的異常檢測示例。所以我用一個非常明顯的異常值創建了樣本數據。這是數據的圖片:
問題是,到目前為止,我還沒有任何方法可以可靠地檢測異常值。我嘗試了局部異常因子、隔離森林、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 測試中的示例。