MeCabに制約付き解析(部分解析)という機能があるのでそのメモです。
参考: 制約付き解析(部分解析)
入力文の一部の形態素情報が既知である、あるいは境界がわかっているときに、 それを満たすように解析する機能です。
と書いてある通り、一部の形態素情報がわかっているときにそれを満たすように解析します。例えば、IPA辞書には「クラウド」という単語が無いので、IPA辞書を使って「クラウド」を含むテキストを分解すると「クラ」と「ウド」という2単語に分かれて出てきます。(実はN-Best解を表示していくとその中には未知語の「クラウド」として出力してくれるものも出てくるのですが。)
import MeCab
tagger = MeCab.Tagger()
print(tagger.parse("このブログはクラウド環境で動いています"))
"""
この 連体詞,*,*,*,*,*,この,コノ,コノ
ブログ 名詞,一般,*,*,*,*,*
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
クラ 名詞,固有名詞,一般,*,*,*,クラ,クラ,クラ
ウド 名詞,一般,*,*,*,*,ウド,ウド,ウド
環境 名詞,一般,*,*,*,*,環境,カンキョウ,カンキョー
で 助詞,格助詞,一般,*,*,*,で,デ,デ
動い 動詞,自立,*,*,五段・カ行イ音便,連用タ接続,動く,ウゴイ,ウゴイ
て 助詞,接続助詞,*,*,*,*,て,テ,テ
い 動詞,非自立,*,*,一段,連用形,いる,イ,イ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
EOS
"""
本来は、「クラウド」を辞書登録するべきなのですが、応急処置として、今回の文書では「クラウド」は1単語だよ、と明示できるのが制約付き解析です。
使い方は簡単で、次の二つを変更するだけです。
– MeCab起動時に -p (–partial) オプションをつける。(Pythonの場合はTagger生成時に”-p”を指定)
– 解析結果を指定したい部分は、「表層\t素性パターン」という形式で記入する。
「表層\t素性パターン」になっていない行は文断片とみなされ、普通に形態素解析されます。
素性パターン はワイルドカードとして * (アスタリスク)を使っても良いですし、名詞などとしても良いようです。「*,非自立」のようにして品詞の第二分類が非自立のものといった指定もできます。また、実は任意の文字列を設定することもでき、その場合は設定した文字列がそのまま出てきます。動詞や形容詞など品詞の一種であっても未知語処理の都合上、その文字列に当てはまらない品詞だった場合はそのまま表示されるようです。
とりあえずワイルドカードで「クラウド」だけ指定してやってみます。
tagger = MeCab.Tagger("-p")
print(tagger.parse(
"""
このブログは
クラウド\t*
環境で動いています。
"""
))
"""
この 連体詞,*,*,*,*,*,この,コノ,コノ
ブログ 名詞,一般,*,*,*,*,*
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
クラウド 名詞,一般,*,*,*,*,*
環境 名詞,一般,*,*,*,*,環境,カンキョウ,カンキョー
で 助詞,格助詞,一般,*,*,*,で,デ,デ
動い 動詞,自立,*,*,五段・カ行イ音便,連用タ接続,動く,ウゴイ,ウゴイ
て 助詞,接続助詞,*,*,*,*,て,テ,テ
い 動詞,非自立,*,*,一段,連用形,いる,イ,イ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
"""
「クラウド」が一単語としてみなされましたね。今回指定した「クラウド」は未知語なので読みなどは出てきませんが、制約付き解析で指定した単語が辞書にある場合はちゃんと読みも出てきます。
さて、ここからが応用です。前回の記事でN-Best解表示時のコスト計算にバグがある、という話を書いていますが実はこの制約付き解析を使うと、正しいコストが出力できます。
この先は前回の記事と見比べながら読んでください。
参考: MeCabのN-Best解のコストがどこで間違っているのか確認した
前回の記事では「すもももももももものうち」の4つ目の解析結果を取り上げました。
$ mecab -N 4 -E EOS\\t%pc\\n
すもももももももものうち
#####################################
#1~3個目の結果は省略します。以下は4番目の解。#
#####################################
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS 21245
この、 21245は1個目のN-Best解の累積コストであって、4番目の解の累積コストでは無いのですが、そのずれの原因が、連接コストの1箇所が本当は 478 なのに、-4203 として計算されてしまっていることを確認したのでした。(詳細は前回の記事。)
ということは、本当のこの解のコストの総和は、 $21245 + (478-(-4203)) = 25926$ のはずです。
これが実は制約付き解析を使うと出力できます。
やり方は簡単で、コストの表示と制約付きを指定して起動したMeCabに、N-Best解で表示された文字列を渡すだけです。
tagger = MeCab.Tagger(
"-p" +
" -F %m\\t%s\\t%phl\\t%phr\\t%c\\t%pC\\t%pn\\t%pc\\t%H\\n" +
" -E EOS\\t%s\\t%phl\\t%phr\\t%c\\t%pC\\t%pn\\t%pc\\tEOS\\n")
print(tagger.parse(
"""すもも\t名詞,一般,*,*,*,*,すもも,スモモ,スモモ
もも\t名詞,一般,*,*,*,*,もも,モモ,モモ
も\t助詞,係助詞,*,*,*,*,も,モ,モ
も\t助詞,係助詞,*,*,*,*,も,モ,モ
もも\t名詞,一般,*,*,*,*,もも,モモ,モモ
の\t助詞,連体化,*,*,*,*,の,ノ,ノ
うち\t名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ"""
))
# 以下出力結果
"""
すもも 0 1285 1285 7546 -283 7263 7263 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
もも 0 1285 1285 7219 62 7281 14544 名詞,一般,*,*,*,*,もも,モモ,モモ
も 0 262 262 4669 -4158 511 15055 助詞,係助詞,*,*,*,*,も,モ,モ
も 0 262 262 4669 478 5147 20202 助詞,係助詞,*,*,*,*,も,モ,モ
もも 0 1285 1285 7219 17 7236 27438 名詞,一般,*,*,*,*,もも,モモ,モモ
の 0 368 368 4816 -4442 374 27812 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 0 1313 1313 5796 -5198 598 28410 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS 3 0 0 0 -2484 -2484 25926 EOS
"""
前回の記事に倣って、それぞれの単語の生起コストや各単語間の連接コストも全部表示したので、かえって見にくくなってて申し訳ないのですが、最終的な累積コストとして25926が出てきましたね。