MeCab
MeCab (和布蕪)
オープンソースの形態素解析エンジン。条件付き確率場(CRF: Conditional Random Fields)でパラメータ推定されており、比較的高速な形態素解析が可能。MeCab導入の際、参考にしたページのリンクを貼っておく。
MeCab: Yet Another Part-of-Speech and Morphological Analyzer
インストール (Windows)
http://sourceforge.net/projects/mecab/files/からmecab本体をダウンロードする。Windowsなら自己解凍インストーラを実行するだけ。Windows版にはIPA辞書が含まれている。Windows 7なら、コントロールパネルで「環境変数」で検索すると、[システムの環境変数の編集]という項目が出てくるので、[システムの環境変数の編集]->[環境変数]でMeCab/bin/にパスを通す。
インストール(Ubuntu)
インストールしたマシンのシステムの情報を一応示しておく。
$ uname -a Linux vela 2.6.38-8-generic-pae #42-Ubuntu SMP Mon Apr 11 05:17:09 UTC 2011 i686 i686 i386 GNU/Linux
本体のインストール。デフォルトだとJUMAN辞書が含まれているみたい。
$ sudo apt-get install mecab
$ sudo apt-get install mecab-ipadic
おそらくデフォルトだと辞書はeuc-jpになっている。utf-8に変えたいときは次のようにする(IPA辞書の場合)。JUMANのほうを変えたいなら、ipadicのところをjumanに変えるだけでいいと思う。
$ sudo /usr/lib/mecab/mecab-dict-index -d /usr/share/mecab/dic/ipadic/ -o /var/lib/mecab/dic/ipadic/ -f euc-jp -t utf-8 -p
辞書の切り替えは次のようにする。
$ sudo update-alternatives --config mecab-dictionary alternative mecab-dictionary (/var/lib/mecab/dic/debian を提供) には 2 個の選択肢があります。 選択肢 パス 優先度 状態 ------------------------------------------------------------ * 0 /var/lib/mecab/dic/ipadic 70 自動モード 1 /var/lib/mecab/dic/ipadic 70 手動モード 2 /var/lib/mecab/dic/juman 30 手動モード 現在の選択 [*] を保持するには Enter、さもなければ選択肢の番号のキーを押してください:
使い方
コマンドプロンプトでmecabと打って、解析したい文を入力するだけ。ちゃんとインストールされていて、パスが通っていたら下のようになるはず。
>mecab
すもももももももものうち
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS
分かち書きしたいときは、-Owakatiオプションをつける。
>mecab -Owakati 飛ばねぇ豚はただの豚だ。 飛ば ねぇ 豚 は ただ の 豚 だ 。
読みだけほしい場合は、-Oyomiオプションをつける
>mecab -Oyomi 「時鳥」ってどう読むの? 「ホトトギス」ッテドウヨムノ?
Nbestがほしい場合は、-Nオプションを使う。下は、読みの3ベストを表示する例.
>mecab -Oyomi -N3 猜疑に歪んだ暗い瞳がせせら笑う。 サイギニユガンダクライヒトミガセセラワラウ。 サイギニヒズンダクライヒトミガセセラワラウ。 サイギニイガンダクライヒトミガセセラワラウ。
Chasen形式で出力したいときは、-Ochasenオプションを使う。
>mecab -Ochasen はぐれ刑事純情派 はぐれ ハグレ はぐれる 動詞-自立 一段 連用形 刑事 ケイジ 刑事 名詞-一般 純情 ジュンジョウ 純情 名詞-一般 派 ハ 派 名詞-接尾-一般 EOS
デフォルトでは未知語に対して適当に品詞推定が行われるが、推定をやめたい場合は-x (--unk-feature)オプションを使う。
>mecab ロムスカ・パロ・ウル・ラピュタ ロムスカ・パロ・ウル・ラピュタ 名詞,固有名詞,組織,*,*,*,* EOS >mecab -x "未知語" ロムスカ・パロ・ウル・ラピュタ ロムスカ・パロ・ウル・ラピュタ 未知語 EOS
引数にファイル名を指定すると、そのファイルを解析対象とする。また、-o (--output)=FILEオプションをつけると出力ファイルを指定できる。
>mecab INPUT -o OUTPUT
ラティス中の全形態素を出力するときは-aオプションを使う。
また、どの程度ラティスを作るかのレベル指定ができる-l0(高速,デフォルト),-l1(Nbestが出せるくらい,中速),-l2(低速)
>mecab -a -l2
g++ (Ubuntu)で使う場合
※ログ取り忘れたので間違っているかもしれないが、libmecab-devを入れとく必要がある。
コンパイルするときは、
% g++ -O2 `mecab-config --cflags` example.cpp -o example `mecab-config --libs`
Visual C++で使う場合
プロジェクトのプロパティで、[C++]->[追加のインクルードディレクトリ]と、[リンカ]->[追加のライブラリディレクトリ]にMeCab/sdk/を加える。そして、[リンカ]->[入力]->[追加の依存ファイル]でMeCab/sdk/libmecab.libを指定する。
※ライブラリのパス指定をするとき、パスにスペースが含まれているときは、ダブルコーテーションでくくる。
※構成(Debug)、(Release)ごとに設定できるようになっているので注意する
コード
ほとんどMeCab: Yet Another Part-of-Speech and Morphological Analyzerのサンプルと同じ。
注意 CのAPIとの違い
mecab_t が MeCab::Tagger
mecab_node_t が MeCab::Node
mecab_new() が MeCab::createTagger() ファクトリ関数
mecab_destroy () はなく,delete を呼んで開放する
※Nbestを出すときはMeCab::createTagger()で-l1(2)オプションを渡しておく
#include <iostream> #include <mecab.h> inline void mecab_check(MeCab::Tagger *tagger){ if( !tagger ) throw MeCab::getTaggerError(); } template<typename T> inline void mecab_check(T eval, MeCab::Tagger *tagger){ if( !eval ) throw ( tagger ? tagger->what() : MeCab::getTaggerError() ); } //サンプルのマクロ //#define MECAB_CHECK(eval) if (! eval) { \ // const char *e = tagger ? tagger->what() : MeCab::getTaggerError(); \ // std::cerr << "Exception:" << e << std::endl; \ // delete tagger; \ // return -1; } int main(int argc, char* argv[]){ char input[1024] = "流派東方不敗は!王者の風よ!全新系列!天破侠乱!見よ!東方は赤く燃えている!"; MeCab::Tagger *tagger = MeCab::createTagger(argc, argv); const int NBEST = 3; try{ mecab_check(tagger); const char *result; result = tagger->parse( input ); mecab_check( result, tagger ); std::cout << "RESULT" << std::endl << result << std::endl; //Nbest解を得るにはlオプションが必要 result = tagger->parseNBest( NBEST, input ); mecab_check( result, tagger ); //MECAB_CHECK(result); std::cout << "NBEST" << std::endl << result << std::endl; //Nbest分一気に出る //解析結果をもっともらしい順に取得する際の初期化 mecab_check( tagger->parseNBestInit( input ) , tagger); //tagger->next()でnbestをたどる for(int i=0; i< NBEST; i++ ) std::cout << i+1 << " best:" << std::endl << tagger->next() << std::endl; //解析結果をMeCab::Node*型で返す MeCab::Node* node = (MeCab::Node*)tagger->parseToNode( input ); mecab_check( node, tagger ); for( ; node; node = node->next ){ std::cout << "Node ID:" << node->id << ' '; switch( node->stat ){ case MECAB_NOR_NODE: break; //NOR = normal case MECAB_BOS_NODE: std::cout << "Begin of Sentence "; break; case MECAB_EOS_NODE: std::cout << "End of Sentence "; break; case MECAB_UNK_NODE: std::cout << "(Unknown Word)"; //break; default: //node->surfaceからnode->lengthだけ出すようにしないといけない std::cout.write( node->surface, node->length ); } std::cout << ' ' << node->feature //素性(CSV形式) << ' ' << (int)(node->surface - input) << ' ' << (int)(node->surface - input + node ->length ) << ' ' << node->rcAttr //右コンテキストid << ' ' << node->lcAttr //左コンテキストid << ' ' << node->posid //形態素id << ' ' << (int)node->char_type //文字種情報 << ' ' << (int)node->stat //形態素の種類 << ' ' << (int)node->isbest //1best ? 0 : 1 << ' ' << node->alpha //forward log 確率 << ' ' << node->beta //backword log 確率 << ' ' << node->prob //周辺確率 << ' ' << node->wcost //単語生起コスト << ' ' << node->cost << std::endl; //累積コスト } }catch(const char* str){ std::cerr << "Exception: " << str <<std::endl; delete tagger; return 1; } return 0; }