V8パッケージを使ってRからRakuten MAを呼び出してみる

# 概要
　[VRにbot,OS,形態素解析にディープラーニングまで！JavaScriptの限界を超えた鉄人達の変態的所業まとめ](https://bita.jp/dml/crazyjstools)を読み、RからJavascriptが呼べたらもっと変態なのかなと思ったのでやってみました。
　調べてみると{V8}というパッケージがあったので、JavaScriptで書かれた形態素解析器Rakuten MAが使えるか試してみました。
　{V8}とRakuten MAについては下記をご参考ください。

- [V8: Embedded JavaScript Engine for R](https://cran.r-project.org/web/packages/V8/index.html)
- [GitHub - jeroenooms/V8](https://github.com/jeroenooms/V8)
- [Rakuten MA - morphological analyzer (word segue
n- tor + PoS Tagger) for Chinese and Japanese written purely in JavaScript](https://github.com/rakuten-nlp/rakutenma)
- [RakutenMAによる形態素解析入門](http://antibayesian.hateblo.jp/entry/2015/01/08/085741)


# 事前準備
 必要なNode.jsのパッケージをインストールし、RakutenMAを参照するrequireメソッドを含む.jsをbrowserifyでコンパイルしておく。

```shell:パッケージインストール
$ npm install rakutenma
$ npm install js-beautify

# パッケージがインストールされたパスを確認
# 自分のMac環境ではホーム直下のnode_modules以下にインストールされている
$ npm config get prefix
```

```shell:browserify
# {V8}のVignetteにある通りにする（var RakutenMAにするとR実行部で" ReferenceError: RakutenMA is not defined"）
$ echo "global.RakutenMA = require('$HOME/node_modules/rakutenma/');" > in.js
$ browserify in.js -o RakutenMAbundle.js

# モデルファイルの切り替えられるようにモデルファイルの.jsを分けて作っておく
$ echo "global.model = require('$HOME/node_modules/rakutenma/model_ja.json');" > in.js
browserify in.js -o Modelbundle.js
$ browserify in.js -o Modelbundle.js
```

# R実行部
　browserifyで作成した.jsファイルを`V8::source`で読み込む。

```R:R側準備
library(stringr)
library(V8)

ct <- V8::v8()
ct$source(file = stringr::str_c(Sys.getenv("HOME"), "RakutenMAbundle.js", sep = "/"))
ct$source(file = stringr::str_c(Sys.getenv("HOME"), "Modelbundle.js", sep = "/"))

# グローバル環境を確認
> ct$get(V8::JS('Object.keys(global)'))
 [1] "console"      "print"        "global"       "ArrayBuffer"  "Int8Array"    "Uint8Array"  
 [7] "Int16Array"   "Uint16Array"  "Int32Array"   "Uint32Array"  "Float32Array" "Float64Array"
[13] "DataView"     "RakutenMA"    "model" 
```

　RakutenMAのdemo.jsにある通りに実行していく。

```R:形態素解析
# 事前学習されたモデルを読み込んで、RakutenMAインスタンスを生成
ct$eval(src = V8::JS('var rma = new RakutenMA(model, 1024, 0.007812);'))

# 素性については下記を参考
# https://github.com/rakuten-nlp/rakutenma#supported-feature-templates
> ct$eval(src = V8::JS('rma.featset = RakutenMA.default_featset_ja;'))
[1] "c0,w0,w1,w9,w2,w8,b1,b9,b2,b8,c1,c9,c2,c8,c3,c7,d1,d9,d2,d8"

# Set the feature hash function (15bit)
ct$eval(src = V8::JS('rma.hash_func = RakutenMA.create_hash_func(15);'))

# 例文を形態素解析
ct$eval(src = V8::JS('var rs = rma.tokenize("うらにわにはにわにわとりがいる")'))
> ct$get(name = "rs")
     [,1]           [,2]  
[1,] "うらにわ"     "N-nc"
[2,] "に"           "P-k" 
[3,] "は"           "P-rj"
[4,] "にわにわとり" "N-nc"
[5,] "が"           "P-k" 
[6,] "いる"         "V-dp"
```

- [POSタグリスト](https://github.com/rakuten-nlp/rakutenma#pos-tag-list-in-japanese-and-correspondence-to-bccwj-tags)より抜粋

| タグ  | 対応する BCCWJ 品詞名 |
| ---  | ---------------- |
| N-n  | 名詞-名詞的        |
| N-nc | 名詞-普通名詞      |
| P-k  | 助詞-格助詞        |
| P-rj | 助詞-係助詞        |
| V-c  | 動詞-一般         |
| V-dp | 動詞-非自立可能    |

　そのままのモデルだとうまくいっていないので、モデルを再学習させる。

```R:モデルの再学習
ct$eval(src = V8::JS(
  'res = rma.train_one(
    [
      ["うらにわ","N-nc"],
      ["に","P-k"],
      ["は","P-rj"],
      ["にわ","N-n"],
      ["にわとり","N-nc"],
      ["が","P-k"],
      ["いる","V-c"]
    ]
  );')
)

# 形態素解析の再実行
ct$eval(src = V8::JS('var rs = rma.tokenize("うらにわにはにわにわとりがいる")'))
> ct$get(name = "rs")
     [,1]       [,2]  
[1,] "うらにわ" "N-nc"
[2,] "に"       "P-k" 
[3,] "は"       "P-rj"
[4,] "にわ"     "N-n" 
[5,] "にわとり" "N-nc"
[6,] "が"       "P-k" 
[7,] "いる"     "V-dp"
```

　学習した結果が反映されています。

--- 

# まとめ
　{V8}パッケージを用いてJavaScriptで書かれた形態素解析器Rakuten MAをRから呼び出せるか確認したところ、デモと同じ結果が出てきており、見たところ動作はしているようです。とはいえ、もっと適したJavaScriptの書き方があるでしょうから、折を見て学習していこうと思います。

　{V8}の活用により、JavaScriptの可視化以外のパッケージもRから有効利用できるようになりました。これで{Rcpp}でMeCabとKyTeaが呼び出せて、{rJava}でkuromojiが呼び出せて、{PythonInR}でChainer/scikit-learnなどが使えます。とても変態ですね。
　続けてJuman/KNPもいきたいところですが、なかなかどうして難しいものです。Juman++に期待したいですが、こちらもなかなかどうして難しいものですね。
　進捗、がんばります。


## 参考
- [Using NPM packages in V8](https://cran.r-project.org/web/packages/V8/vignettes/npm.html)
- [Browserify](http://browserify.org) 
- [Browserify: それはrequire()を使うための魔法の杖](http://qiita.com/cognitom/items/4c63969b5085c90639d4)
- [JUMAN++ (a Japanese Morphological Analyzer)](https://github.com/ku-nlp/jumanpp)
- [RNNLMベースの形態素解析器 JUMAN++ をhomebrewでインストールできるようにした](http://chezou.hatenablog.com/entry/2016/10/15/162047)


### 実行環境
```r:実行環境
> devtools::session_info()
Session info ----------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.3.1 (2016-06-21)
 system   x86_64, darwin13.4.0        
 ui       RStudio (0.99.903)          
 language (EN)                        
 collate  ja_JP.UTF-8                 
 tz       Asia/Tokyo                  
 date     2016-10-20                  

Packages --------------------------------------------------------------------------------------------
 package    * version date       source                            
 assertthat   0.1     2013-12-06 CRAN (R 3.3.1)                    
 curl         1.2     2016-08-13 cran (@1.2)                       
 DBI          0.5     2016-08-11 cran (@0.5)                       
 devtools     1.12.0  2016-06-24 CRAN (R 3.3.0)                    
 digest       0.6.9   2016-01-08 CRAN (R 3.3.0)                    
 dplyr        0.5.0   2016-06-24 CRAN (R 3.3.1)                    
 jsonlite     1.0     2016-07-01 CRAN (R 3.3.0)                    
 magrittr     1.5     2014-11-22 CRAN (R 3.3.1)                    
 memoise      1.0.0   2016-01-29 CRAN (R 3.3.0)                    
 R6           2.1.3   2016-08-19 cran (@2.1.3)                     
 Rcpp         0.12.7  2016-09-05 cran (@0.12.7)                    
 rsconnect    0.4.3   2016-08-13 Github (rstudio/rsconnect@1665cb8)
 stringi      1.1.1   2016-05-27 CRAN (R 3.3.1)                    
 stringr    * 1.1.0   2016-08-19 cran (@1.1.0)                     
 tibble       1.2     2016-08-26 cran (@1.2)                       
 V8         * 1.0.3   2016-06-28 CRAN (R 3.3.0)                    
 withr        1.0.2   2016-06-20 CRAN (R 3.3.0)     
```