ベイジアンフィルターで日本語を分類する。

ベイジアンフィルターで日本語を取り扱う時に問題になってくるのが、文章を品詞レベルに分解する処理。英語の場合は、文章はスペースで区切られた品詞の集合で構成されるため、余分なことをせずに簡単に処理できる。例えば、'How do I set up an AirPort wireless network?'という文章の場合、ベイジアンフィルターは、スペースで区切られた単語を、分類するための判断材料として自動的に取り込んでくれる。
ところが、日本語の場合は、「エアポートの無線ネットワークはどうやって設定しますか?」という文章を、「エアポート の 無線 ネットワーク は どう やっ て 設定 し ます か ? 」のように、品詞をスペースで区切った文章に変換して、ベイジアンフィルターに渡してあげる必要があるらしい。これはすごく高度な作業だ。自分のレベルではどうやっても出来ない。
そこで、この高度な作業を処理してくれる形態素解析エンジンというものが、いろいろ発表されているので、それを利用することに。今回は、「MeCab」を利用させて頂くことにした。

MeCabのインストール

利用環境
ダウンロード
MeCabのインストール
  • まず、ファイルをダウンロードしたら、~/mecab_srcフォルダを作成して、そこに移動した。その後、ターミナルから以下のコマンド操作を実行した。

MeCab本体

cd ~/mecab_src
tar zxfv mecab-0.96.tar.gz
cd mecab-0.96
./configure
make
make check

すると、エラーらしき警告が出るが...

  :
  :
===================
1 of 3 tests failed
===================
make[2]: *** [check-TESTS] Error 1
make[1]: *** [check-am] Error 2
make: *** [check-recursive] Error 1

構わずインストールしてしまった。

sudo make install
MeCab 0.97の場合
  • sudo make installで以下のようなエラーでインストールできなかった...。
$ sudo make install
Password:
Making install in src
test -z "/usr/local/lib" || .././install-sh -c -d "/usr/local/lib"
/bin/sh: .././install-sh: Permission denied
make[2]: *** [install-libLTLIBRARIES] Error 126
make[1]: *** [install-am] Error 2
make: *** [install-recursive] Error 1
  • 上記メッセージ「/bin/sh: .././install-sh: Permission denied」に注目して、lsで確認すると...
 $ ls -l
 total 3888
...(中略)...
 -rw-r--r--@   1 bebe  staff    5569  1 29  2007 install-sh
  • どうもファイル install-sh に実行権限がないのが問題みたいだ。実行権限を設定してみると...
 $ chmod 744 ~/Downloads/mecab-0.97/install-sh
 $ ls -l
 total 3888
...(中略)...
 -rwxr--r--@   1 bebe  staff    5569  1 29  2007 install-sh

無事、インストールできた!

IPA辞書のインストール

続いて、IPA辞書もインストール。

  • デフォルトの文字コードEUCなので、configureのオプションにUTF8を指定することにした。
cd ~/mecab_src
tar zxfv mecab-ipadic-2.7.0-20070610.tar.gz
cd mecab-ipadic-2.7.0-20070610
./configure --with-charset=utf8
make
sudo make install
MeCabを試してみる


ひと通りインストールできたと思ったので、ターミナルから試してみた。

  • mecabコマンドでmecabモードに入る。
  • そして「日本語を解析する」と入力すると、その下に品詞に分解され解析された結果が表示された。
  • 終了はctrl+c。
mecab
日本語を解析する
日本語     名詞,一般,*,*,*,*,日本語,ニッポンゴ,ニッポンゴ
を       助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
解析      名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
する      動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
EOS
  • mecab -O wakatiオプションでmecabモードに入れば、目指すスペース区切りの文章に変換してくれる。
mecab -O wakati
日本語を解析する 
日本語 を 解析 する 


ちゃんと機能している!

mecab-rubyもインストール

rubyからMeCabを利用するためにmecab-rubyをインストールした。

cd ~/mecab_src
tar zxfv mecab-ruby-0.96.tar.gz
cd mecab-ruby-0.96
ruby extconf.rb
make
sudo make install

どうやら、うまくインストールできたようだ。

/usr/bin/install -c -m 0755 MeCab.bundle /Applications/Locomotive2/Bundles/standardRailsSept2006.locobundle/i386/lib/ruby/site_ruby/1.8/i686-darwin8.7.1
mecab-rubyから試してみる
      • UTF8な環境にしておく。
$KCODE = 'u'
require 'rubygems'
require 'MeCab'

wakati = MeCab::Tagger.new('-O wakati')
puts wakati.parse('日本語を解析する')

