読者です 読者をやめる 読者になる 読者になる

IPA辞書から無駄な項目を省く(MeCab)

mecab speed ruby

MeCabのサイトからダウンロードできるIPA辞書には、無駄な項目(単語)が若干含まれている。
※ '無駄'とは普通の形態素解析しか行わない限り。N-Best解などの結果を使いたい場合は別。

# IPA辞書のダウンロードディレクトリに移動
$ cd mecab-ipadic-2.7.0-20070801/

# 辞書(*.csv)内の'神島'という単語を検索
$ grep '$神島,' *.csv
# 表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音
神島,1290,1290,7653,名詞,固有名詞,人名,姓,*,*,神島,カミシマ,カミシマ
  # ここより下の3単語は、単語コストと読み・発音以外は等しい
神島,1293,1293,8715,名詞,固有名詞,地域,一般,*,*,神島,カミジマ,カミジマ
神島,1293,1293,8715,名詞,固有名詞,地域,一般,*,*,神島,コウノシマ,コーノシマ
神島,1293,1293,8716,名詞,固有名詞,地域,一般,*,*,神島,カミシマ,カミシマ
  # ここより下の6単語は、単語コストと読み・発音以外は等しい
神島,1288,1288,8573,名詞,固有名詞,一般,*,*,*,神島,カミジマ,カミジマ     
神島,1288,1288,8573,名詞,固有名詞,一般,*,*,*,神島,コウノシマ,コーノシマ
神島,1288,1288,8569,名詞,固有名詞,一般,*,*,*,神島,カンジマ,カンジマ
神島,1288,1288,8569,名詞,固有名詞,一般,*,*,*,神島,コウジマ,コージマ
神島,1288,1288,8575,名詞,固有名詞,一般,*,*,*,神島,カミシマ,カミシマ
神島,1288,1288,8088,名詞,固有名詞,一般,*,*,*,神島,カシマ,カシマ

MeCabで実装されている(と僕が推測している)形態素解析アルゴリズムでは、表層形と二つの文脈IDが等しい単語があった場合、必ず単語コストが小さいものが選択されることになる。
そのため、'神島'という単語に対するエントリは、実際には以下の三つで十分。

神島,1290,1290,7653,名詞,固有名詞,人名,姓,*,*,神島,カミシマ,カミシマ
神島,1293,1293,8715,名詞,固有名詞,地域,一般,*,*,神島,カミジマ,カミジマ 
神島,1288,1288,8088,名詞,固有名詞,一般,*,*,*,神島,カシマ,カシマ

こういった無駄な項目を省けば、形態素解析の速度も速くなるだろうと思い、試してみた。
項目除外には、次のrubyスクリプトを使用。

# MeCabの辞書から重複した無駄な項目を取り除く
# ファイル名: rmdup.rb

# 入力
hash = Hash.new
while line=gets
  name,id1,id2,cost,rest = line.strip.split(',',5)
  key = [name,id1,id2]  # キーは単語の表層形と左文脈IDと右文脈ID
  hash[key] = Array.new unless hash.key?(key)
  hash[key] << [cost.to_i,rest]
end

# 出力
hash.each do |key,val|
  name,id1,id2 = key
  cost,rest = val.sort_by{|v| v[0] }[0]  # コストが一番低いものだけ出力する
  puts [name,id1,id2,cost,rest].join(',')
end

まず、どのくらいの項目が削除できるか。

$ cat mecab-ipadic-2.7.0-20070801/*.csv | wc -l
392126

$ cat mecab-ipadic-2.7.0-20070801/*.csv | ruby rmdup.rb | wc -l
378915

# 13211項目(約3.3%)減

次に、処理速度。※ それぞれの辞書の作成過程は省く

# 夏目漱石の『こころ』(UTF-8)の形態素解析(分かち書き)に要する時間

$ ls -lh kokoro
-rw-r--r-- 1 root root 542K 2009-06-27 02:42 kokoro

# 普通のIPA辞書を使用した場合
$ time mecab -O wakati -d original kokoro > /dev/null
real	0m0.120s
user	0m0.116s
sys	0m0.004s

# 無駄な項目を削除したIPA辞書を使用した場合
$ time mecab -O wakati -d rmdup kokoro > /dev/null  
real	0m0.117s
user	0m0.108s
sys	0m0.008s

項目除外版の方が、気持ち程度速くなっている(約2.5%)*1

結論

IPA辞書から無駄な項目を除外すれば、確かに処理速度は向上するが、効果は結構微々たるもの。

*1:どの程度速くなるかは、もちろん入力テキストによって異なる。ただし、平均して、辞書からの項目除外率(約3.3%)を大きく外れることなないような気がする(特に根拠のない予想)