今回もMeCabの話です。
今回はMeCabの出力の形式をカスタマイズする方法を紹介します。
何もオプションを指定しなかった場合の出力形式については以前記事にしたことがあります。
参考: MeCabの出力フォーマット
MeCabを起動する時に引数で指定するか、mecabrc 特定の記法で記載することで、この出力形式を変更することができます。ドキュメントはこちらです。
参考: 出力フォーマット
正直、ドキュメントを読んでいただければ大体わかると思うのですが、この記事では上記のドキュメントに書いてないことや、実際に動かした場合の挙動などを中心に紹介したいと思います。
コマンドラインの引数で指定できるオプションは以下の4種類です。
–node-format ・・・ 形態素の出力
–bos-format ・・・形態素の前に出力される文頭記号(ヘッダー)
–eos-format・・・ 形態素の後に出力される文末記号(フッター)
–unk-format・・・ 未知後の出力。指定しないと形態素と同じ形式
ドキュメント上は、 –eon-format という、 N-best出力で, N-Bestの出力が終了したときに出力する形式を指定するオプションも掲載されているのですが、これを指定してN-Best解を出力させても何も変化がありませんでした。実装されていないのかな。(version は mecab of 0.996 で確認しました。) => (追記)未実装の機能だと思っていたのですが、 –eos-format と一緒に指定すると、 –eno-format も動作しました。–eno-format単体だと動かない理由は謎です。(追記ここまで)
このまま名前では長いですが、それぞれ一文字のエイリアスがふられています。これは mecabコマンドのヘルプを見るとわかります。該当部分だけ抜粋したのが以下です。
$ mecab --help | grep STR
-F, --node-format=STR use STR as the user-defined node format
-U, --unk-format=STR use STR as the user-defined unknown node format
-B, --bos-format=STR use STR as the user-defined beginning-of-sentence format
-E, --eos-format=STR use STR as the user-defined end-of-sentence format
-S, --eon-format=STR use STR as the user-defined end-of-NBest format
-x, --unk-feature=STR use STR as the feature for unknown word
-F や -E などの方が短くて使いやすそうですね。 また、 –unk-feature という ドキュメントになかったオプションがあることもわかります。
-U (–unk-format) と -x (–unk-feature) はどちらも未知後(辞書にない単語)の出力形式を指定するものですが、 -U は出力全体を指定し、 -x の方は表層形はそのまま出力し、品詞情報部分をSTRで指定した文字列で出力するという違いがあります。
「メロス」(メロスが未知後)で実験すると次のようになります。
$ mecab -U '未知語\n'
走れメロス
走れ 動詞,自立,*,*,一段,連用形,走れる,ハシレ,ハシレ
未知語
EOS
$ mecab -x '未知語'
走れメロス
走れ 動詞,自立,*,*,一段,連用形,走れる,ハシレ,ハシレ
メロス 未知語
EOS
-U では ‘未知語\n’ と改行コード付きで指定しました。そうしないと次の単語や文末の場合はEOSとの間が開業されず連結されてしまいます。一方で、 -x の方は 表層形の後に、通常品詞などが出てくる部分のみを書き換えます。また、デフォルトで出力後に改行をしてくれるので、-x で指定する文字列の末尾に改行コードをつける必要はありません.
さて、STRで指定する文字列ですが、上の例でお見せしたような固定文字列だけではなく、さまざまな変数が使えます。上のドキュメントに全部載っているのですが、個人的に使いそうなのだけ選んで紹介します。
%s ・・・形態素種類 (0: 通常, 1: 未知語, 2:文頭, 3:文末)
%m ・・・形態素の表層文字列
%c ・・・単語生起コスト
%H ・・・素性 (品詞, 活用, 読み) 等を CSV で表現したもの
%pC ・・・1つ前の形態素との連接コスト
%pc ・・・連接コスト + 単語生起コスト (文頭から累積)
%pn ・・・連接コスト + 単語生起コスト (その形態素単独, %pw + %pC)
%phl ・・・左文脈 id
%phr ・・・右文脈 id
%f[N] ・・・csv で表記された素性の N番目の要素
%f[N1,N2,N3…] ・・・N1,N2,N3番目の素性をタブ区切りで表示
%f[N1, N2, N3…] は素性を ‘,’をデリミタとして表示、とドキュメントに書いてありますが、実際は上の一覧に書いた通り、タブ区切りで出力されます。
$ mecab -F '%m\t%f[0,1,6]\n'
すもももももももものうち
すもも 名詞 一般 すもも
も 助詞 係助詞 も
もも 名詞 一般 もも
も 助詞 係助詞 も
もも 名詞 一般 もも
の 助詞 連体化 の
うち 名詞 非自立 うち
EOS
%c で出力される単語生起コストや、%pCで表示される連接コスト、その他、 %phl / %phr の文脈 IDなどの情報は、MeCabの仕様を理解する上で非常に役に立ちました。
この辺はまた改めて記事にまとめたいと思います。
%s を使うと、辞書にあった単語と、なかった未知語を見分けることができます。未知後を特定したい場合は -Uで指定するよりも、%s でフラグをつけた方が有効そうです。こんなふうに出力すると、「メロス」が未知語だったことがわかりますね。%Hのうしろに’,’区切りでつけてしまうと、何番目の要素が%s相当なのかわかりにくいので、タブ区切りにすとか、%Hの前に出力するのがおすすめです。
$ mecab -F '%m\t%s\t%H\n'
メロスは激怒した
メロス 1 名詞,一般,*,*,*,*,*
は 0 助詞,係助詞,*,*,*,*,は,ハ,ワ
激怒 0 名詞,サ変接続,*,*,*,*,激怒,ゲキド,ゲキド
し 0 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
た 0 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
EOS
-F や -U だけでなく、 -E (–eos-format)などでも上記の変数群は使うことができます。
ただし、 -B (–bos-format) は文頭のオプションなので、1つ前の形態素との連接コストなど、前の単語が存在する前提の情報を出力しようとするとエラーになります。気をつけましょう。
さて、僕はこのようなオプションを見るとデフォルト(未指定の場合)の指定はどのようになっているのかが気になるタイプの人です。
それで、ドキュメントを見ると次のように書いてあります。
わかち書き出力 (-Owakati), デフォルトの出力, 出力ダンプ (-Odump) は 高速性を犠牲にしたく ないために, ハードコーディングされています.
ハードコーディングされてるって情報しかなく、結局どう設定されているのかわかりませんね。ということで、ソースコード内のハードコーディングされている部分を探しました。
どうやら、 writer.cppファイルのこの部分のようです。
// default values
std::string node_format = "%m\\t%H\\n";
std::string unk_format = "%m\\t%H\\n";
std::string bos_format = "";
std::string eos_format = "EOS\\n";
std::string eon_format = "";
\\\\は\のエスケープなので、要するに、 “%m\t%H\n” ですね。僕はてっきり、
表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音
のような形式が指定されていると思っていたのですが、そんなことはなかったです。
この %H は素性等をCSVで指定したもの、と定義されていますが、実際は辞書内の文字列をそのまま表示しています。
ここまでコマンドラインでMeCabを使う場合の例を見てきましたが、もちろんこれらの設定はPythonライブラリからMeCabを使う場合も利用できます。
単純にTaggerオブジェクトを生成するときに辞書を指定すると同じように文字列で引数を渡すだけです。
試しに単語の生起コストも一緒に表示してみました。
import MeCab
# 生起コスト(%c)も表示する
tagger = MeCab.Tagger("-F %m\\t%c\\t%H\\n")
print(tagger.parse("すもももももももものうち"))
"""
すもも 7546 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 4669 助詞,係助詞,*,*,*,*,も,モ,モ
もも 7219 名詞,一般,*,*,*,*,もも,モモ,モモ
も 4669 助詞,係助詞,*,*,*,*,も,モ,モ
もも 7219 名詞,一般,*,*,*,*,もも,モモ,モモ
の 4816 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 5796 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS
"""