概要

「日本テレビ東京」

この実際には存在しない、どこで切り分ければ良いのかよく分からない言葉を、あなたが形態素解析するとしたら、どんな風に分かちますか?

おそらく以下の3つのどれかを考えるのではないでしょうか。

日本テレビ東京
日本テレビ東京
日本テレビ東京

今回はこの言葉の解析をMeCab+NAIST辞書にお願いして、結果を分析することで、MeCabが行っているコスト計算について勉強してみたいと思います。

@CretedDate 2009年10月頃
@Env MeCab0.98 NAIST辞書 0.6.1-20090630

とりあえず実行してみる

さっそくMeCabに「日本テレビ東京」を解析してもらいましょう。

$ echo 日本テレビ東京 | mecab

日本	名詞,固有名詞,地域,国,*,*,日本,ニッポン,ニッポン,,
テレビ東京	名詞,固有名詞,組織,*,*,*,テレビ東京,テレビトウキョウ,テレビトーキョー,,
EOS

「日本 | テレビ東京」と分けていますね。視聴率的には負けていますが、NAIST辞書的には日本テレビよりもテレビ東京が優先されたようです。

ちなみに「フジテレビ東京」ではどうなるでしょうか。

$ echo フジテレビ東京 | mecab

フジテレビ	名詞,固有名詞,組織,*,*,*,フジテレビ,フジテレビ,フジテレビ,,
東京	名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー,,
EOS

どうやらNAIST辞書的な順位は、「フジテレビ > テレビ東京 > 日本テレビ」となるようです。

では、解析する文字列が「日本テレビ東京支部」だった場合はどうなるでしょう。

$ echo 日本テレビ東京支部 | mecab

日本テレビ	名詞,固有名詞,組織,*,*,*,日本テレビ,ニホンテレビ,ニホンテレビ,,
東京	名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー,,
支部	名詞,一般,*,*,*,*,支部,シブ,シブ,,
EOS

ちゃんと人間が考えるような、「日本テレビ | 東京 | 支部」に解析してくれました。頭いいですね。

ところで、上の例は全て最良の解のみを出力していますが、MeCabには良いと思った解析方法を上位から指定件数出力する機能があります。

試しに上位3件を出力するように引数を設定して、「日本テレビ東京」を解析すると、どうなるでしょう。

$ echo 日本テレビ東京 | mecab -N3

日本	名詞,固有名詞,地域,国,*,*,日本,ニッポン,ニッポン,,
テレビ東京	名詞,固有名詞,組織,*,*,*,テレビ東京,テレビトウキョウ,テレビトーキョー,,
EOS

日本テレビ	名詞,固有名詞,組織,*,*,*,日本テレビ,ニホンテレビ,ニホンテレビ,,
東京	名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー,,
EOS

日本	名詞,固有名詞,地域,国,*,*,日本,ニッポン,ニッポン,,
テレビ	名詞,一般,*,*,*,*,テレビ,テレビ,テレビ,,
東京	名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー,,
EOS

惚れ惚れするような結果ですね。最初に私が書いた「人間が考えそうな3つの分け方」を見事に答えてくれました。

単語ごとのコストに関する説明

MeCabは辞書ファイルに設定されたコスト値を読み取り、指定された文章の解析可能なパターンの中で、最もコストが低い順序を採用することで単語を分割しています。

では、各テレビ局名のコスト値は、辞書ファイルの中ではどう設定されているのでしょう。

各単語のコスト値は、NAIST辞書では以下のファイルに記載されています。

/usr/local/lib/mecab/dic/naist-jdic/naist-jdic.csv

上記ファイルから関連がありそうな文字を引っ張り出してみると、下記のような設定になっていました。

テレビ東京,1352,1352,4752,名詞,固有名詞,組織,*,*,*,テレビ東京,テレビトウキョウ
日本テレビ,1352,1352,2988,名詞,固有名詞,組織,*,*,*,日本テレビ,ニホンテレビ
フジテレビ,1352,1352,4146,名詞,固有名詞,組織,*,*,*,フジテレビ,フジテレビ

