先日、このようなエントリを書きました。
mecab-ipadic-neologdの辞書を、Lucene Kuromojiに適用してみる
http://d.hatena.ne.jp/Kazuhira/20150315/1426391366
mecab-ipadic-neologd自体については、こちら。
MeCab 用の新語辞書 mecab-ipadic-neologd を公開しました
http://diary.overlasting.net/2015-03-13-1.html
このエントリでは、LuceneのKuromojiにmecab-ipadic-neologdを適用してみたのですが、2つの問題が出ました。
ひとつは、Kuromojiがmecab-ipadic-neologdのシード辞書に含まれる原形が15文字を超える単語を取り込めないこと。もうひとつは、同じくmecab-ipadic-neologdのシード辞書に含まれる文脈IDと品詞の組み合わせが、元のIPA辞書とズレてしまっていてやっぱり取り込めないこと。
最初のものは、Kuromojiの事情だと思いますが(オリジナルのMeCabは原形が15文字を超えていようが動作するので)、後者はmecab-ipadic-neologdの問題かなぁとちょっと思っていました。
すると、作者の@overlastさんにこのエントリを見ていただけたようで、修正してもらえました!
@kazuhira_r ありがとうございます。ご迷惑をおかけしました文脈IDを修正しました。すいませんでした。お時間がある時に問題が残っていないかご確認頂きたいです。原型の15文字制限はneologd側の問題では無い気がします。 URL
2015-03-15 17:11:36 via TweetDeck to @kazuhira_r
ありがとうございます!
3/17追記)
その後、辞書に反映する原形の最大値を指定できるオプションまでつけてもらえました!
@kazuhira_r './bin/install-mecab-ipadic-neologd -n --max_baseform_length 15' でgit pullして、原型が15文字以内のエントリだけ残せるようになりました。 #neologd
2015-03-17 08:21:55 via TweetDeck to @kazuhira_r
スミマセン…ありがとうございます!
というわけで、気を取り直して再度適用方法をまとめたいと思います。今度は、もう少しボリュームを抑えて…。
※前回のエントリの記述が混じっているものもありますが、ご了承ください
追記)
最終的に、bashスクリプトにしました。いきなり結果が欲しい方は、こちらへ。
Lucene Kuromojiに対して、mecab-ipadic-neologdの辞書を適用してビルドするbashスクリプトを書きました
http://d.hatena.ne.jp/Kazuhira/20150317/1426606053
MeCabとIPA辞書のインストール
READMEを読みつつ、必要なソフトウェアを揃えます。
mecab-ipadic-NEologd : Neologism dictionary for MeCab
https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md
必要なものは、C++コンパイラ、iconv、MeCab、mecab-ipadic、xzだそうです。
前回までである程度揃えてしまったので、ここではMeCabとIPA辞書のインストールから始めます。
MeCabのインストール。今回もMeCabをシステムグローバルにインストールしないので、インストール先を指定します。ここでは、「$MECAB_HOME」と記載します。
$ wget https://mecab.googlecode.com/files/mecab-0.996.tar.gz $ tar -zxvf mecab-0.996.tar.gz $ cd mecab-0.996 $ ./configure --prefix=$MECAB_HOME $ make $ sudo make install
インストールしたMeCabにパスを通します。
$ export PATH=$MECAB_HOME/bin:$PATH
IPA辞書のインストール。
$ wget https://mecab.googlecode.com/files/mecab-ipadic-2.7.0-20070801.tar.gz $ tar -zxvf mecab-ipadic-2.7.0-20070801.tar.gz $ cd mecab-ipadic-2.7.0-20070801 $ ./configure --with-charset=utf-8 $ make $ sudo make install
ここまでで、mecab-ipadic-neologdのインストール要件が揃います。
mecab-ipadic-neologdのインストール
以下に記載の手順に沿って、mecab-ipadic-neologdをインストールします。
mecab-ipadic-NEologd : Neologism dictionary for MeCab
https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md
$ git clone https://github.com/neologd/mecab-ipadic-neologd.git $ cd mecab-ipadic-neologd $ git pull $ ./bin/install-mecab-ipadic-neologd -n --max_baseform_length 15
今回、@overlastさんに追加していただいたオプション、「-n --max_baseform_length [原形の最大長]」を指定して、今回は原形の長さが15文字以内になるようにしています。
実行すると、途中でこんな表示が出て原形が15文字を超えたものを、消してくれてるっぽいです。
[make-mecab-ipadic-neologd] : Delete the entries whose length of base form is longer than 15 from seed file
そして、ビルドした時に、カレントディレクトリに生成される「build」ディレクトリの中身を、今後は使うことになります。
$ ls -l build 合計 11928 drwxrwxr-x 2 xxxxx xxxxx 4096 3月 17 21:53 mecab-ipadic-2.7.0-20070801-neologd-20150317 -rw-rw-r-- 1 xxxxx xxxxx 12208105 3月 17 21:52 mecab-ipadic-2.7.0-20070801.tar.gz
「neologd」の次の日付の部分(今回は「20150317」)は、辞書が更新されるにしたがって上がっていくようなので、適宜読み替えてください。
ちなみに、今回のような使い方だと、最後に実行するスクリプトは、「bin/install-mecab-ipadic-neologd」ではなくて「libexec/make-mecab-ipadic-neologd.sh」でもいいかもしれません。
以降、MeCabは使わなくなります。
Luceneのビルド
続いて、Luceneをビルドします。
Subversionからエクスポートして、Lucene本体をビルド。今回のLuceneのバージョンは5.0.0を使うので、タグは「lucene_solr_5_0_0」です。
$ svn export http://svn.apache.org/repos/asf/lucene/dev/tags/lucene_solr_5_0_0 $ cd lucene_solr_5_0_0/lucene $ ant ivy-bootstrap $ ant compile
「ant ivy-bootstrap」は、すでにAntにIvyが導入済みであれば不要です。
なお、ここでLuceneをエクスポートしたディレクトリ(/path/to/lucene_solr_5_0_0)を、$LUCENE_SRC_HOMEと記載します。
Kuromojiの配置されているディレクトリへ移動。
$ cd analysis/kuromoji
先ほど、mecab-ipadic-neologdをビルドした時の中間生成物(build/mecab-ipadic-2.7.0-20070801-neologd-20150317)を、Kuromojiのビルド成果物の出力先にコピーします。
$ cp -Rp [mecab-ipadic-neologdをビルドしたディレクトリ]/build/mecab-ipadic-2.7.0-20070801-neologd-20150317 $LUCENE_SRC_HOME/lucene/build/analysis/kuromoji
デフォルトのIPA辞書ではなく、コピーしたmecab-ipadic-neologdの中間生成物を使うように、build.xmlのipadic.versionを修正します(ここが、ディレクトリ名も指すようになっているので)。
<!-- <property name="ipadic.version" value="mecab-ipadic-2.7.0-20070801" /> --> <property name="ipadic.version" value="mecab-ipadic-2.7.0-20070801-neologd-20150317" />
先にも書きましたが、neologdの後ろに続く日付は、適宜インストールしたバージョンに合わせて修正してください。
今回使う辞書(というかCSVファイル)はUTF-8で書かれているので、デフォルトのEUC-JPから変更します。
<!-- <property name="dict.encoding" value="euc-jp"/> --> <property name="dict.encoding" value="utf-8"/>
build-dictタスクでは、辞書のダウンロードは不要になるので、dependsからdownload-dictタスクを切り離します。
<!-- <target name="build-dict" depends="compile-tools, download-dict"> --> <target name="build-dict" depends="compile-tools">
辞書作成ツールは、今回のCSVファイルを読ませるとデフォルトのヒープサイズ(1G)では足りなくなるので、拡張します。2Gにしましたが、今回はこれで十分に余裕がありました。
<!-- TODO: optimize the dictionary construction a bit so that you don't need 1G --> <!-- <java fork="true" failonerror="true" maxmemory="1g" classname="org.apache.lucene.analysis.ja.util.DictionaryBuilder"> --> <java fork="true" failonerror="true" maxmemory="2g" classname="org.apache.lucene.analysis.ja.util.DictionaryBuilder">
※Antの設定はシステムプロパティでもできることを後で思い出しましたが、maxmemoryなどは変えられなさそうなのでこのままbuild.xmlを修正する方向のままにしました
では、辞書をビルドします。
$ ant regenerate
ここで、mecab-ipadic-neologdインストール時に「-n --max_baseform_length 15」オプションを付けていなかった場合、しばらく待っていると辞書のビルドに失敗します。
[java] building tokeninfo dict... [java] parse... [java] sort... [java] encode... [java] Exception in thread "main" java.lang.AssertionError [java] at org.apache.lucene.analysis.ja.util.BinaryDictionaryWriter.put(BinaryDictionaryWriter.java:129) [java] at org.apache.lucene.analysis.ja.util.TokenInfoDictionaryBuilder.buildDictionary(TokenInfoDictionaryBuilder.java:143) [java] at org.apache.lucene.analysis.ja.util.TokenInfoDictionaryBuilder.build(TokenInfoDictionaryBuilder.java:78) [java] at org.apache.lucene.analysis.ja.util.DictionaryBuilder.build(DictionaryBuilder.java:37) [java] at org.apache.lucene.analysis.ja.util.DictionaryBuilder.main(DictionaryBuilder.java:82)
冒頭にも書きましたが、Kuromojiが原形が15文字を超えることを許さないみたいなのです。
assert baseForm.length() < 16;
参考:MeCabの辞書のフォーマットについて)
単語の追加方法
http://mecab.googlecode.com/svn/trunk/mecab/doc/dic.html
うまくいかなかった場合は、このあたりを見直してみてください。
成功すると、以下の用に表示されます。
regenerate: BUILD SUCCESSFUL Total time: 1 minute 31 seconds
また、前回はここで文脈IDと品詞の組み合わせがズレていてコケていたのでした。バッチリ修正されていますね!
そして、Kuromoji本体をビルド。
$ ant jar-core
jar-core: [jar] Building jar: $LUCENE_SRC_HOME/lucene/build/analysis/kuromoji/lucene-analyzers-kuromoji-5.0.0-SNAPSHOT.jar BUILD SUCCESSFUL Total time: 5 seconds
Lucene Kuromojiを使って動作確認
では、Kuromojiを使って動作確認します。プログラムは、Scalaで記述。
build.sbt
build.sbt name := "lucene-kuromoji-mecab-neologd" version := "0.0.1-SNAPSHOT" scalaVersion := "2.11.5" organization := "org.littlewings" updateOptions := updateOptions.value.withCachedResolution(true) scalacOptions ++= Seq("-Xlint", "-unchecked", "-deprecation", "-feature") libraryDependencies ++= Seq( "org.apache.lucene" % "lucene-core" % "5.0.0", "org.apache.lucene" % "lucene-analyzers-common" % "5.0.0", "org.apache.lucene" % "lucene-analyzers-kuromoji" % "5.0.0" )
確認用のコード。
src/main/scala/org/littlewings/lucene/kuromoji/KuromojiWithNeologd.scala
package org.littlewings.lucene.kuromoji import org.apache.lucene.analysis.ja.JapaneseAnalyzer import org.apache.lucene.analysis.tokenattributes.CharTermAttribute object KuromojiWithNeologd { def main(args: Array[String]): Unit = { val texts = Array( "すもももももももものうち", "きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー!", "日本経済新聞でモバゲーの記事を読んだ", "くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ", "艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム" ) val analyzer = new JapaneseAnalyzer for (text <- texts) { val tokenStream = analyzer.tokenStream("", text) val charTermAttr = tokenStream.addAttribute(classOf[CharTermAttribute]) tokenStream.reset() val tokens = Iterator .continually(tokenStream.incrementToken()) .takeWhile(identity) .map(_ => charTermAttr.toString) println(s"InputText = $text") println(s" Tokenized = ${tokens.mkString("[", ", ", "]")}") tokenStream.close() } } }
形態素解析する文章は、適当にWikipediaなどから貼っています。また、KuromojiはデフォルトのSEARCHモードです。
このプログラムを実行してみます。
> run [info] Running org.littlewings.lucene.kuromoji.KuromojiWithNeologd InputText = すもももももももものうち Tokenized = [すもも, もも, もも] InputText = きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー! Tokenized = [く, ー, ぱみゅぱみゅは, 2012, 年, つけ, つける, デビュ] InputText = 日本経済新聞でモバゲーの記事を読んだ Tokenized = [日本, 日本経済新聞, 経済, 新聞, モバゲ, 記事, 読む] InputText = くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ Tokenized = [くり, ぃむしちゅ, ー, 上田, 晋, 也, 有田, 哲, 平, 2, 人, 日本, お笑い, コンビ] InputText = 艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム Tokenized = [艦隊, くし, ょんは, 角川, ゲームス, 開発, dmm, com, 配信, ブラウザゲーム] [success] Total time: 0 s, completed 2015/03/17 0:14:21
Tokenized = の部分が形態素解析した結果ですが、けっこうすごいことになりました。わからない単語が多いということですね。
では、ここで先ほど辞書を使ってビルドした、KuromojiのJARファイルを使ってみます。
1度sbtを終了。
> exit
libディレクトリを作成します。
$ mkdir lib
この中に、ビルドしたJARファイルを放り込みます。
$ cp $LUCENE_SRC_HOME/lucene/build/analysis/kuromoji/lucene-analyzers-kuromoji-5.0.0-SNAPSHOT.jar lib/
sbtの依存関係定義から、Kuromojiを外します。
libraryDependencies ++= Seq( "org.apache.lucene" % "lucene-core" % "5.0.0", "org.apache.lucene" % "lucene-analyzers-common" % "5.0.0" // "org.apache.lucene" % "lucene-analyzers-kuromoji" % "5.0.0" )
では、再度sbtを起動して、実行。
> run [info] Running org.littlewings.lucene.kuromoji.KuromojiWithNeologd InputText = すもももももももものうち Tokenized = [すもももももも, すもももももももものうち, もも] InputText = きゃりーぱみゅぱみゅは、2012年に「つけまつける」でデビュー! Tokenized = [きゃりーぱみゅぱみゅ, 2012年, つけまつける, デビュ] InputText = 日本経済新聞でモバゲーの記事を読んだ Tokenized = [日本, 日本経済新聞, 経済, 新聞, mobage, 記事, 読む] InputText = くりぃむしちゅーは、上田晋也と有田哲平の2人からなる日本のお笑いコンビ Tokenized = [くりぃむしちゅー, 上田, 晋也, 有田, 有田哲平, 哲平, 2, 人, 日本, お笑いコンビ] InputText = 艦隊これくしょんは、角川ゲームスが開発し、DMM.comが配信しているブラウザゲーム Tokenized = [艦隊これくしょん, 角川ゲームス, 開発, dmm.com, 配信, ブラウザゲーム] [success] Total time: 1 s, completed 2015/03/17 0:15:09
結果がだいぶ変わりましたね。「きゃりーぱみゅぱみゅ」といった人名などがかなり認識できています。
ところで、「すもももももももものうち」の結果が、妙なことになりました。
InputText = すもももももももものうち Tokenized = [すもももももも, すもももももももものうち, もも]
一応、シードのCSVを確認…。
$ view [mecab-ipadic-neologdをビルドしたディレクトリ]/build/mecab-ipadic-2.7.0-20070801-neologd-20150317/mecab-user-dict-seed.20150317.csv
このあたりに引っかかりましたね…。
すももももも,1288,1288,5072,名詞,固有名詞,一般,*,*,*,すももももも,スモモモモモ,スモモモモモ すもももももも,1288,1288,4587,名詞,固有名詞,一般,*,*,*,すもももももも,スモモモモモモ,スモモモモモモ
そして、「すもももももももものうち」は単体で名詞として存在していたり…。
すもももももももものうち,1288,1288,4143,名詞,固有名詞,一般,*,*,*,すもももももももものうち,スモモモモモモモモノウチ,スモモモモモモモモノウチ
とりあえず、mecab-ipadic-neologdの辞書をKuromojiで取り込んで動かすという目標は達成したので、よしとしましょう!
終わりに
mecab-ipadic-neologdについてですが、公開されてから注目を集めているようで、いろんなところで名前を見たり、◯◯で使ってみたみたいなエントリが出ているようです。
その中で、先日自分はLucene Kuromojiで踏んだわけですが…。とはいえ、@overlastさんにコメントおよび修正いただけたりして、とても驚きました。前回はかなり無理矢理ビルドを通しましたが、修正してもらえたことでLucene Kuromojiでもかなり取り込みやすくなったと思います。
ありがとうございました!
今回作成したソースコードとスクリプトは、こちらに置いています。
https://github.com/kazuhira-r/lucene-examples/tree/master/lucene-kuromoji-mecab-neologd
前回より、形態素解析する文章をちょっといじったりしています。