kagome で UniDic を使えるようにするまでの紆余曲折

相変わらずコツコツ作ってる Pure golang形態素解析kagome ですが,これまで IPA 辞書しか使えなかったんですけど,UniDic も使えるようになりました.

バイナリサイズは若干大きくなりますが,辞書内包にしているので,「使ってる辞書何だったけ?案件」がおこりにくく,デプロイも簡単です.

UniDic ?

UniDic は IPA 辞書より形態素単位が細かめに出来ています.また,収録されている形態素数も IPA 辞書より多くなってます.品詞体系も IPA とは若干異なります.細かめに切ってくれるので,検索向きかもしれません.

収録形態素
IPA 392126
UniDic 756463

(左)IPA 辞書では 魏/志/倭/人/伝 となってしまうのが,(右)UniDic だと 魏志/倭人/伝 ととれるように! (嬉しいか?

f:id:ikawaha:20160112112415p:plain:w300f:id:ikawaha:20160112111609p:plain:w300

ただ埋め込むだけ.しかし一筋縄ではいかない

kagome では,辞書を内包するために go-bindata を利用させてもらっています.これを使うと,いわゆるアセットデータをバイナリの中に組み込んで,普通のファイルのようにアクセスできます.古い記事ですが,こんな感じで使えます.go-bindata でコンパイル時にリソースを埋め込んじゃおう! - Qiita.go-bindata を使えば,アセットとして埋め込みたいファイルを 1ファイルの go ソースに変換してくれます.

UniDic も mecab 用にファイルが作られているので,辞書の項目数が若干違うだけで,辞書ビルド用のプログラムを少し変更するだけでビルドして動作するところまでは割とすぐ出来ました.しーかーしー,

$ git push origin feature/unidic_20160104
Counting objects: 24, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (20/20), done.
Writing objects: 100% (24/24), 75.96 MiB | 74.00 KiB/s, done.
Total 24 (delta 12), reused 0 (delta 0)
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: f53d265fe46a47bbef042562b153d189
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File internal/dic/data/bindata.go is 215.20 MB; this exceeds GitHub's file size limit of 100.00 MB
To git@github.com:ikawaha/kagome.git
 ! [remote rejected] feature/unidic_20160104 -> feature/unidic_20160104 (pre-receive hook declined)
error: failed to push some refs to 'git@github.com:ikawaha/kagome.git'

アセットファイルが 215M もあって github にあげようとすると拒否られる orz.知っていましたか?github は 50M以上のファイルをアップすると警告されて,100M以上のファイルは push 出来ないことを orz.しかもこれ,ある程度圧縮された状態で 215MB なのです.

「git-lfs を使えよ」と言われるのですが,git-lfs にファイルを置いたら go get 一発でインストールできなくなってしまう・・・.

詰んだ

go-bindata を改造する

golang のプログラムは,同一ディレクトリに入っていれば同じパッケージになるので,ファイルを細かく分割しても問題ないはず.215Mもあるファイルをエディタで切り出したりするのはしんどいので,go-bindata に手を入れました.きれいに分割するのは難しそうなので,とりあえず元ファイルの単位で出力するように手を入れます.

https://github.com/jteeuwen/go-bindata/compare/master...ikawaha:feature/separate_asset_body_20160105

これでもう一度アセット作り直して,これまで 1つだった bindata.go を 12個に分割して push.

-rw-r--r--@  1 john staff   6.5K  1 12 10:09 bindata.go
-rw-r--r--@  1 john staff   2.3K  1 12 10:09 bindata00.go
-rw-r--r--@  1 john staff   6.5M  1 12 10:09 bindata01.go
-rw-r--r--@  1 john staff    15M  1 12 10:09 bindata02.go
-rw-r--r--@  1 john staff    20M  1 12 10:09 bindata03.go
-rw-r--r--@  1 john staff   2.1M  1 12 10:09 bindata04.go
-rw-r--r--@  1 john staff   2.6K  1 12 10:09 bindata05.go
-rw-r--r--@  1 john staff   2.3K  1 12 10:09 bindata06.go
-rw-r--r--@  1 john staff    98M  1 12 10:09 bindata07.go
-rw-r--r--@  1 john staff    33M  1 12 10:09 bindata08.go
-rw-r--r--@  1 john staff    32M  1 12 10:09 bindata09.go
-rw-r--r--@  1 john staff   5.3M  1 12 10:09 bindata10.go
-rw-r--r--@  1 john staff   2.4K  1 12 10:09 bindata11.go
remote: warning: File internal/dic/data/bindata07.go is 97.71 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB

97M ぎりぎりセーフ!

というわけで

kagome で UniDic 使えるようになりました.

欠点は,辞書の初回ロードが遅いと云うことでしょうか...辞書データを圧縮しているので,解凍する時間がどうしても辞書ロード時に必要になってしまうのがオーバーヘッドになっています.辞書データ圧縮しないと速くはなるのですが,github にのせられなくなってしまうので go get 一発でインストールが実現できなくなってしまうという悲しみ.辞書データをもっと細切れにして github に push 出来ればいいのかもしれません.今後の課題です.

次に目指すは Neologd 対応ですかね.内包にするのは難しそうだな・・・.初回にダウンロードしてくるようにするとかだろうか・・・.

そんなわけで今年も紆余曲折していきたいと思います.