MeCabの制約付き解析モードを利用する
MeCabの制約付き解析モードを利用する
やりたいこと
標準の辞書だけだと、どうしても不要な単語まで分割してしまう。
かといって、辞書ファイルの内容をいじるのは割と手間がかかる作業だ。
そこで、「制約つき解析モード」を利用することにした。工藤さんによる解説
やったこと
- 形態素境界制約つき(任意の場所にインデックスで境界を指定できる)で分割してみる
- 入力フォーマットを工夫して制約付き解析にする
形態素境界制約つきの単語分割をする
python wrapperで制約付きモードを試してみた記事にyukinoiさんの記事があった。
MeCabの単語境界を明示的にして単語分割するモードをPythonで呼び出す方法を解説している。
試してみるものの。。。こける。。。
どうも
end_position = start_position + len(token.encode(charset))
の行でエンコードエラーが起きているらしい。
よく考えてみれば、入力はutf-8なのだから、わざわざエンコードする必要はあるのかな・・・・?と思い、
end_position = start_position + len(token)
に書き換えてみた。
動いた。
システムに組み込もうとしてみる
紹介記事では、2次元のリストで、入力文を与えているため、システム的に使おうと思うと、2次元リストにしないといけない。
しかも、既知の単語があった場合は、適時リストに分割していく必要がある。(つまり、既知の単語を探索しながら、unicode→リストに放り込むという作業が必要になる)
いろいろ考えてみたが、正規表現でなんとかなった。
import re s = "めちゃめちゃいけてるに出ているよい子の濱口はよく海に行く人でした。" split_list = re.split(r'(めちゃめちゃ|よい子の濱口)', s) for i in labeled_tokens: print i[0]
とすると、
めちゃめちゃ いけてるに出ている よい子の濱口 はよく海に行く人でした。
と分割できる。成功だ。
解析結果も
めちゃめちゃ 名詞,形容動詞語幹,*,*,*,*,めちゃめちゃ,メチャメチャ,メチャメチャ いけてるに出ている 名詞,一般,*,*,*,*,* よい子の濱口 名詞,一般,*,*,*,*,* はよく海に行く人でした。 名詞,サ変接続,*,*,*,*,* BOS/EOS,*,*,*,*,*,*,*,*
となってうまくいった。。。
かのように見えるが。。。
このコードはうまくいく時とうまくいかない時があって、非常に謎。
例えば、
import re s = "月がーでたでったーよいよいよであらっさのほいほいほい" split_list = re.split(r'(よいよいよ|よい子の濱口)', s) labeled_tokens = [[item] for item in split_list if item != ''] for node in tagger.feature_constraint_parse(labeled_tokens): print node.surface, node.feature
で試してみると、
月がーでたでったー 感動詞,*,*,*,*,*,*
しか出てこない。
どうやら、unicodeとutf-8の変換のところでしくじっており、正しい境界で切れていないらしい。
その他、文字化けが頻発したりしたので、諦めた。
もっと安直な制約付き解析にする
せっかく-p
モードが用意されているので、これを使ってしまうことにする。
再掲になるが、工藤さんによる解説
ポイントは
- 制約をつけたい単語はタブ区切りで記述(単語\t品詞)
- 普通にラティスを展開してほしいところは何もつけない
- 文の最後にはEOSを記述すること
の3つ。
この3点を踏まえて動かしてみると、
import MeCab # インスタンス作成時に-pをつけておく m = MeCab.Tagger("-Ochasen -p") print m.parse("月\t名詞\nがーでたでったーよいよいよ\t感動詞\nであらっさ\t感動詞\nのほいほいほい\nEOS")
月 ツキ 月 名詞-一般 がーでたでったーよいよいよ がーでたでったーよいよいよ がーでたでったーよいよいよ 感動詞 であらっさ であらっさ であらっさ 感動詞 の ノ の 助詞-連体化 ほ ホ ほる 動詞-自立 五段・ラ行 体言接続特殊2 い イ いる 動詞-非自立 一段 連用形 ほ ホ ほる 動詞-自立 五段・ラ行 体言接続特殊2 い イ いる 動詞-非自立 一段 連用形 ほ ホ ほる 動詞-自立 五段・ラ行 体言接続特殊2 い イ いる 動詞-非自立 一段 連用形 EOS
となり、きちんと制約つけながら分割できた。
(文字列を整えたりするのに、きたないコードになったけど、そこはご愛嬌)