Rubyでも、ちゃんと動いている!

日本語 を 解析 する


以下のページが大変参考になりました。感謝です!

日本語をベイジアンフィルターで分類

RubyMeCabを利用する環境は整った。これで、ベイジアンフィルターは日本語を正しく認識してくれるはず。以下のように試してみた。

$KCODE='u'

require 'rubygems'
require 'classifier'
require 'stemmer'
require 'MeCab'

# 分類の設定
bayes = Classifier::Bayes.new('mac', 'windows')
wakati = MeCab::Tagger.new('-O wakati')

# 分類の学習
bayes.train('mac', wakati.parse('iPodの設定はどのように変更したら良いですか。'))
bayes.train('mac', wakati.parse('AirPortの無線ネットワークはどうやって設定しますか。'))
bayes.train('mac', wakati.parse('MacOSXのMailはどうやって設定しますか。'))
bayes.train('windows', wakati.parse('Internet Explorer 5以降を実行しておく必要があります。'))
bayes.train('windows', wakati.parse('マイクロソフトダウンロードセンターからアップデートを取得できます。'))
bayes.train('windows', wakati.parse('今の仕事のためにオフィスライブベーシックを手に入れよう。'))

comment = 'この書類を開くにはマイクロソフトオフィスが必要です。'

# 分類データの数値化
puts bayes.classifications(wakati.parse(comment)).inspect

# 分類の結果
puts bayes.classify(wakati.parse(comment))

# Bayesオブジェクトの中身
p bayes

前回に引き続き、学習サンプルが少な過ぎてあまり良い例ではないが、なんとか分類できたようだ。

# 分類データの数値化
{"Windows"=>-53.9273660615414, "Mac"=>-60.1861959201719}

# 分類の結果
Windows

# Bayesオブジェクトの中身
#{:て=>2, :し=>3, :airport=>1, :は=>3, :ます=>2, :たら=>1, :無線=>1, :どの=>1, :macosx=>1, :良い=>1, :ネットワーク=>1, :よう=>1, :mail=>1, :ipod=>1, :です=>1, :どう=>2, :に=>1, :の=>3, :か=>3, :やっ=>2, :変更=>1, :設定=>3, :。=>3}, :Windows=>{:仕事=>1, :し=>1, :て=>1, :必要=>1, :から=>1, :ため=>1, :が=>1, :ます=>2, :アップデート=>1, :以降=>1, :オフィスライブベーシック=>1, :あり=>1, :取得=>1, :を=>3, :手=>1, :マイクロソフト=>1, :に=>2, :でき=>1, :実行=>1, :の=>2, :入れよ=>1, :ダウンロード=>1, :internet=>1, :今=>1, :おく=>1, :う=>1, :センター=>1, :explor=>1, :。=>3}}, @total_words=75>

学習結果を保存する

今の状態では、プログラムの実行が終わると、学習内容は破棄されてしまう。ファイルに保存してみる。

$KCODE = 'u'
require 'rubygems'
require 'classifier'
require 'stemmer'
require 'MeCab'

# 分類の設定
# bayes_dataが存在したら、ベイズオブジェクトへ復元
begin
  bayes = nil
  File.open("/Users/bebe/bayes_data", "r") {|f| bayes = Marshal.load(f)}
rescue
  bayes = Classifier::Bayes.new('mac', 'windows')
end
wakati = MeCab::Tagger.new('-O wakati')

# 分類の学習
bayes.train('mac', wakati.parse('iPodの設定はどのように変更したら良いですか。'))
bayes.train('mac', wakati.parse('AirPortの無線ネットワークはどうやって設定しますか。'))
bayes.train('mac', wakati.parse('MacOSXのMailはどうやって設定しますか。'))
bayes.train('windows', wakati.parse('Internet Explorer 5以降を実行しておく必要があります。'))
bayes.train('windows', wakati.parse('マイクロソフトダウンロードセンターからアップデートを取得できます。'))
bayes.train('windows', wakati.parse('今の仕事のためにオフィスライブベーシックを手に入れよう。'))

comment = 'この書類を開くにはマイクロソフトオフィスが必要です。'

# 分類データの照会
puts bayes.classifications(wakati.parse(comment)).inspect

# 分類の結果
puts bayes.classify(wakati.parse(comment))

# Bayesオブジェクトの中身
p bayes

# ベイズオブジェクトをファイルに保存
File.open("/Users/bebe/bayes_data", "wb") {|f| Marshal.dump(bayes, f)}

これで、学習結果は保存されるようになった!