【機械学習】Jubatusを使ってみた

Jubatusは機械学習のフレームワークです。

jubatus
photo by jubat.us

Features

Jubatusは 2014/09/07 時点でバージョンは 0.62 です。
特徴は大きく以下の3つのようです。

  • リアルタイム処理
  • バッチ型機械学習並の学習精度
  • 分散処理

早速インストールしてみます。

Install

環境は Ubuntu12.04 (32bit)です。shellのインストーラは上手く行きませんでした。

$ ./install.sh
$ ./install_python.sh

32bit版はサポートしていないのかもしれないです。
今回はソースからインストールする事にしました。

# 前準備
$ sudo apt-get install build-essential git-core pkg-config
$ sudo apt-get install libmsgpack-dev libonig-dev liblog4cxx10-dev

# jubatus_mpio
$ mkdir -p jubatus/src
$ cd jubatus/src
$ wget https://download.jubat.us/files/source/jubatus_mpio/jubatus_mpio-0.4.1.tar.gz
$ tar xzf jubatus_mpio-0.4.1.tar.gz
$ cd jubatus_mpio-0.4.1
$ ./configure && make && sudo make install

# jubatus_msgpack
$ wget https://download.jubat.us/files/source/jubatus_msgpack-rpc/jubatus_msgpack-rpc-0.4.1.tar.gz
$ tar xzf jubatus_msgpack-rpc-0.4.1.tar.gz
$ cd jubatus_msgpack-rpc-0.4.1
$ ./configure && make && sudo make install

# Jubatus-core
$ wget -O jubatus_core.tar.gz https://github.com/jubatus/jubatus_core/archive/master.tar.gz
$ tar xzf jubatus_core.tar.gz
$ cd jubatus_core-master
$ ./waf configure && ./waf build &&  sudo ./waf install
$ sudo ldconfig

# Jubatus
$ wget -O jubatus-master.tar.gz https://github.com/jubatus/jubatus/archive/master.tar.gz
$ tar xzf jubatus-master.tar.gz
$ cd jubatus-master
$ ./waf configure && ./waf build &&  sudo ./waf install
$ sudo ldconfig

依存ライブラリのバージョンに引きずられそう…

Classifier / Recommender を使ってみた

Jubatusの機能は以下です。

  • Classifier
  • Recommender
  • Regression
  • Graph
  • Stat

Classifier

試しに入力に対して出力を多値分類する機能であるClassifierのサンプルコードを実行してみます。

Python-clinetをインストールします。

$ sudo pip install jubatus
$ jubaclassifier --configpath shogun.json &
$ lsof -i:9199
COMMAND    PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
jubaclass 2246 tatsuya    6u  IPv4  13514      0t0  TCP *:9199 (LISTEN)
$ python shogun.py 
徳川 慶喜
足利 義昭
北条 守時

client = jubatus.Classifier(host, port, name)でclientオブジェクトを生成して,client.train(train_data)で学習,client.classify([d])で分類を行います。

学習に関する設定は設定ファイル(json)で行います。
サポートされている学習手法はperceptron, PA, PA1, PA2, CW ,AROW ,NHERDでmethodで指定します。
特徴抽出の設定はconverterで行います。例題ではn-gramに設定されています。
学習時のパラメータregularization_weightはparameterで設定できます。これは使用ケースによって適切な値は変わってきます。

{
  "method": "CW",
  "converter": {
    "num_filter_types": {},
    "num_filter_rules": [],
    "string_filter_types": {},
    "string_filter_rules": [],
    "num_types": {},
    "num_rules": [],
    "string_types": {
      "unigram": { "method": "ngram", "char_num": "1" }
    },
    "string_rules": [
      { "key": "*", "type": "unigram", "sample_weight": "bin", "global_weight": "bin" }
    ]
  },
  "parameter": {
    "regularization_weight" : 1.0
  }
}

例題では結果は max(res[0], key=lambda x: x.score) によりscoreが最大になるresを予測結果としています。
次に, 試しに手元のTODO管理サービスで登録したタスクのカテゴリ, それに対する内容をdatasetとして学習させ, 単語からどのカテゴリに分類されるかの予測を行ってみます。
特徴量は事前にmecabで単語分解した名詞句としました。学習に使用したデータ数は737個です。

dataset = [{'token': u'JavaScriptPromise', 'label': u'web'}, {'token': u'Qiita', 'label': u'web'}, ...]

今回はお試しということで stopword が多く入ってしまっているのには目をつぶりました。
分類結果は以下の通りになりました。webで登録したタスクが多いのに対して, shoppingで登録したタスクが少ないのが結果に表れています。

estimate_result{label: web, score: 4.82648277283} : web JavaScript
estimate_result{label: personal, score: 0.542537629604} personal バナナ
estimate_result{label: web, score: 1.23609662056} :  web Blog
estimate_result{label: web, score: 1.79979705811} :  web Qiita
estimate_result{label: web, score: 1.82443261147} :  web アンドロイド
estimate_result{label: shopping, score: 0.0} :  shopping 横浜
estimate_result{label: web, score: 2.01594114304} :  web ファミリーマート

