質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

データマイニング

データマイニングは、購買履歴やクレジットカードの利用履歴、電話の通話履歴など企業にある大量のデータを解析して、その中に隠れたパターンやルールを探し出す技術です。DMと略されることもあります。

Q&A

解決済

1回答

4856閲覧

時系列データに対するK近傍法の閾値の決め方等

AI_engineer

総合スコア15

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

データマイニング

データマイニングは、購買履歴やクレジットカードの利用履歴、電話の通話履歴など企業にある大量のデータを解析して、その中に隠れたパターンやルールを探し出す技術です。DMと略されることもあります。

0グッド

0クリップ

投稿2020/11/08 02:16

編集2020/11/09 05:18

質問

時系列データに対する異常検知についての研究をしています。
ネットで色々調べた結果、
・外れ値検知
・異常部位検出
・変化点検知
などの手法があることがわかりました。
時系列データに対し、窓幅を設定しデータの異常を検知するということがしたいです。
(データ点ではなく部分時系列が異常かどうかを評価するということ)
手法を色々調べて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()

左上:訓練データ,左下:テストデータ,右上:異常度

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

K近傍法の分類の方法、K値の決め方については、以下が参考になるでしょう。

機械学習 〜 K−近傍法 〜

K値はいろいろ変えてみて、もっとも分類精度の高いものを採用しているようです。

ご質問のケース「部分時系列から異常を判定する」は、特徴量をどう見るかがポイントであると思います。すなわち、単純な3軸平均加速度だけでなく、短時間の動きの何を特徴とみなして、特徴量として採用するか(計算するか)に、いろいろと試行錯誤するエンジニアリング要素が詰められているように思います。例えば、3軸加速度が一定を超えたら測定頻度を一時的に上げて、ms単位の加速度の変化を収集し、それをフーリエ変換して・・・みたいな形で、たくさんの特徴量を得ることができそうです。特徴量をどう見るかでK近傍法の距離も変わってきますので、とても重要です。

その特徴量と正解データ(正常/異常)をもとに、K近傍法を用いるのか、ランダムフォレストを用いるのか、GBDTを用いるのか、は、また別の議論です。K近傍法に決めつけずに、いろいろ試してみるとよいと思います。なお、書籍「Kaggleで勝つデータ分析の技術」では、GBDTをほぼ万能な基本モデルと位置付けており、まずはGBDTを試してみることをオススメします。なお、ここまでの話でご理解いただけると思いますが、「時系列」という要素は特徴量エンジニアリングには考慮していますが、その後のモデル検討には考慮していません。こういった問題を**「時系列機械学習」であると決めつけて、ググったりしますと、間違った方向に進んでしまいます**ので、ご注意ください。

投稿2020/11/08 04:22

編集2020/11/08 04:23
toast-uz

総合スコア3266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AI_engineer

2020/11/08 06:01

回答ありがとうございます。 回答を拝見させていただき、K近傍法を用いる際、特徴量として何を設定するか、またK近傍法だけでなくGBDTなどの他の手法の検討をが大事ということがわかりました。 大変恐縮ですが、私自身機械学習を1か月前に初めて触れ知識がかなり浅い状態なので一度で理解することができませんでした。そこで補足質問をさせていただきたいのですが、 >「部分時系列から異常を判定する」は、特徴量をどう見るかがポイントであると思います。すなわち、単純な3軸平均加速度だけでなく、短時間の動きの何を特徴とみなして、特徴量として採用するか(計算するか)に、いろいろと試行錯誤するエンジニアリング要素が詰められているように思います。 私が今挑戦している研究は"熱中症による転倒検知"をテーマとしています。 熱中症によって転倒した際の"転倒時の3軸加速度"、"転倒後の硬直時間の3軸加速度"に注目して実際に転倒したか転倒していないかを判定するということが最終目標になっています。 私が機械学習に関して知識が浅く、特徴量等についていまいちわかっていないのですが、単純に3軸の加速度値だけで転倒を判断することは難しいのでしょうか。 もしそうなのであれば、どのような特徴量を設定するのか等の考え方を教えていただきたいです。 (通常の転倒であれば、日常生活中の加速度値の高い動作と転倒を区別をする必要がある為、加速度値以外に転倒時の角度等を判定に使用していましたが、熱中症による転倒であると転倒後の硬直時間ということが特徴的なので単純な加速度値だけで判断できるのではと考えました。) GBDTについては聞いたこともなかったので調べてみようと思います。 アドバイスありがとうございます。
toast-uz

2020/11/08 06:14 編集

特徴量として何を用いれば良いかは、機械学習以前に該当のドメイン知識が重要です。私自身は、一般論として、「転倒」と「しゃがみ込み」の区別が、単純な最大加速度や平均加速度では難しいのでは、ということから、いろいろ試してみるべきでは、というくらいで表現しました。「熱中症での転倒」でのドメインについて質問者様は知識が豊富そうですので、その知見のもと、いろいろ組み合わせて結果をチューニングしいてけばよいと思います。なお、測定可能であれば、周辺気温や体表面温度なども特徴量に入れるとよいかもです。
toast-uz

2020/11/08 06:44

あと、紹介した手法以外では、1次元CNNがアナログ波形の分類には有効である可能性があります。余裕があれば、試してみてください。
AI_engineer

2020/11/09 05:28

補足ありがとうございます。 1次元CNNについても調べてできそうであれば実装してみたいと思います。 新たにk近傍法について質問をさせて頂いたのでもしよろしければ回答の方をよろしくお願いいたします。 (この質問の延長のようなものになっています。)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問