質問
時系列データに対する異常検知についての研究をしています。
ネットで色々調べた結果、
・外れ値検知
・異常部位検出
・変化点検知
などの手法があることがわかりました。
時系列データに対し、窓幅を設定しデータの異常を検知するということがしたいです。
(データ点ではなく部分時系列が異常かどうかを評価するということ)
手法を色々調べてK近傍法を使うとよいと書いてあったのですが、そこでいくつか質問があります。
・K近傍法を使う際、Kの適切な値を選択する方法はありますか。適当に決め打ちするしかないのでしょうか。
・異常度を計算しそれをtestデータとともにプロットするところまではできましたが、最終的に正常か異常かを判定するにはどうすればよいのでしょうか。
異常度の閾値を自分で設定して判定するということは考えましたが、閾値の設定の仕方もわからず困っています。
(ホテリング理論?を使って閾値の決定をすることを考えましたが元のデータが正規分布に従うのかどうかがわかりません。ちなみに元データは転倒検知をする際の、人の動きにおける3軸加速度です。)
自分なりにネットで調べましたが、部分時系列から異常を判定する記事が思ったよりも少なかった為質問させていただきました。
どなたかアドバイスを頂けたら幸いです。
長文失礼いたします。
補足情報(FW/ツールのバージョンなど)
Pythonを使って実装しています。
python
1import pandas as pd 2import numpy as np 3import matplotlib.pyplot as plt 4from sklearn.neighbors import NearestNeighbors 5 6 7''' 8dataをsize毎のスライス窓に分割 9''' 10 11def main(): 12 df = pd.read_csv("20191121.csv") 13 14 # 余分なデータをDataFrameから削除 15 df = df.drop(['name', 'x_rad/s', 'y_rad/s', 'z_rad/s'], axis=1) 16 17 df = df.set_index('time') 18 19 #x, y, z軸加速度を視認化 20 df.plot().legend(loc='upper left') 21 22 # 前から2480件のx軸加速度を学習データ、その次の2479件をテストデータとする 23 # # df.iloc[2479] ---> 53845130 24 # df.iloc[2480] ---> 53845150 25 train_data = df.loc[:53845130, 'x_ags'] 26 test_data = df.loc[53845150:, 'x_ags'].reset_index(drop=True) 27 28 # 窓幅 29 width = 30 30 31 # k近傍法のk 32 nk = 1 33 34 # 窓幅を使ってベクトルの集合を作成 35 train = embed(train_data, width) 36 test = embed(test_data, width) 37 38 # k近傍法でクラスタリング 39 neigh = NearestNeighbors(n_neighbors=nk) 40 neigh.fit(train) 41 42 # 距離を計算 43 d = neigh.kneighbors(test)[0] 44 45 # 距離の正規化 46 mx = np.max(d) 47 d = d / mx 48 49 # 訓練データ 50 plt.subplot(221) 51 plt.plot(train_data, label='Training') 52 plt.xlabel("Amplitude", fontsize=12) 53 plt.ylabel("Sample", fontsize=12) 54 plt.grid() 55 leg = plt.legend(loc=1, fontsize=15) 56 leg.get_frame().set_alpha(1) 57 58 # 異常度 59 plt.subplot(222) 60 plt.plot(d, label='d') 61 plt.xlabel("Amplitude", fontsize=12) 62 plt.ylabel("Sample", fontsize=12) 63 plt.grid() 64 leg = plt.legend(loc=1, fontsize=15) 65 leg.get_frame().set_alpha(1) 66 67 # 検証用データ 68 plt.subplot(223) 69 plt.plot(test_data, label='Test') 70 plt.xlabel("Amplitude", fontsize=12) 71 plt.ylabel("Sample", fontsize=12) 72 plt.grid() 73 leg = plt.legend(loc=1, fontsize=15) 74 leg.get_frame().set_alpha(1) 75 76 77def embed(lst, dim): 78 emb = np.empty((0, dim), float) 79 for i in range(lst.size - dim + 1): 80 tmp = np.array(lst[i:i+dim])[::-1].reshape((1, -1)) 81 emb = np.append(emb, tmp, axis=0) 82 return emb 83 84if __name__ == '__main__': 85 main()
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/08 06:01
2020/11/08 06:14 編集
2020/11/08 06:44
2020/11/09 05:28