のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

Go言語を触ったことのない人間がSensorBeeを使ってみた Part1

Sponsored Links

本日はさくっとSensorBeeを使ってみました。

皆さんこんにちは
お元気ですか。連休でほっとしています。

今回はSensorBeeと呼ばれるライブラリを紹介します。
Machine Learningまでは流石に長過ぎるので、word countまでやってみました。

What is SensorBee

sensorbee.io

SensorBeeは特徴として以下の内容を兼ね揃えます。

Stateful

機械学習に有用な構造化されていない情報を取得し、ユーザが定義した機械学習のモデルを動作させることができます。
また、ChainerやJubatusに加え、その他SensorBeeで記載できるQueryによっても作成することができます。

Expressive

命令やクエリはBQLで書かれています。BQLはパワフルな言語で簡単に習得でき、SQLに似ています(確かに)。
BQLはスキーマレスで、JSONにかなり近い、データ構造となってます。

LightWeight

SensorBeeはLightweightで軽量です。30MBも必要ないので、Raspberry Piのような
小型であっても動作します。 しかしながら、very smallなデバイスには搭載するには十分ではありません。
将来的には、このようなデバイスにも動作させたいんだそうな。

Install

goを持ってない人はgoからのインストールが必要となります。

Go(Mac)

Go自体のインストールと環境変数となります。

$ brew install go
$ export GOROOT=/usr/local/opt/go/libexec
$ export GOPATH=$HOME/go
$ export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

SensorBeeのインストール

SensorBeeのインストールは簡単です。

$ go get gopkg.in/sensorbee/sensorbee.v0/...

Tutorial

これだけではなんのことかまるでわからないので、Tutorialを実施してみます。
まずは、データの取得と初期化を行います。

データの取得と初期化