続いて, 特徴抽出自体は jubatus に任せてみます。単語分解せずに124個の文書をそのまま入れてみました。

estimate_result{label: web, score: 5.48305892944} web JavaScript
estimate_result{label: personal, score: 0.986351072788} personal バナナ
estimate_result{label: web, score: 0.847658574581} web Blog
estimate_result{label: web, score: 2.22040104866} web Qiita
estimate_result{label: personal, score: 0.511609315872} personal アンドロイド
estimate_result{label: shopping, score: 0.0} shopping 横浜
estimate_result{label: book, score: 0.656536340714} book ファミリーマート

妥当な結果だと思います。学習データでshoppingに属するタスクが少ないのでdatasetの問題。

Recommender

Recommenderを試してみます。methodは”inverted_index”,”minhash”,”lsh”, “euclid_lsh”,”nearest_neighbor_recommender”が使えます。

{
  "converter" : {
    "string_filter_types": {},
    "string_filter_rules":[],
    "num_filter_types": {},
    "num_filter_rules": [],
    "string_types": {},
    "string_rules":[
      {"key" : "*", "type" : "str", "sample_weight":"bin", "global_weight" : "bin"}
    ],
    "num_types": {},
    "num_rules": [
      {"key" : "*", "type" : "num"}
    ]
  },
  "parameter" : {
    "hash_num" : 128
    },
  "method": "lsh"
}

movielensのdatasetsはサイズが大きいので,u.dataだけ取ってきます。

# movielens
$ mkdir -p dat/ml-100k
$ cd dat/ml-100k
$ wget https://files.grouplens.org/datasets/movielens/ml-100k/u.data
$ cd -
$ jubarecommender -f config.json &
$ cd python
$ python ml_update.py
$ python ml_analyze.py

update_row(0: string id, 1: datum row)でモデルを更新してsimilar_row_from_id(0: string id, 1: uint size)であるユーザに近いscoreのユーザを取得します。


user  942  is similar to : ['id_with_score{id: 942, score: 1.0}', 'id_with_score{id: 430, score: 0.6640625}', 'id_with_score{id: 85, score: 0.65625}', 'id_with_score{id: 867, score: 0.6484375}', 'id_with_score{id: 839, score: 0.6484375}', 'id_with_score{id: 488, score: 0.6484375}', 'id_with_score{id: 591, score: 0.640625}', 'id_with_score{id: 370, score: 0.640625}', 'id_with_score{id: 841, score: 0.6328125}', 'id_with_score{id: 567, score: 0.6328125}']

他のRecommenderサンプルであるnpb_similar_playerもmovielensと同じ仕組みです。

Nodejs-clientを試す

jubatus-node-clientを試してみます。
clinetのコードはtutorial.jsを参考に。

# node 0.10.31
npm install jubatus-node-client
curl -O https://people.csail.mit.edu/jrennie/20Newsgroups/20news-bydate.tar.gz
tar -xvzf 20news-bydate.tar.gz

# server
jubaclassifier --configpath=config.json --name=tutorial &

# client
node tutorial.js
2014-09-11 23:17:44,033 8137 INFO  [server_base.cpp:129] starting save to /tmp/10.0.2.15_9199_classifier_tutorial.jubatus
2014-09-11 23:17:44,033 8137 INFO  [server_base.cpp:172] saved to /tmp/10.0.2.15_9199_classifier_tutorial.jubatus
2014-09-11 23:17:44,034 8136 INFO  [server_base.cpp:52] starting load from /tmp/10.0.2.15_9199_classifier_tutorial.jubatus
2014-09-11 23:17:44,034 8136 INFO  [server_base.cpp:74] loaded from /tmp/10.0.2.15_9199_classifier_tutorial.jubatus

jubatus-node-client に限ったことではありませんが, 0.11.xx以降ではV8のAPIが変わっているのでそのままでは動きません。

ML関連ライブラリ

他に試してみたいML関連のライブラリは以下です。

eblearn

eblearnはC++実装のCNNによる学習・推論を行うライブラリです。

Theano

Theanoは主にdeep learning用のPython数値計算ライブラリです。
PythonではNumpyが数値計算ライブラリの事実上の標準となっていますが, TheanoではNumpyのように計算手続きを関数型言語の特徴を取り入れています。
使い方はqiitaこちらを参考に。

pylearn2

deep learningライブラリのPylearn2はTheanoがベースになっています。(github)

cuda-convnet

cuda-convnetはCNNの推論・学習ライブラリです。
eblearnと違いプーリングの種類が豊富で色空間も変更でき局所コントラスト正規化も実装されています。


[1] Jubatus概要
[2] メディアデータ検知
[3] Jubatusアーキテクチャ
[4] Jubatus0.60の機能
[5] 機械学習のテスト
[6] リアルタイム分散処理
[7] opencv連携
[8] Jubatusの今後