テレビ,1345,1345,3307,名詞,一般,*,*,*,*,テレビ,テレビ
日本,1354,1354,3606,名詞,固有名詞,地域,国,*,*,日本,ニッポン
フジ,1345,1345,5226,名詞,一般,*,*,*,*,フジ,フジ
フジ,1352,1352,3572,名詞,固有名詞,組織,*,*,*,フジ,フジ
東京,1353,1353,3188,名詞,固有名詞,地域,一般,*,*,東京,トウキョウ

コスト値は4つ目のフィールド、テレビ東京なら4752(証券コードみたいですね)と記述されています。

コスト値は低いものほど優先されるはずですが、意外なことに上で解析した時に最も優先度が低かったはずの日本テレビが一番コスト値が低く(2988)なっています。

連接コストに関する説明

どうしてコスト的に低いはずの日本テレビよりも、テレビ東京が優先される結果が返って来たのか。

その理由は連接コストという要素が絡んでくるからです。連接コストは、その単語と隣の単語の左文脈IDと右文脈IDを見て、繋がりやすさからコストを上下させる機能です。

例えば「姓」の後には「名」が来やすい(連接コスト、-6659)けど、「名」の後に「姓」が来るパターンはそれほど多くはない(連接コスト、41)と設定されているとか、「国」の後には「地域」が来やすい(連接コスト、-6966)など、各文脈IDごとにコストが割り振られています。

実際に連結コストにどのような値が割り振られているかは、matrix.defを参照してください。

/usr/local/lib/mecab/dic/naist-jdic/matrix.def

以下はmatrix.defから「姓」(1350)「名」(1351)の連結コストを抜き出したものです。

1350 1351 -6659
1351 1350 41
また、「国」(1354)「地域」(1363)の連結コストは以下のようになっています。
1354 1363 -6966
1363 1354 1062

地域 → 国の順序で連結するケースはかなり少ない(+1062)ものと見て設定されているようです。

ちなみにNAIST辞書の文脈IDは、1377個あります。で、それぞれのIDがそれぞれのID(自身を含む)に対する連接コストを持たなければいけないので、matrix.defに設定してある対応関係は「1377 * 1377 = 1896129個」になります。

ひゃくはちじゅうまん……。とりあえず手動ではとても管理できないボリュームです。

コストが見える引数を指定して結果を見てみる

MeCabにはその単語を解析するのにかかったコストを表示してくれる機能があります。

フォーマット用パラメータの以下の子たちがそうです。

%pw : 単語生起コスト。上で説明した「naist-jdic.csv」に書いてあるコスト値と同じ。
%pc : 連接コスト + 単語生起コスト (文頭から累積)。詳細は後述。
%pn : 連接コスト + 単語生起コスト (その形態素単独)

フォーマットの詳しい話は、こちらが参考になります
http://mecab.sourceforge.net/format.html

というわけで、その辺りを設定してMeCabを実行してみます。

フォーマットは「%m,%phl,%phr,%pw,%pc,%pn\n」を設定します。これを設定すると、「表層文字,左ID,右ID」の後ろに、上で説明した3つのコストが出力されます。また、解析結果は2つまで表示しています。

echo 日本テレビ東京 | mecab -F"%m,%phl,%phr,%pb,%pw,%pc,%pn\n" -N2

日本,1354,1354,3606,2610,2610
テレビ東京,1352,1352,4752,4604,1994
EOS

日本テレビ,1352,1352,2988,1969,1969
東京,1353,1353,3188,4383,2414
EOS

上のままだと見づらいので、結果を表にしてみましょう。

解析結果
表層文字列左文脈ID右文脈ID単語生起コスト連接+生起(累積)連接+生起(単独)
日本13541354360626102610
テレビ東京13521352475246041994

naist-jdic.csvの当該単語のスコア情報を見てみると、以下のように設定されていました。

naist-jdic.csvの記述
表層文字左文脈ID右文脈ID単語生起コスト
日本135413543606
テレビ東京135213524752

naist-jdic.csvの「日本」と「テレビ東京」の単語生起コストが、「解析結果」の値と等しくなっていることが分かります。

