以前、MeCabのユーザー辞書を作る方法を紹介しました。
参考: MeCabでユーザー辞書を作って単語を追加する
システム辞書に無い単語をユーザー辞書に登録して使えば、当然システム辞書の単語とユーザー辞書の単語の両方を使って形態素解析が行えるようになります。
この時にもし、システム辞書に登録済みの単語を改めてユーザー辞書に登録してしまったらどのような挙動になるのか気になったのでドキュメントを確認してみましたがそれらしい記載がありませんでした。(他サイトにユーザー辞書がシステム辞書を上書きするという情報もあったのですが、本当にそうなのか疑わしいとも思いました。)
そこで実験してみようと思ったのがこの記事です。
また、MeCabは起動時にシステム辞書は1つしか指定できませんが、ユーザー辞書は複数指定できます。その複数のユーザー辞書に登録したらどういう挙動になるのかも確認しました。
それとついでにですが、1個のユーザー辞書に同じ単語を複数回登録した場合(これはもうただの辞書作成時のミスでしかあり得ないのですが。)の事象も見ています。
え、システム辞書に登録されてる単語をユーザー辞書に登録することなんてある?と思われる方もいらっしゃると思いますが、これは普通にあります。気づかずに登録してしまった、という場合はもちろんですが、解析結果の誤りを修正するために生起コストの設定を変えたいというケースがあるのです。
例えば、IPA辞書そのままだと、「りんごジュース」の形態素解析結果は次のように誤ったものになります。
$ echo りんごジュース | mecab
りん 副詞,助詞類接続,*,*,*,*,りん,リン,リン
ご 接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
ジュース 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
IPA辞書に「りんご」が登録されていないわけではありません。バッチリ含まれています。
# ビルド前のIPA辞書のファイルが含まれているディレクトリで実行
$ grep りんご * -r
Noun.csv:りんご,1285,1285,7277,名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
「りんご」自体の生起コストが高いこととか、「BOS」と「名詞,一般」の連接コストなどの諸々の事情によりこのような誤りが発生しています。これを是正する手段の一つが、「りんご」をもっと低い生起コストで登録することなのです。
とりあえず、生起コストを5000に落としてやってみます。下のコードでcatしてるようなテキストをファイルを作り、ユーザー辞書をコンパイルしてMeCabを動かしてみます。
# seedファイルの中身確認
$ cat apple1.csv
りんご,1285,1285,5000,名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
# コンパイル
$ /usr/local/Cellar/mecab/0.996/libexec/mecab/mecab-dict-index -d /usr/local/lib/mecab/dic/ipadic -u apple1.dic -f utf-8 -t utf-8 apple1.csv
reading apple1.csv ... 1
emitting double-array: 100% |###########################################|
done!
# 生成されたユーザー辞書を使って形態素解析(生起コストも表示)
$ echo りんごジュース | mecab -F %m\\t%c\\t%H\\n -u apple1.dic
りんご 5000 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
ユーザー辞書に登録した生起コスト5000のりんごを使って形態素解析されましたね。
この結果だけ見ると、システム辞書にある単語をユーザー辞書に登録したら情報が上書きされたように見えます。ただし、実際の動きはそうでは無いのです。
上書きされたように見えるだけで、システム辞書とユーザー辞書それぞれのりんごは別々の独立した単語として処理されていて、解には生起コストが低いユーザー辞書のりんごが採用されたというのが正確な動きになります。このことはN-Best解を表示すると確認できます。
$ echo りんごジュース | mecab -F %m\\t%c\\t%H\\n -N3 -u apple1.dic
りんご 5000 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りん 4705 副詞,助詞類接続,*,*,*,*,りん,リン,リン
ご 6655 接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りんご 7277 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
3番目の解として、システム辞書の生起コスト7277のりんごもバッチリ登場していますね。上書きされて消えているわけでは無いのです。
つまりユーザー辞書に単語を登録しても、元のシステム辞書より高い生起コストを設定してたらそれは1番目の解としては使われないということです。apple2って名前で、生起コスト8000のりんごを登録してやってみます。
$ cat apple2.csv
りんご,1285,1285,8000,名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
$ /usr/local/Cellar/mecab/0.996/libexec/mecab/mecab-dict-index -d /usr/local/lib/mecab/dic/ipadic -u apple2.dic -f utf-8 -t utf-8 apple2.csv
reading apple2.csv ... 1
emitting double-array: 100% |###########################################|
done!
$ echo りんごジュース | mecab -F %m\\t%c\\t%H\\n -u apple2.dic
りん 4705 副詞,助詞類接続,*,*,*,*,りん,リン,リン
ご 6655 接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
システム辞書だけの場合と結果変わりませんでしたね。このことからも、ユーザー辞書の単語がシステム辞書の単語を上書きする説は誤りであることがわかります。
実は元々、他のサイトの記事で単語が上書きされる説を見かけて、ユーザー辞書を複数登録したら最後にどっちの単語が残るんだ?という疑問からこの検証を始めています。
しかし、「そもそも上書きしないで別の単語として扱われる」が結論であれば、同じ辞書に複数回単語登録したり、ユーザー辞書を複数使用してそれぞれに重複してた単語があったとしても、別の単語として扱われて生起コストで判定される、と予想が付きます。
一応、「りんご」が2回登録された辞書も作って、上で作った2辞書と合わせて3辞書で動かしてみましょう。
$ cat apple3.csv
りんご,1285,1285,6000,名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
りんご,1285,1285,4000,名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
$ /usr/local/Cellar/mecab/0.996/libexec/mecab/mecab-dict-index -d /usr/local/lib/mecab/dic/ipadic -u apple3.dic -f utf-8 -t utf-8 apple3.csv
reading apple3.csv ... 2
emitting double-array: 100% |###########################################|
done!
$ echo りんごジュース | mecab -F %m\\t%c\\t%H\\n -u apple1.dic,apple2.dic,apple3.dic -N6
りんご 4000 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りんご 5000 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りんご 6000 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りん 4705 副詞,助詞類接続,*,*,*,*,りん,リン,リン
ご 6655 接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りんご 7277 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
りんご 8000 名詞,一般,*,*,*,*,りんご,リンゴ,リンゴ
ジュース 3637 名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
EOS
3つの辞書に登録した4つのりんごと、システム辞書に元々あったりんごが全部使われていますね。
NBest解に登場する順番もシンプルに生起コストの順番になっています。
ユーザー辞書で指定した順番に上書きされて最後の辞書の一番最後の単語しか残らないんじゃ無いか、みたいなことを懸念していましたが、そんなことは全くありませんでした。