Lucene Kuromojiとの組み合わせで、時々エントリを書いていますmecab-ipadic-NEologdですが、以前Kuromoji(Atilika)との組み合わせでは失敗したことがあります。
Kuromoji(Atilika)に、mecab-ipadic-neologdの辞書を適用できない?という話
http://d.hatena.ne.jp/Kazuhira/20150318/1426690374
Kuromoji
http://www.atilika.org/
Kuromoji(GitHub)
https://github.com/atilika/kuromoji
で、このAtilikaのKuromojiなのですが、最近更新が活発なようで、masterブランチは0.9系になっています。
AtilikaのMavenリポジトリには、相変わらず0.7.7しかないのですが。
http://www.atilika.org/nexus/content/repositories/atilika/org/atilika/kuromoji/kuromoji/
0.8系はどうしましたか?
で、0.9系だとKuromojiのモジュール構成も変わっていて更新も頻繁に行われているので、今NEologdを適用すると結果も変わるのかな?と思い、再度チャレンジしてみました。
結果からいくと、適用できました。ちょっと辞書を修正すれば。
対象は、IPA辞書とUniDicとします。
最初の準備として、KuromojiのソースコードをGitHubからCloneしておきましょう。
$ git clone https://github.com/atilika/kuromoji.git
あとは、それぞれに対してNEologdを組み込んでビルドしてみます。
Kuromoji 0.9 × mecab-ipadic-NEologdでビルドする
まずは、Kuromojiとmecab-ipadic-NEologdの組み合わせから。
mecab-ipadic-NEologdをCloneしてきて、CSV辞書を作成します。
$ git clone https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ libexec/make-mecab-ipadic-neologd.sh
今回、mecab-ipadic-NEologdの辞書の日付は「20150810」でした。
先ほどCloneしたKuromojiのリポジトリへ移動し
$ cd /path/to/kuromoji
$ mkdir kuromoji-ipadic/dictionary $ cp -R /path/to/mecab-ipadic-neologd/build/mecab-ipadic-2.7.0-20070801-neologd-20150810 kuromoji-ipadic/dictionary
対象のプロジェクトは、「kuromoji-ipadic」です。
ビルドを行う前に、コンパイル時のヒープを広げておきます。
$ export MAVEN_OPTS='-Xmx4g'
前は2Gでよかったのですが、今は3Gでも足りませんでした。NEologdが成長していますね。
で、ビルド。
$ mvn -pl kuromoji-ipadic -am package \ -DskipTests=true \ -DskipDownloadDictionary=true \ -Dkuromoji.dict.dir=kuromoji-ipadic/dictionary/mecab-ipadic-2.7.0-20070801-neologd-20150810 \ -Dkuromoji.dict.encoding=utf-8
追記)
20150810日付以前のNEologdでは、Kuromojiに組み込む際に失敗しますが、20150817以降であれば修正いただいたので大丈夫です。
@kazuhira_r いつもお世話になってます。二重引用符のエスケープすり抜けている経路があったので、今回の更新で修正しました。ご指摘ありがとうございました!!
2015-08-17 17:28:55 via TweetDeck to @kazuhira_r
対応いただいた、@overlastさん、ありがとうございました!
追記、ここまで)
失敗…。
java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.RuntimeException: Unmatched quote in entry: ANIME FES.“VS”,1288,1288,5229,名詞,固有名詞,一般,*,*,*,ANIME FES.“VS",アニメフェスバーサス,アニメフェスバーサス at com.atilika.kuromoji.util.DictionaryEntryLineParser.parseLine(DictionaryEntryLineParser.java:64) at com.atilika.kuromoji.ipadic.compile.TokenInfoDictionaryCompiler.parse(TokenInfoDictionaryCompiler.java:35) at com.atilika.kuromoji.ipadic.compile.TokenInfoDictionaryCompiler.parse(TokenInfoDictionaryCompiler.java:27) at com.atilika.kuromoji.compile.AbstractTokenInfoDictionaryCompiler.analyzeTokenInfo(AbstractTokenInfoDictionaryCompiler.java:64) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.buildTokenInfoDictionary(AbstractDictionaryCompiler.java:48) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.build(AbstractDictionaryCompiler.java:38) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.build(AbstractDictionaryCompiler.java:163) at com.atilika.kuromoji.ipadic.compile.DictionaryCompiler.main(DictionaryCompiler.java:33) ... 6 more
なんか、CSVに「"」(二重引用符)が半端に入っているような…。
ANIME FES.“VS"
仕方ないので、ここは「"」を「”」に変換しておきます。
※繰り返しになりますが、この手順はNEologdが20150817以降であれば不要です
$ perl -wpi -e 's!"!”!g' kuromoji-ipadic/dictionary/mecab-ipadic-2.7.0-20070801-neologd-20150810/*.csv
再度、ビルド。
$ mvn -pl kuromoji-ipadic -am package \ -DskipTests=true \ -DskipDownloadDictionary=true \ -Dkuromoji.dict.dir=kuromoji-ipadic/dictionary/mecab-ipadic-2.7.0-20070801-neologd-20150810 \ -Dkuromoji.dict.encoding=utf-8
今度は成功しました。
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ kuromoji-ipadic --- [INFO] Building jar: /path/to/kuromoji/kuromoji-ipadic/target/kuromoji-ipadic-0.9-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] Kuromoji ........................................... SUCCESS [ 0.003 s] [INFO] Kuromoji Common .................................... SUCCESS [ 1.241 s] [INFO] Kuromoji IPADIC .................................... SUCCESS [07:20 min] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 07:21 min [INFO] Finished at: 2015-08-14T00:01:09+09:00 [INFO] Final Memory: 36M/3309M [INFO] ------------------------------------------------------------------------
やりましたね!前回はKuromojiのソースコードに細工をしないと、ビルドできなかったのに。
ビルド所要時間、7分ちょっと…。うちの環境でビルドしている時の比較ですが、Lucene Kuromojiの3倍以上かかってる感じです。
動作確認(Kuromoji × mecab-ipadic-NEologd)
それでは、動作確認してみましょう。動作確認用のプログラムは、このようなものを用意。
sample_ipadic_neologd.groovy
import com.atilika.kuromoji.ipadic.Tokenizer def texts = ['すもももももももものうち', 'きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー!', '日本経済新聞でモバゲーの記事を読んだ', 'くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ', '艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム'] def tokenizer = new Tokenizer() texts.each { text -> println("$text") println(' [' + tokenizer.tokenize(text).collect { it.surfaceForm }.join(', ') + ']') }
Tokenizerのパッケージ名、辞書の名前が入るようになったんですね…。
import com.atilika.kuromoji.ipadic.Tokenizer
で、動かした結果。まずは、通常のIPA辞書のもので確認(別途ビルドしました)。
$ groovy -cp kuromoji/kuromoji-common/target/kuromoji-common-0.9-SNAPSHOT.jar:kuromoji/kuromoji-ipadic/target/kuromoji-ipadic-0.9-SNAPSHOT.jar sample_ipadic_neologd.groovy すもももももももものうち [すもも, も, もも, も, もも, の, うち] きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー! [きゃ, り, ー, ぱみゅぱみゅは, 、, 2012, 年, に, 「, つけ, ま, つける, 」, で, デビュー, !] 日本経済新聞でモバゲーの記事を読んだ [日本経済新聞, で, モバゲー, の, 記事, を, 読ん, だ] くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ [くり, ぃむしちゅ, ー, は, 、, 上田, 晋, 也, と, 有田, 哲, 平, の, 2, 人, から, なる, 日本, の, お笑い, コンビ] 艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム [艦隊, これ, くし, ょんは, 、, 角川, ゲームス, が, 開発, し, 、, DMM, ., com, が, 配信, し, て, いる, ブラウザゲーム]
続いて、mecab-ipadic-NEologd版。
※起動がちょっと重め
$ groovy -cp kuromoji/kuromoji-common/target/kuromoji-common-0.9-SNAPSHOT.jar:kuromoji/kuromoji-ipadic/target/kuromoji-ipadic-0.9-SNAPSHOT.jar sample_ipadic_neologd.groovy すもももももももものうち [すもももももももものうち] きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー! [きゃりーぱみゅぱみゅ, は, 、, 2012年, に, 「, つけまつける, 」, で, デビュー, !] 日本経済新聞でモバゲーの記事を読んだ [日本経済新聞, で, モバゲー, の, 記事, を, 読ん, だ] くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ [くりぃむしちゅー, は, 、, 上田, 晋也, と, 有田哲平, の, 2, 人, から, なる, 日本, の, お笑いコンビ] 艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム [艦隊これくしょん, は, 、, 角川ゲームス, が, 開発, し, 、, DMM.com, が, 配信, し, て, いる, ブラウザゲーム]
形態素解析結果が、大きく変わりましたね。OKそうです。
Kuromoji 0.9 × mecab-unidic-NEologdでビルドする
続いて、mecab-unidic-NEologdを使ってビルドしてみます。
なお、UniDicですが、Lucene版のKuromojiでは実はサポートしていません。こちらが使えるのは、Atilika Kuromojiのアドバンテージな気もします。
mecab-ipadic-NEologdの時と同じように、mecab-unidic-NEologdをCloneしてきてビルドします。
$ git clone https://github.com/neologd/mecab-unidic-neologd.git
$ cd mecab-unidic-neologd
$ libexec/make-mecab-unidic-neologd.sh
mecab-ipadic-NEologdとほぼ同じ手順です。
Kuromojiのディレクトリへ移り、
$ cd /path/to/kuromoji
ヒープを広げて
$ export MAVEN_OPTS='-Xmx4g'
$ mkdir kuromoji-unidic/dictionary $ cp -R /path/to/mecab-unidic-neologd/build/unidic-mecab-2.1.2_src-neologd-20150810 kuromoji-unidic/dictionary
今回の対象は、「kuromoji-unidic」です。
で、ビルド。
$ mvn -pl kuromoji-unidic -am package \ -DskipTests=true \ -DskipDownloadDictionary=true \ -Dkuromoji.dict.dir=kuromoji-unidic/dictionary/unidic-mecab-2.1.2_src-neologd-20150810
こちらも、コケてしまいました…。mecab-ipadic-NElogdの時と、同じ理由で。
java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.RuntimeException: Unmatched quote in entry: ANIME FES.“VS”,1288,1288,3861,名詞,固有名詞,一般,*,*,*,アニメフェスバーサス,ANIME FES.“VS",ANIME FES.“VS",アニメフェスバーサス,ANIME FES.“VS",アニメフェスバーサス,固,*,*,*,* at com.atilika.kuromoji.util.DictionaryEntryLineParser.parseLine(DictionaryEntryLineParser.java:64) at com.atilika.kuromoji.unidic.compile.TokenInfoDictionaryCompiler.parse(TokenInfoDictionaryCompiler.java:36) at com.atilika.kuromoji.unidic.compile.TokenInfoDictionaryCompiler.parse(TokenInfoDictionaryCompiler.java:28) at com.atilika.kuromoji.compile.AbstractTokenInfoDictionaryCompiler.analyzeTokenInfo(AbstractTokenInfoDictionaryCompiler.java:64) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.buildTokenInfoDictionary(AbstractDictionaryCompiler.java:48) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.build(AbstractDictionaryCompiler.java:38) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.build(AbstractDictionaryCompiler.java:163) at com.atilika.kuromoji.unidic.compile.DictionaryCompiler.main(DictionaryCompiler.java:34) ... 6 more
とりあえず、こちらも修正。
$ perl -wpi -e 's!"!”!g' kuromoji-unidic/dictionary/unidic-mecab-2.1.2_src-neologd-20150810/*.csv
リトライ。
$ mvn -pl kuromoji-unidic -am package \ -DskipTests=true \ -DskipDownloadDictionary=true \ -Dkuromoji.dict.dir=kuromoji-unidic/dictionary/unidic-mecab-2.1.2_src-neologd-20150810
で、またコケます…。
[WARNING] java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NumberFormatException: Value out of range. Value:"-38377" Radix:10 at java.lang.Short.parseShort(Short.java:120) at java.lang.Short.parseShort(Short.java:144) at com.atilika.kuromoji.unidic.dict.DictionaryEntry.<init>(DictionaryEntry.java:54) at com.atilika.kuromoji.unidic.compile.TokenInfoDictionaryCompiler.parse(TokenInfoDictionaryCompiler.java:37) at com.atilika.kuromoji.unidic.compile.TokenInfoDictionaryCompiler.parse(TokenInfoDictionaryCompiler.java:28) at com.atilika.kuromoji.compile.AbstractTokenInfoDictionaryCompiler.analyzeTokenInfo(AbstractTokenInfoDictionaryCompiler.java:64) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.buildTokenInfoDictionary(AbstractDictionaryCompiler.java:48) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.build(AbstractDictionaryCompiler.java:38) at com.atilika.kuromoji.compile.AbstractDictionaryCompiler.build(AbstractDictionaryCompiler.java:163) at com.atilika.kuromoji.unidic.compile.DictionaryCompiler.main(DictionaryCompiler.java:34) ... 6 more
今回は、事情が違うようです。
Kuromojiはコストをshortの範囲で表現しなくてはならないようで、今回はshortの下限を下回っているエントリが存在しています。
$ grep -E ',\-38377' kuromoji-unidic/dictionary/unidic-mecab-2.1.2_src-neologd-20150810/*.csv kuromoji-unidic/dictionary/unidic-mecab-2.1.2_src-neologd-20150810/mecab-unidic-user-dict-seed.20150810.csv:この歌を・・・・・・・・♪,1288,1288,-38377,名詞,固有名詞,一般,*,*,*,コノウタヲ,この歌を・・・・・・・・♪,この歌を・・・・・・・・♪,コノウタヲ,この歌を・・・・・・・・♪,コノウタヲ,固,*,*,*,*
Lucene Kuromojiでmecab-ipadic-NEologdと組み合わせた時も、絵文字のコストがshortの範囲を越えてビルドに失敗したことがあったなぁ…。
仕方がないので、今回はコストをshortの最小値に設定。
-32768
気を取り直して、再度ビルド。
$ mvn -pl kuromoji-unidic -am package \ -DskipTests=true \ -DskipDownloadDictionary=true \ -Dkuromoji.dict.dir=kuromoji-unidic/dictionary/unidic-mecab-2.1.2_src-neologd-20150810
今度は、OKでした!
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ kuromoji-unidic --- [INFO] Building jar: /path/to/kuromoji/kuromoji-unidic/target/kuromoji-unidic-0.9-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] Kuromoji ........................................... SUCCESS [ 0.002 s] [INFO] Kuromoji Common .................................... SUCCESS [ 1.072 s] [INFO] Kuromoji UniDic .................................... SUCCESS [10:14 min] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 10:15 min [INFO] Finished at: 2015-08-14T00:31:27+09:00 [INFO] Final Memory: 32M/3399M [INFO] ------------------------------------------------------------------------
ビルドに、約10分…。
動作確認(Kuromoji × mecab-unidic-NEologd)
ビルドしたKuromoji+mecab-unidic-NEologdで、動作確認。使ったプログラムは、こちら。
sample_unidic_neologd.groovy
import com.atilika.kuromoji.unidic.Tokenizer def texts = ['すもももももももものうち', 'きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー!', '日本経済新聞でモバゲーの記事を読んだ', 'くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ', '艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム'] def tokenizer = new Tokenizer() texts.each { text -> println("$text") println(' [' + tokenizer.tokenize(text).collect { it.surfaceForm }.join(', ') + ']') }
UniDicの場合のTokenizerのパッケージは、こちら。
import com.atilika.kuromoji.unidic.Tokenizer
で、動かした結果。こちらも、まずは通常のUniDicのもので確認(やっぱり、別途ビルドしました)。
$ groovy -cp kuromoji/kuromoji-common/target/kuromoji-common-0.9-SNAPSHOT.jar:kuromoji/kuromoji-unidic/target/kuromoji-unidic-0.9-SNAPSHOT.jar sample_unidic_neologd.groovy すもももももももものうち [すもも, も, もも, も, もも, の, うち] きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー! [きゃ, り, ー, ぱ, み, ゅ, ぱ, み, ゅ, は, 、, 2, 0, 1, 2, 年, に, 「, つけ, まつ, ける, 」, で, デビュー, !] 日本経済新聞でモバゲーの記事を読んだ [日本, 経済, 新聞, で, モバゲー, の, 記事, を, 読ん, だ] くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ [くりぃむ, しちゅー, は, 、, 上田, 晋也, と, 有田, 哲平, の, 2, 人, から, なる, 日本, の, お, 笑い, コンビ] 艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム [艦隊, これ, く, しょ, ん, は, 、, 角川, ゲーム, ス, が, 開発, し, 、, D, M, M, ., c, o, m, が, 配信, し, て, いる, ブラウザ, ゲーム]
続いて、mecab-unidic-NEologd版。
※起動がちょっと重め
$ groovy -cp kuromoji/kuromoji-common/target/kuromoji-common-0.9-SNAPSHOT.jar:kuromoji/kuromoji-unidic/target/kuromoji-unidic-0.9-SNAPSHOT.jar sample_unidic_neologd.groovy すもももももももものうち [すもももももももものうち] きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー! [きゃりーぱみゅぱみゅ, は, 、, 2, 0, 1, 2, 年, に, 「, つけまつける, 」, で, デビュー, !] 日本経済新聞でモバゲーの記事を読んだ [日本経済新聞, で, モバゲー, の, 記事, を, 読ん, だ] くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ [くりぃむしちゅー, は, 、, 上田晋也, と, 有田哲平, の, 2, 人, から, なる, 日本, の, お笑いコンビ] 艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム [艦隊これくしょん, は, 、, 角川ゲームス, が, 開発, し, 、, DMM.com, が, 配信, し, て, いる, ブラウザゲーム]
こちらもOKそうです。
NEologdとは関係なさそうですが、UniDicだと2012年がバラバラにされるんですね。
2, 0, 1, 2, 年
まとめ
Atilika Kuromojiに対して、mecab-ipadic-NEologdとmecab-unidic-NEologdのそれぞれを組み込む手順を示しました。
一部、辞書を修正しちゃいましたが…。UniDicのコストの話(shortの下限を下回る)はさておき、二重引用符の件はなんでしょう?これでハマった人、見たことないような。後でちょっと追ってみようかな…。
通常、自分はLucene Kuromoji+mecab-ipadic-NEologdを使って試していますが(Lucene版KuromojiはUniDicに対応してないし)、だいたいの手順はできたのでKuromoji(Atilika)が0.9のリリースタグでもつけられる状態になってくれれば、おおよそビルドの自動化ができる気がします。
Lucene版に比べると、Kuromoji(Atilika)のアドバンテージはこういうところでしょうか。
- モジュールのバリエーションが多い(kuromoji/kuromoji-ipadic、kuromoji-jumandic、kuromoji-naist-jdic、kuromoji-unidic、kuromoji-unidic-kanaaccent) ※NEologd視点では、現時点ではipadicとunidicですが
- 原型の15文字制限がない
- LuceneのCoreがくっついてこない
Lucene Kuromojiの場合、原型が15文字を超えることを許さないんですよね…。
気になるところは、今のところビルドが遅くてメモリも大量に消費する、というところですかね。辞書を修正してしまった点は、また別の話だと思います。
とりあえず、こんなところで。