次に連接コストについて。matrix.devには連接コストは以下のように記述されています。

matrix.devの記述
左文脈ID右文脈ID連接コスト
01354-996
13541352-2758
13520-941

連接コストは、1354, 1352以外に0も必要になります。0はBOS/EOS。つまり文頭と文末を意味します。文頭の言葉(今回は日本)は、自身の左に文脈IDが0の値がいるものとして計算されます。

連接コストも計算にいれて、「日本」の「連接+生起」コストを計算すると、3606 + -996 = 2610になります。これは「解析結果」に表示されている「日本」の「連接+生起」コストと等しいことが分かります。

次に「テレビ東京」の「連接+生起」コストは、テレビ東京自身の単語生起コストの4752に、「1354 → 1352」の連結コスト-2758を足すことになるので、4752 + -2758 = 1994になります。「解析結果1」の「連接+生起(単独)」と等しい値になっていますね。

また「テレビ東京」の「連接+生起(累計)」は「日本」と「テレビ東京」のコストを足した、「2610 + 1994 = 4604」になっています。

最後に、これは「解析結果」の出力には表示されていませんが、EOS(文末)への遷移もコストに加える必要があります。EOSの単語生起コストは0なので、文脈ID「1352 → 0」の遷移の分だけ加算します。

というわけで、最終的なコストは「4604 + -941 = 3663」になります。

計算式まとめ

「日本の生起コスト」 + 「文脈ID 0 → 1354の連結コスト」 = 「日本までのコスト」 ⇒ 3606 + -996 = 2610

「テレビ東京の生起コスト」 + 「文脈ID 1354 → 1352の連結コスト」 = 「テレビ東京のコスト」 ⇒ 4752 + -2758 = 1994

「BOS/EOSのコスト」 + 「文脈ID 1352 → 0の連結コスト」 = 「文末のコスト」 ⇒ 0 + -941 = -941

3つのコストを加算したものが、そのルートの総コスト ⇒ 2610 + 1994 + -941 = 3663

次善の解析結果のコスト

では、次善の解析結果、「日本テレビ | 東京」に分割する場合のコストはどうなるでしょう。

先ほどと同じように表にしてみます。

解析結果
表層文字列左文脈ID右文脈ID単語生起コスト連接+生起(累積)連接+生起(単独)
日本テレビ13521352298819691969
東京13531353318843832414

単語生起コスト(naist-jdic.csvに記述)は、上表の単語生起コストの値と同じだということが分かっているので省きます。

matrix.devの記述
左文脈ID右文脈ID連接コスト
01352-1019
13521353-774
13530-658

以上のデータがあれば、計算可能ですね。

次善の解析結果のコストを計算してみる

日本テレビのコスト ⇒ 2988 + -1019 = 1969

東京のコスト ⇒ 3188 + -774 = 2414

文末のコスト ⇒ 0 + -658 = -658

総コスト ⇒ 1969 + 2414 + -658 = 3725

というわけで、次善の結果の総コストは3725になります。1つ目の解析結果は3663だったので、僅かに2つ目よりコストが低くなっています。

4回も計算しなくても、4383 - 658で一発じゃないかと思った方。その通りです。

実際にはMeCabさんはこの2つだけでなく、「日 | 本 | テ | レ | ビ | 東 | 京 」とか「日本 | テレビ | 東 | 京」など、考えられる全てのパターンを探索してくれています。

MeCabがどのレベルまでパターンを考えているか体感したい場合は、以下のコマンドが有効です。

$ echo 日本テレビ東京 | mecab -Odump

大量の解析に関わるdumpが出力されます。

まとめ

以上、「日本テレビ東京で学ぶMeCabのコスト計算」でした。

筆者はこれまでMeCabを使う際に、漠然とコストが関わってるのだなぁとしか考えておらず、どの数値をどう計算しているかも知らなかった為、この記事を書いて勉強になりました。

MeCabの計算はこれだけではなく、引数に「-l2」を付けると素敵な素敵な周辺確率の世界にも突入できますが、その辺りはまた、別の機会にということで。