今回はデータの流れから特定のパターンを見つける話です。(勉強中です)
はじめに
Milkcocoaのトップページでは、オフィスに置いている照度センサーの値を表示しています。
当然電気をつけたり消したりすると変化します。(今はリアルタイムでは動いてないみたいです)もともとはTechnical Rockstarsの東京オフィスの玄関に設置して、玄関から人が入るときに電気をつけるだろうという計算でした。なんにしろ何かしらの出来事と連動している可能性があるわけです。
東京オフィスの玄関に設置していたときは、ここからさらにslack通知をしてました。そのときに以下のようなコードを書いていました。
if(value - pre_value > 5) {
//電気がついた
}
当然これだとセンサーの種類や場合によって、いちいち書き直さないといけないわけで、いいやり方とは言えないと思うわけです。
今回のようなデータの流れの中でパターンを見つける場合に、どういうやり方があるんだろうと少し検索したところ、Dynamic time warpingという方法を見つけました。日本語だと動的時間伸縮法です。以下の記事が参考になりました。
ある系列が、お手本の系列に対して、どのくらい似ているかを計算できます。さらにグラフをマッチさせるときに、x軸側のスケールを考慮する感じですかね。
実際にDTWを使ってみたくなりました。
実装
npmでdtwモジュールを見つけたので、これを使ってみることにしました。
一旦MilkcocoaからHistory APIでデータを落としました。
var MilkCocoa = require('milkcocoa');
var milkcocoa = new MilkCocoa('teai9pn46zr.mlkcca.com');
var fs = require('fs');
var data = [];
var history = milkcocoa.dataStore('light').history();
history.sort('desc');
history.size(100);
history.limit(1000);
history.on('data', function(d) {
data = data.concat(d);
});
history.on('end', function() {
fs.writeFileSync('./data.json', JSON.stringify(data));
});
history.run();
Milkcocoaに保存されていた照度データを、ファイルにJSONで保存しました。
あとはゆっくり解析します。まずざっとデータを見て、電気をつけた感のあるデータの場所を抜き出しました。eventSeqにお手本のデータとして代入しておきます。それを全データと照合して、どれくらい似ているかを算出します。costが少ない方が似ています。costが一定以下のものを抜き出しました。costが一定以下なら、ドアが開いたと判断できます。
var DTW = require('dtw');
var fs = require('fs');
var dataStr = fs.readFileSync('./data.json');
var data = JSON.parse(dataStr).reverse().slice(300, 800);
calculate_cost(data.map(function(d) {return d.value.v;}));
var eventSeq = [4, 5, 6, 14, 10];
function calculate_cost(t) {
for(var i=0;i < t.length - 5;i++) {
calculate_cost_part(eventSeq, t.slice(i, i + 5), i);
}
}
function calculate_cost_part(s, t, index) {
var dtw = new DTW();
var cost = dtw.compute(s, t);
var path = dtw.path();
if(cost < 24) {
console.log(data[index].timestamp);
}
}
目で確認したかったので、照度データを青い線で折れ線グラフ化し、DTWにより算出したコストが一定以下だった部分に赤い印をつけています。このタイミングで電気をつけているわけですね。まあ、なんとなく合っているような。右側は夜ですね。
まとめ
実際はこの後でリアルタイムなイベント検知をしなければいけませんね。(今回は省きました。。)この方法だとお手本データを変えると、他の出来事にも応用できます。例えば電気を消したとか。他のデータセットにも、プログラムコードをほとんど変えずに使えます。データ解析は素人なので、変な部分があればコメントお願いします。
参考になりました<(_ _)>