$ go get github.com/sensorbee/tutorial/wordcount
$ mkdir wordcount
$ cp $GOPATH/src/github.com/sensorbee/tutorial/wordcount/config/* ./wordcount/
$ build.yaml	sensorbee.yaml	   wordcount.bql

ビルド用のコマンドとしてbuild_sensorbeeを使う必要があります。

$ go get gopkg.in/sensorbee/sensorbee.v0/cmd/build_sensorbee
$ cd wordcount/
$ build_sensorbee

build.yamlの内容は以下のようになります。

$ cat build.yaml
plugins:
  - github.com/sensorbee/tutorial/wordcount/plugin

サーバの起動

これでSensorBeeを使う準備ができました。
早速、SensorBeeのサーバを起動してみましょう。

$ ./sensorbee run
INFO[0000] Setting up the server context                 config={"logging":{"log_dropped_tuples":false,"min_log_level":"info","summarize_dropped_tuples":false,"target":"stderr"},"network":{"listen_on":":15601"},"storage":{"uds":{"params":{},"type":"in_memory"}},"topologies":{}}
INFO[0000] Starting the server on :15601

試しにcurlを投げてみましょう。以下のようなレスポンスが返ってくるはずです。

$ curl http://localhost:15601/api/v1/runtime_status
{"gomaxprocs":4,"goroot":"/usr/local/opt/go/libexec","goversion":"go1.5.3","hostname":"{host name}-Pro.local","num_cgo_call":1,"num_cpu":4,"num_goroutine":13,"pid":44076,"user":"Tereka","working_directory":"/Users/Tereka/Programing/Software/SensorBee/wordcount"}

まずは、topologyと呼ばれるものが必要になります。topologyは
RDBMSのデータベースに近いそうです。まずは、これを作成しましょう。

./sensorbee topology create wordcount

出力されているStreaming情報はBQLと呼ばれる文法を使うことで様々なことをすることができます。
まずは、stream(ストリーム)からデータを取得してみましょう。

wordcount> CREATE SOURCE sentences TYPE wc_sentences;
wordcount> SELECT RSTREAM * FROM sentences [RANGE 1 TUPLES];

BQN

はじめに

BQNはストリーム間の関連性のデータ命令と関係性を示した命令があります。(あってる?)
ストリームの処理単位を決定することができます。
ストリームの処理単位は以下のような構文で実施することができます。

[RANGE n TUPLES] or [RANGE n SECONDS]. [RANGE n TUPLES]

例えば、以下のように書けます。

SELECT RSTREAM * FROM sentences [RANGE 1 TUPLES];

STREAMは3種類あります。

Stream 説明
RSTREAM 新しいtupleが到着した時に結果を更新する。(処理をする)
ISTREAM 到着したtupleのみ更新し、以前までの時刻は更新しない。(処理をしない)
DSTREAM 解説plz
SELECT文

まずは、SELECT文 SQLと殆ど同じ書き方です。

wordcount> SELECT RSTREAM name FROM sentences [RANGE 1 TUPLES];
{"name":"isabella"}
{"name":"isabella"}
{"name":"isabella"}
{"name":"jacob"}
{"name":"sophia"}
WHERE文

これも殆ど同じではないだろうか。
WHERE name = "sophia"の部分で、フィルタリングをかけています。

wordcount> SELECT RSTREAM * FROM sentences [RANGE 1 TUPLES] WHERE name = "sophia";
{"name":"sophia","text":"in velit commodo cillum cillum consequat proident dolore ut"}
{"name":"sophia","text":"in aute aliqua irure anim sit et"}
{"name":"sophia","text":"mollit sunt commodo id id commodo esse sit"}
{"name":"sophia","text":"cillum magna aute tempor eu velit"}
GROUP BY

SQLのGROUP BYと似たような使い方です。出力は名前が以前+今回で何回出てきたかをcountで出力しているようですね。

wordcount> SELECT ISTREAM name, count(*) FROM sentences [RANGE 60 SECONDS]
    GROUP BY name;
{"count":1,"name":"jacob"}
{"count":1,"name":"sophia"}
{"count":2,"name":"sophia"}
{"count":1,"name":"isabella"}
{"count":2,"name":"isabella"}

ストリームの作成

既にあるストリームから、新しいストリームを作成することができます。
sentencesを処理して新しいwordsと呼ばれるストリームを作成しています。

wordcount> CREATE STREAM words AS SELECT RSTREAM name, text AS word FROM wc_tokenizer("sentences", "text") [RANGE 1 TUPLES];
wordcount> SELECT RSTREAM * FROM words [RANGE 1 TUPLES];
{"name":"isabella","word":"proident"}
{"name":"isabella","word":"id"}
{"name":"isabella","word":"eu"}
{"name":"isabella","word":"laboris"}
{"name":"isabella","word":"sunt"}

これを使うと、以下のようにしてword countを実施することができます。

wordcount> SELECT ISTREAM word, count(*) FROM words [RANGE 60 SECONDS] GROUP BY word;
{"count":1,"word":"culpa"}
{"count":1,"word":"sunt"}
{"count":1,"word":"occaecat"}
{"count":1,"word":"ullamco"}
{"count":1,"word":"ut"}
{"count":1,"word":"consequat"}
{"count":1,"word":"minim"}
{"count":1,"word":"aute"}

それぞれのワードのカウント最大数と最小数を求めています。
また、以下のBQNによって、出現ワードの最大回数、最小回数を算出することができます。

wordcount> CREATE STREAM word_counts AS
    SELECT ISTREAM word, count(*) FROM words [RANGE 60 SECONDS]
    GROUP BY word;
wordcount> SELECT RSTREAM max(count), min(count)
    FROM word_counts [RANGE 60 SECONDS];
{"max":8,"min":8}
{"max":8,"min":5}
{"max":8,"min":5}
{"max":11,"min":5}
{"max":11,"min":5}

これで、ワードのカウントをSensorBeeで実施するチュートリアルを完走しました。
チュートリアルが半分残っているので時間に余裕があれば、Part2やります。
間違ってたら後で修正かけます。。