名古屋で数学するプログラマ(仮)

@antimon2 が趣味兼一部本職の数学で何かするときのブログ。

MeCab Ruby と CaboCha Ruby をインストールしてみた

機械学習も統計もあまり勉強進んでいませんゴメンナサイ。
ちょっとそのきっかけ作り(という名目の個人的な実験)のために、形態素解析とか日本語係り受け解析とかを試してみることにしました。
個人的な理由のために Ruby からの利用を前提として。

MeCabMeCab Ruby のインストール

最初は「形態素解析」というものに触れてみようということで、 MeCab をインストール。
技術ブログでは「失敗したログも含めて全部記録する」のが定石なんですが、めんどくさいし個人的には成功例と「なぜそれで成功したのか(なぜ失敗を回避できたか)」が分かれば良いと思うのでその方針で書きます。
ちなみに環境は、Mac OSX Lion 10.7.4 です。

インストールしたのは以下の通り:

まずは MeCab 本体。最新のtar ballをDLして以下の要領でインストール。

$ tar xzvf mecab-0.994.tar.gz
$ cd mecab-0.994
$ ./configure --enable-utf8-only
$ make
$ sudo make install

ポイントは以下の通り:

  • ./configure時に「--enable-utf8-only」オプションを付加。Ruby 1.9UTF-8 での使用しか想定していないので。またこうするとeucsjisの変換テーブルを埋め込まず実行バイナリを小さく出来ると言うことなので*1

これはすんなり完了。
続いて辞書のインストール。

$ tar xzvf mecab-ipadic-2.7.0-20070801.tar.gz 
$ cd mecab-ipadic-2.7.0-20070801
$ ./configure --with-charset=utf8
$ make
$ sudo make install

ポイント:

  • ./configure時に「--with-charset=utf8」オプションを付加。Ruby 1.9UTF-8 での使用しか想定していないので。

こちらもすんなり。なんだMeCabてばインストール簡単じゃん。

早速実験。sumomo.txt は utf-8 のテキストファイルです。

$ cat sumomo.txt
すもももももももものうち
$ mecab sumomo.txt
すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
うち	名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS

OK。

では続いて Ruby で直接いじれるようにするためのモジュールをインストール。Downloads - mecab - Japanese morphological analyzer - Google Project Hostingから最新のモジュールのtar ballをDLして、以下の要領でインストール。

$ tar xzvf mecab-ruby-0.994.tar.gz 
$ cd mecab-ruby-0.994
$ ruby extconf.rb 
$ make
$ sudo make install
$ ruby test.rb 
《実行結果省略》

こちらは何も難しいことはないですね。
当然のことながら、今実行している ruby に新しいモジュールとしてインストールされるので、rvmやrbenv等で複数バージョンを管理しているなら、必要なバージョンのRubyごとにインストールしないといけません。rvmなら、専用のgemsetを作ってからインストール、っていう方法も良いかも。私はめんどくさいので素の(普段使用している)Ruby だけにインストールしました。

簡単に実行確認。

[1] 1.9.3-p125(main)> require 'MeCab'
=> true
[2] 1.9.3-p125(main)> sentence = "\u592a\u90ce\u306f\u3053\u306e\u672c\u3092\u4e8c\u90ce\u3092\u898b\u305f\u5973\u6027\u306b\u6e21\u3057\u305f\u3002"
=> "太郎はこの本を二郎を見た女性に渡した。"
[3] 1.9.3-p125(main)> mecab = MeCab::Tagger.new
=> #<MeCab::Tagger:0x007f885c18ae20 @__swigtype__="_p_MeCab__Tagger">
[4] 1.9.3-p125(main)> puts mecab.parse sentence
太郎	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
この	連体詞,*,*,*,*,*,この,コノ,コノ
本	名詞,一般,*,*,*,*,本,ホン,ホン
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
二	名詞,数,*,*,*,*,二,ニ,ニ
郎	名詞,一般,*,*,*,*,郎,ロウ,ロー
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
見	動詞,自立,*,*,一段,連用形,見る,ミ,ミ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
女性	名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
渡し	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
EOS
=> nil

