RNNLM Toolkitを動かして、KenLMとPerplexity比較

RNNLM Toolkitを使ってみたよーって投稿を日本語では見かけなかったので、備忘録も兼ねて

#Recurrent Neural Network Language Model(RNNLM)

リカレントニューラルネットワークを利用した言語モデル
詳細はググって下さい(自分も勉強中)


#RNNLM Toolkit
Tomas Mikolov氏が開発したツールキット
[RNNLM Toolkit](http://www.fit.vutbr.cz/~imikolov/rnnlm/)
最新版は http://rnnlm.org/ に上がっているがページからしょっちゅうエラー返される


#ダウンロード

環境：CentOS7.2
とりあえずアクセスできるサイトに置いてある一番新しいのを持ってくる

```
$ mkdir rnnlm
$ cd rnnlm
$ wget http://www.fit.vutbr.cz/~imikolov/rnnlm/rnnlm-0.3e.tgz
$ tar zxvf rnnlm-0.3e.tgz
```

#インストール
Makefileがそのままだと動かなかったので書き換え

```file:makefile
#CC = x86_64-linux-g++-4.6 #コメントアウト                                                                                                                            
#CFLAGS = -lm -O2 -Wall -funroll-loops -ffast-math #コメントアウト                                                                                                    
#CFLAGS = -lm -O2 -Wall                                                                                                                               

CC = g++ #追加
CFLAGS = -lm -O2　#追加

all: rnnlmlib.o rnnlm

rnnlmlib.o : rnnlmlib.cpp
        $(CC) $(CFLAGS) $(OPT_DEF) -c rnnlmlib.cpp

rnnlm : rnnlm.cpp
        $(CC) $(CFLAGS) $(OPT_DEF) rnnlm.cpp rnnlmlib.o -o rnnlm

clean:
        rm -rf *.o rnnlm
```

その後、Make

```
$ make clean
$ make
```


#RNNLM学習

学習用、調整用、テスト用のコーパスを用意する(1行1文、分かち書きされたもの)
今回はntcir10の日本語特許文から学習用10万文(train100k.txt)、調整用5千文(valid5k.txt)、テスト用10万文(test100k.txt)を用意

```
$ time ./rnnlm -train train100k.txt -valid valid5k.txt -rnnlm rnnlm.hidden25.class300.model -hidden 25 -rand-seed 1 -debug 2 -class 300 -bptt 6 -bptt-block 10

debug mode: 2
train file: train100k.txt
valid file: valid5k.txt
class size: 300
Hidden layer size: 25
BPTT: 6
BPTT block: 10
Rand seed: 1
rnnlm file: rnnlm.hidden25.class300.model
Starting training using file train100k.txt
Vocab size: 74522
Words in train file: 6244514
Iter:   0       Alpha: 0.100000    TRAIN entropy: 6.8871    VALID entropy: 6.7309
Iter:   1       Alpha: 0.100000    TRAIN entropy: 6.5655    VALID entropy: 6.6412
Iter:   2       Alpha: 0.100000    TRAIN entropy: 6.4743    VALID entropy: 6.6185
Iter:   3       Alpha: 0.100000    TRAIN entropy: 6.4212    VALID entropy: 6.5830
Iter:   4       Alpha: 0.100000    TRAIN entropy: 6.3844    VALID entropy: 6.5716
Iter:   5       Alpha: 0.050000    TRAIN entropy: 6.3150    VALID entropy: 6.4327
Iter:   6       Alpha: 0.025000    TRAIN entropy: 6.2540    VALID entropy: 6.3519
Iter:   7       Alpha: 0.012500    TRAIN entropy: 6.2201    VALID entropy: 6.3012
Iter:   8       Alpha: 0.006250    TRAIN entropy: 6.2016    VALID entropy: 6.2673
Iter:   9       Alpha: 0.003125    TRAIN entropy: 6.1918    VALID entropy: 6.2513
```

出来上がったモデルのPerplexityを算出

```
$ time ./rnnlm -rnnlm rnnlm.hidden25.class300.model -test test100k.txt

test file: test100k.txt
rnnlm file: rnnlm.hidden25.class300.model

test log probability: -11721481.126285

PPL net: 76.748383
```

パラメータ説明

-rnnlm : 保存する言語モデルの名前
-hidden : 隠れ層のユニット数、多いほど性能が良くなる(ただし学習時間が遅くなる)
-class : untruncatedな語彙数、性能を求める場合1に設定するが、とても遅い(300~500推奨)
-bptt : Back Propagation Through Timeのステップ数(少なくとも6回推奨)


#実験

classを300、bpttを6に固定し、hiddenのみ変化させてRNNLMを構築し、Perplexityを算出

|hidden|Perplexity|time|
|:-:|:-:|:-:|
|25|76.7484|63m49.649s|
|50|62.7530|144m37.927s|
|75|57.3227|216m2.546s|
|100|53.0952|324m38.522s|
|150|49.8061|473m19.125s|
|200|47.0688|705m6.422s|
|300|44.6543|1139m2.378s|

隠れ層のユニット数増加に従って、Perplexityが減少することが確認できる
その分言語モデルの作成に時間がかかる(hidden=200で12時間弱)

RNNLMとの比較のため、KenLMにtrain100k.txtとvalid5k.txtを合わせたコーパスを学習させ、テストコーパスを用いてPerplexityを計測(結果だけ掲載)

|Perplexity|time|
|:-:|:-:|
|61.2690|28.1269s|

KenLMは構築時間が早い


#考察

RNNLMの隠れ層ユニット数が75のとき、KenLMのPerplexityを上回った
Deep Learning恐るべし…
ただ、構築時間がKenLMと比較してかなり掛かる