こんばんは、ロードローラーです。
今日は変化点検出を試したので紹介します。
IoTでデータを取得できる場面は広がりました。特に多いのが正常/異常を検出したいといった取り組みですが、いずれも「What is 異常?」を定義できずに悩んでいるようです。
そんな状況で私が注目したのが変化点検出のChangeFinder。これは「具体的にはわからないけど何かしら変化があった。」という瞬間を検出をする処理です。閾値処理のように高周波な変化やノイズに反応しにくく、傾向の変化を捉えるので、サンプルデータを入手しにくく定義困難な異常の検出に向いています。
インストール方法
私が実行した環境はUbuntu14.04です。以下を実行すればOKです。
1 |
pip install changefinder |
が、しかし、これだけでは動かないこともあります。だいたいこのあたりを追加すれば動きます。(うろ覚えでスイマセン。。。)
1 2 3 |
<span class="go">pip install numpy</span> <span class="go">pip install scipy </span>pip install matplotlib |
サンプルソースと実行結果
ガウス分布で疑似的にデータを作り出してChangeFinderするサンプルがよく公開されてます。ソースと実行結果は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
※ChangeFinder.py import matplotlib.pyplot as plt import changefinder import numpy as np data=np.concatenate([ np.random.normal(0.6, 0.05, 300), np.random.normal(1.7, 0.05, 300), np.random.normal(0.5, 0.05, 300), np.random.normal(1.2, 0.05, 300) ]) cf = changefinder.ChangeFinder(r=0.01, order=1, smooth=7) ret = [] for i in data: score = cf.update(i) ret.append(score) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(ret) ax2 = ax.twinx() ax2.plot(data,'r') plt.show() |
赤色がデータ値、青色がChangeFinder結果。データ値(赤色)の高周波な変動には反応せず、元となるガウス分布が変化しときにChangeFinder(青色)が反応しているのがわかります。こういった「そもそものデータ発生源の傾向変化」は単純な閾値処理では検出できません。
手持ちのデータに適用してみた
これだけじゃ面白くないので適当に採取したデータにChangeFinderを実行してみました。csvファイルを読み込んで実行するようにpythonプログラムを少々変更しています。
123456789101112131415161718192021222324252627282930313233343536373839 ※ChangeFinderCSV.pyimport matplotlib.pyplot as pltimport changefinderimport numpy as npimport csvimport pandas as pdimport datetimedata=[]time=[]f = open('data20170422.csv', 'rb')dataReader = csv.reader(f)fieldnames = next(dataReader)for row in dataReader:#print rowdata.append(float(row[0]))time.append(datetime.time(int(row[5]),int(row[6]),0,0))cf = changefinder.ChangeFinder(r=0.01, order=1, smooth=15)ret = []for i in data:score = cf.update(i)ret.append(score)fig = plt.figure()#1画面フルに表示するax1 = fig.add_subplot(111)ax1.set_title('Change Finder')ax1.plot(time, ret, color = 'g', label='ChangeFinder')#ax2をax1に関連付けるax2 = ax1.twinx()ax2.plot(time,data,color = 'r', label = 'Noise')plt.subplots_adjust(hspace=0.7,bottom=0.2)plt.show()
対象データは、とある楽曲演奏時のdB値を加工したものです。イントロ⇒メロ⇒サビといった雰囲気の変化を「やかましさの傾向変化」でキャッチできないかなという実験です。
う~ん、微妙。。。07:00:00と22:00:00にサビで盛り上がる場面がくるのですが、捉えられているといえば捉えられてる・・・か??
ここから先はChangeFinderの3パラメータ調節が必要そうですね。このあたりはまた次回に調べてみます。
それではまた