内容については、ここでは深く突っ込みません。

CaboCha のインストール

つづいて CaboCha 。こちらは「日本語係り受け解析器」。
実は MeCab の存在は以前から知っていて、それでちょっと試したんですが、「結局これ、単語(正確には形態素)の分割は出来るけれど、これだけだと係り受けは分かんないじゃん」てことに気付いて(私がやりたかったことがそっちだったことに気付いて)、後から探して見付けてインストールしたのが CaboCha 、だったりします。

インストールしたのは以下の通り:

なお他に、MeCab がインストールされていることが前提です。

まずは CRF++。

$ tar xzvf CRF++-0.57.tar.gz 
$ cd CRF++-0.57
$ ./configure 
$ make
$ sudo make install

インストールそのものは問題なし。一応、ポイント:

続いて CaboCha。MeCab のインストールの時に言及した通り、成功例だけ示します。

$ tar xzvf cabocha-0.64.tar.gz 
$ cd cabocha-0.64
$ LIBS=-liconv ./configure --with-charset=utf8
$ make
$ sudo make install

ポイントは以下の通り:

取り敢えず動作確認。

$ cat sumomo.txt
すもももももももものうち
$ cabocha sumomo.txt
すももも-D    
    ももも---D
      ももの-D
          うち
EOS

…例が悪かったですねw これじゃ何が起きているかよく分からない。別の例。

$ cabocha
私が「あなたは右の道から来ましたか?」と質問したら、あなたは「はい」と答えますか?
            私が---------D      
        「あなたは-----D |      
                右の-D | |      
                道から-D |      
        来ましたか?」と-D      
              質問したら、-----D
                    あなたは---D
                    「はい」と-D
                    答えますか?
EOS

複文、係り受け、きちんと解析できてますね。素晴らしい(^-^)

CaboCha Ruby のインストール

続いて CaboCha Ruby
MeCab には Ruby で直接利用するためのラッパーモジュールが用意されていましたが、CaboCha は自分で用意する必要があります。といってもSWIG (Simplified Wrapper and Interface Generator)というツールを使って簡単にラッパーモジュールを作れるようになっている*2ので、ありがたくそれを利用します。

ということで、さらに以下をインストール:

$ tar xjvf pcre-8.31.tar.bz2 
$ cd pcre-8.31
$ ./configure
$ make
$ sudo make install
$ tar xzvf swig-2.0.7.tar.gz 
$ cd swig-2.0.7
$ ./configure
$ make
$ sudo make install

ポイント:

  • そのまま SWIG をインストールしようとすると、./configure で pcre がないと怒られたので、PCRE の最新を探してきて先にインストール。予め何かの目的で PCRE を入れてあれば不要かも。

さて、では CaboCha の Ruby 用のモジュールを作ってインストール。

$ cd cabocha-0.64/swig
$ make ruby
$ cd ../ruby/
$ ruby extconf.rb 
$ make
$ sudo make install

ポイント:

  • SWIG が入ってないと、make ruby の時点で「swig: No such file or directory」のエラーになります。
  • ruby extconf.rb以降は、MaCab Ruby と同じ手順ですね。

さてテストですが、用意されている test.rb が Ruby 1.9 だと 正常に動作しません。文字コード指定のマジックコメントが必要です。

$ vi test.rb
#!/usr/bin/ruby
# -*- coding: utf-8 -*-
# ↑この1行を追記

require 'CaboCha'
sentence = "太郎はこの本を二郎を見た女性に渡した。"
《以下略》

で、test.rb 実行。

$ ruby test.rb
<PERSON>太郎</PERSON>は-----------D
                     この-D       |
                       本を---D   |
                       二郎を-D   |
                           見た-D |
                           女性に-D
                           渡した。
EOS
<PERSON>太郎</PERSON>は-----------D
                     この-D       |
                       本を---D   |
                       二郎を-D   |
                           見た-D |
                           女性に-D
                           渡した。
EOS
* 0 6D 0/1 2.909358
太郎	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー	B-PERSON
は	助詞,係助詞,*,*,*,*,は,ハ,ワ	O
* 1 2D 0/0 1.257926
この	連体詞,*,*,*,*,*,この,コノ,コノ	O
* 2 4D 0/1 0.638994
本	名詞,一般,*,*,*,*,本,ホン,ホン	O
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ	O
* 3 4D 1/2 1.696047
二	名詞,数,*,*,*,*,二,ニ,ニ	O
郎	名詞,一般,*,*,*,*,郎,ロウ,ロー	O
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ	O
* 4 5D 0/1 0.000000
見	動詞,自立,*,*,一段,連用形,見る,ミ,ミ	O
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ	O
* 5 6D 0/1 0.000000
女性	名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ	O
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ	O
* 6 -1D 0/1 0.000000
渡し	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ	O
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ	O
。	記号,句点,*,*,*,*,。,。,。	O
EOS

Ruby の実行環境上で実験。

[1] 1.9.3-p125(main)> require 'CaboCha'
=> true
[2] 1.9.3-p125(main)> sentence = "\u592a\u90ce\u306f\u3053\u306e\u672c\u3092\u4e8c\u90ce\u3092\u898b\u305f\u5973\u6027\u306b\u6e21\u3057\u305f\u3002"
=> "太郎はこの本を二郎を見た女性に渡した。"
[3] 1.9.3-p125(main)> cabocha = CaboCha::Parser.new
=> #<CaboCha::Parser:0x007f9b690d1fe0 @__swigtype__="_p_CaboCha__Parser">
=> true
[4] 1.9.3-p125(main)> tree = cabocha.parse sentence
=> #<CaboCha::Tree:0x007f9b6990d948 @__swigtype__="_p_CaboCha__Tree">
[5] 1.9.3-p125(main)> puts tree.toString(CaboCha::OUTPUT_RAW_SENTENCE)
<PERSON>太郎</PERSON>は-----------D
                     この-D       |
                       本を---D   |
                       二郎を-D   |
                           見た-D |
                           女性に-D
                           渡した。
EOS
=> nil
[6] 1.9.3-p125(main)> chunk_to_s = ->(ch){(0...ch.token_size).map{|j|tree.token(ch.token_pos+j).normalized_surface}.join("-")}
=> #<Proc:0x007f9b699611b0@(pry):38 (lambda)>
[7] 1.9.3-p125(main)> chunk_link = ->(ch){if ch.link>=0;ch_from=chunk_to_s[ch];ch_to=chunk_to_s[tree.chunk(ch.link)];"#{ch_from} => #{ch_to}";end;}
=> #<Proc:0x007f9b6903e0b0@(pry):41 (lambda)>
[8] 1.9.3-p125(main)> puts chunk_link[tree.chunk(0)]
=> 太郎-は => 渡し-た-。
[9] 1.9.3-p125(main)> puts chunk_link[tree.chunk(1)]
=> この => 本-を

つまり、treeは文の解析ツリー、chunkが文節、tokenが単語(形態素)、ですね。
そしてCaboCha::Chunk#link が係り受けを表している(自分が「係り」、linkで表されるインデックスのChunkが「受け」)、と。

でもこれ、本当に CaboCha を単純にラップしたもので、Ruby 的に使いにくいところとか気になるところがいくつかあるので、余裕があったらより Ruby っぽくなるようにさらにラップしたいところ。

取り敢えず今日はここまで。

*1:http://mecab.googlecode.com/svn/trunk/mecab/doc/index.html#utf-8 参照。

*2:MeCab RubySWIG を利用して作られたラッパーモジュールです。