【R】RMeCabを使わずにRでMeCabする方法
ノートPCを買ってやりたかったことのひとつに「日本語の係り受け解析」があります。日本語の係り受け解析器は、有名なところでCabocha、KNPがあります。いずれもPythonバインディングが提供されており、Pythonから動作させることが可能です。
偉大な先人たちがいるじゃないですか。
その記述に従ってやってみるじゃないですか。
できないじゃないですかやだー。
彼らはいうわけですよ。
「俺の環境では動いたよ」
orz...
かれこれ2週間くらいあれこれやってみたんですが、結局良い解決策は見つからず、根本的にやり方を変えよう、と思い立ったわけです。「全然うまくいかなかった記録」は近々記事にしようと思います。が、その前にうまくいったやり方をご紹介します。簡単に言えば、
- MeCabをsystem()関数を使って実行し、結果をRで加工する
ことをやっています。「なんだそんだけかー」と思った方は以下、スルーしていただいて構いません。
とりあえずMeCabについてだけ書きますが、CabochaもjumanもKNPも同じです。ただし、KNPはちょっと特殊です。
今のところ、Rで日本語の係り受け解析ができるものはなさそう(RCabochaは開発中止になっているそうですし)なので、「Pythonバインディングがうまくいかない」「Pythonなんか大っ嫌いだ!」という方、お試しください。
目次
MeCabをインストールする
MeCab: Yet Another Part-of-Speech and Morphological Analyzer
こちらよりWindow用の.exeをダウンロードし、ダブルクリックでインストールしてください。文字コードはSHIFT-JISです。PythonバインディングするときはUFT-8推奨のようですが、それだとRで化け化けになるので、SHIFT-JISにしてください。Cabochaを使う場合も同様です。
インストールしたら忘れずにパスを通しておいてくださいね。
Windows10の場合、
- 左下のWindowsマークを右クリック
- 「システム」を選択
- システムウィンドウから「システムの詳細設定」をクリック
- 開いたウィンドウの右下「環境変数」をクリック
- システム環境変数の「Path」を選択して「編集」
で、インストールしたMeCabのフォルダ内のbinを追加すればOKです。
心配ならばコマンドプロンプトで「mecab」と打ってMeCabが動くか試してみてください。
MeCabにneologdを適用する
これは好みの問題ですが、個人的にはneologdを適用しておくことをお勧めします。
github.com
Windowsにneologdを入れる場合は上記をご参考に。ちなみに2016年10月26日時点でのneologd辞書になります。dicフォルダ内を入れ替えれば最新にできるんじゃないかと思っていますが、まだ試していません。そのうち試して記事にします。
cygwinでもできるっぽいんですが、いまいちうまくいきませんでした。
d.hatena.ne.jp
以上で準備は完了。
以降はすべて、Rで作業します。RStudioなり生Rなり、お好きなものでどうぞ。
早速やってみよう
system("cmd.exe", input = "echo これはテストです。 | mecab")
とすると、
Microsoft Windows [Version 10.0.14393] (c) 2016 Microsoft Corporation. All rights reserved. C:\Users\XXXXXXXX\Documents>echo これはテストです。 | mecab これ 名詞,代名詞,一般,*,*,*,これ,コレ,コレ は 助詞,係助詞,*,*,*,*,は,ハ,ワ テスト 名詞,サ変接続,*,*,*,*,テスト,テスト,テスト です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス 。 記号,句点,*,*,*,*,。,。,。 EOS C:\Users\XXXXXXXX\Documents>
おお!ちゃんと形態素解析してくれている!
(なんかいらんものもでてるけど。)
このままだと汎用性がないので、形態素解析する文を変数にいれてinputに入れるコマンドを文字列変数にしましょう。
input_text <- c("これはテストではありません。繰り返します。これはテストではありません。") command <- paste("echo",input_text,"| mecab") system("cmd.exe", input = command)
これで、
Microsoft Windows [Version 10.0.14393] (c) 2016 Microsoft Corporation. All rights reserved. C:\Users\XXXXXXXX\Documents>echo これはテストではありません。繰り返します。これはテストではありません。 | mecab これ 名詞,代名詞,一般,*,*,*,これ,コレ,コレ は 助詞,係助詞,*,*,*,*,は,ハ,ワ テスト 名詞,サ変接続,*,*,*,*,テスト,テスト,テスト で 助詞,格助詞,一般,*,*,*,で,デ,デ は 助詞,係助詞,*,*,*,*,は,ハ,ワ あり 動詞,自立,*,*,五段・ラ行,連用形,ある,アリ,アリ ませ 助動詞,*,*,*,特殊・マス,未然形,ます,マセ,マセ ん 助動詞,*,*,*,不変化型,基本形,ん,ン,ン 。 記号,句点,*,*,*,*,。,。,。 繰り返し 動詞,自立,*,*,五段・サ行,連用形,繰り返す,クリカエシ,クリカエシ ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス 。 記号,句点,*,*,*,*,。,。,。 これ 名詞,代名詞,一般,*,*,*,これ,コレ,コレ は 助詞,係助詞,*,*,*,*,は,ハ,ワ テスト 名詞,サ変接続,*,*,*,*,テスト,テスト,テスト で 助詞,格助詞,一般,*,*,*,で,デ,デ は 助詞,係助詞,*,*,*,*,は,ハ,ワ あり 動詞,自立,*,*,五段・ラ行,連用形,ある,アリ,アリ ませ 助動詞,*,*,*,特殊・マス,未然形,ます,マセ,マセ ん 助動詞,*,*,*,不変化型,基本形,ん,ン,ン 。 記号,句点,*,*,*,*,。,。,。 EOS C:\Users\XXXXXXXX\Documents>
と問題なく動作しました。
結果を解析する
とはいえ、コンソールに結果がかえってきても使えません。形態素解析の結果を変数に入れて使える状態にしましょう。
out_mec <- system("cmd.exe", input = command, intern=T)
最後のintern=Tで出力結果をRの変数に入れるように指定しています。変数out_mecの中身を表示すると、
[1] "Microsoft Windows [Version 10.0.14393]" [2] "(c) 2016 Microsoft Corporation. All rights reserved." [3] "" [4] "C:\\Users\\XXXXXXXX\\Documents>echo これはテストではありません。繰り返します。これはテストではありません。 | mecab" [5] "これ\t名詞,代名詞,一般,*,*,*,これ,コレ,コレ" [6] "は\t助詞,係助詞,*,*,*,*,は,ハ,ワ" [7] "テスト\t名詞,サ変接続,*,*,*,*,テスト,テスト,テスト" [8] "で\t助詞,格助詞,一般,*,*,*,で,デ,デ" [9] "は\t助詞,係助詞,*,*,*,*,は,ハ,ワ" [10] "あり\t動詞,自立,*,*,五段・ラ行,連用形,ある,アリ,アリ" [11] "ませ\t助動詞,*,*,*,特殊・マス,未然形,ます,マセ,マセ" [12] "ん\t助動詞,*,*,*,不変化型,基本形,ん,ン,ン" [13] "。\t記号,句点,*,*,*,*,。,。,。" [14] "繰り返し\t動詞,自立,*,*,五段・サ行,連用形,繰り返す,クリカエシ,クリカエシ" [15] "ます\t助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス" [16] "。\t記号,句点,*,*,*,*,。,。,。" [17] "これ\t名詞,代名詞,一般,*,*,*,これ,コレ,コレ" [18] "は\t助詞,係助詞,*,*,*,*,は,ハ,ワ" [19] "テスト\t名詞,サ変接続,*,*,*,*,テスト,テスト,テスト" [20] "で\t助詞,格助詞,一般,*,*,*,で,デ,デ" [21] "は\t助詞,係助詞,*,*,*,*,は,ハ,ワ" [22] "あり\t動詞,自立,*,*,五段・ラ行,連用形,ある,アリ,アリ" [23] "ませ\t助動詞,*,*,*,特殊・マス,未然形,ます,マセ,マセ" [24] "ん\t助動詞,*,*,*,不変化型,基本形,ん,ン,ン" [25] "。\t記号,句点,*,*,*,*,。,。,。" [26] "EOS" [27] "" [28] "C:\\Users\\XXXXXXXX\\Documents>"
このように、コンソールに表示された各行が一つの要素になったベクトルになっています。このベクトルの4行目までとEOSが入っている26行目以降は不要ですので、
#余計な行を削除 out_mec_red <- out_mec[seq(5,(1:length(out_mec))[out_mec=="EOS"]-1)]
で削除します。このままでは扱いづらいので、各要素をさらに細かく分解します。
strsplitをするのですが、区切り文字が"\t"と","の二つあるので、dplyrでパイプして、
library(dplyr) #結果を分割 out_mec_list <- lapply(out_mec_red, function(x){ out <- unlist(strsplit(x, split="\t")) %>% strsplit(split=",") return(unlist(out)) })
とすると、たとえばこのリストの第一要素は
[[1]] [1] "これ" "名詞" "代名詞" "一般" "*" "*" "*" "これ" "コレ" [10] "コレ"
となりました。ここまでくるとだいぶ分析しやすくなりました。
で、例えばここから名詞だけとりだし、名詞を半角スペースを空けて一つの文字列にするには、
#名詞だけ取り出す out_mec_noun <- unlist(sapply(out_mec_list, function(x){ if(x[2] == "名詞"){ return(x[1]) } })) #半角スペースを空けてひとつにつなげる out_sentense <- paste(out_mec_noun, collapse=" ")
とすれば詰みです。
[1] "これ テスト これ テスト"
ちなみにこうして半角スペースを空けた単語列にしておけば、日本語でもtext2vecで分析にかけられるのでとてもおトクです。
コードはこちら
以上のコードをひとまとめにしたのがこちらになります。
library(dplyr) # 解析したい文字列をベクトルに入れる input_text <- c("これはテストではありません。繰り返します。これはテストではありません。") # 実行コマンドと解析したい文字列をつなげる command <- paste("echo",input_text,"| mecab") # system関数で実行し、結果をR変数に代入 out_mec <- system("cmd.exe", input = command, intern=T) #結果を分割 out_mec_list <- lapply(out_mec_red, function(x){ out <- unlist(strsplit(x, split="\t")) %>% strsplit(split=",") return(unlist(out)) }) #名詞だけ取り出す out_mec_noun <- unlist(sapply(out_mec_list, function(x){ if(x[2] == "名詞"){ return(x[1]) } })) #半角スペースを空けてひとつにつなげる out_sentense <- paste(out_mec_noun, collapse=" ")
あとはTF-IDFとるなり、トピックモデルに突っ込むなり、word embeddingするなり、好きにしてください。
Cabochaも動く
その程度だったらRMeCabで十分じゃん!と思ったあなた、あなたは正しい。
でも、同じ方法でCabochaもできるんですよ。それだったらどうですか。
ちなみに、Cabochaをインストールしてパスを通しておけば、
out_cab <- system("cmd.exe", input="echo 明日は晴れるといいですね。 | cabocha -f", intern=T)
とすると、
[1] "Microsoft Windows [Version 10.0.14393]" [2] "(c) 2016 Microsoft Corporation. All rights reserved." [3] "" [4] "C:\\Users\\XXXXXXXX\\Documents>echo 明日は晴れるといいですね。 | cabocha -f1" [5] "* 0 1D 0/1 0.851092" [6] "明日\t名詞,副詞可能,*,*,*,*,明日,アシタ,アシタ" [7] "は\t助詞,係助詞,*,*,*,*,は,ハ,ワ" [8] "* 1 2D 0/1 0.851092" [9] "晴れる\t動詞,自立,*,*,一段,基本形,晴れる,ハレル,ハレル" [10] "と\t助詞,格助詞,引用,*,*,*,と,ト,ト" [11] "* 2 -1D 0/2 0.000000" [12] "いい\t動詞,自立,*,*,五段・ワ行促音便,連用形,いう,イイ,イイ" [13] "です\t助動詞,*,*,*,特殊・デス,基本形,です,デス,デス" [14] "ね\t助詞,終助詞,*,*,*,*,ね,ネ,ネ" [15] "。\t記号,句点,*,*,*,*,。,。,。" [16] "EOS" [17] "" [18] "C:\\Users\\XXXXXXXX\\Documents>"
とちゃんと係り受け解析してくれます。これでRでも日本語の係り受け解析ができます。やったね!
KNPも動くが細工が必要
KNPの場合、単純に
system("cmd.exe", input="echo 彼は本を買って家に帰った。 | juman | knp -tab")
とするとうまくいかず、
Microsoft Windows [Version 10.0.14393] (c) 2016 Microsoft Corporation. All rights reserved. C:\Users\XXXXXXXX\Documents>echo 彼は本を買って家に帰った。 | juman | knp -tab # S-ID:1 KNP:4.11-CF1.1 DATE:2017/01/09 SCORE:0.00000 ERROR:Cannot make mrph EOS ;; Invalid input (4 items)< \ \ 特殊 1 空白 6 * 0 * 0 NIL > ! C:\Users\XXXXXXXX\Documents>
とInvalid inputがかえってきて解析できません。これはコマンドプロンプトでも同じです。
なので、ちょっと細工して
system("cmd.exe", input="juman | knp -tab\n明日は晴れるといいですね。",intern=T,ignore.stderr=F)
としてあげるとうまくいきます。"juman | knp"でknpモードに入り、"\n"で区切って文字列を渡す、ということをやっています。これだったらうまくいきました。ignore.stderr=F"がポイント。
[1] "Microsoft Windows [Version 10.0.14393]" [2] "(c) 2016 Microsoft Corporation. All rights reserved." [3] "" [4] "C:\\Users\\XXXXXXXX\\Documents>juman | knp -tab" [5] "# S-ID:1 KNP:4.11-CF1.1 DATE:2017/01/09 SCORE:-9.46140" [6] "* 1D <文頭><時間><強時間><未来句><ハ><助詞><体言><係:未格><提題><区切:3-5><主題表現><格要素><連用要素><正規化代表表記:明日/あす><主辞代表表記:明日/あす>" [7] "+ 1D <文頭><時間><強時間><未来句><ハ><助詞><体言><係:未格><提題><区切:3-5><主題表現><格要素><連用要素><係チ:判定詞:T解析格-ガ><正規化代表表記:明日/あす><解析格:時間>" [8] "明日 あす 明日 名詞 6 時相名詞 10 * 0 * 0 \"代表表記:明日/あす カテゴリ:時間\" <代表表記:明日/あす><カテゴリ:時間><正規化代表表記:明日/あす><文頭><漢字><かな漢字><名詞相当語><自立><内容語><タグ単位始><文節始><文節主辞>" [9] "は は は 助詞 9 副助詞 2 * 0 * 0 NIL <かな漢字><ひらがな><付属>" [10] "* -1D <文末><ト><句点><助詞><用言:動><レベル:C><区切:5-5><ID:(文末)><係:文末><提題受:30><主節><格要素><連用要素><正規化代表表記:晴れる/はれる><主辞代表表記:晴れる/はれる>" [11] "+ -1D <文末><ト><句点><助詞><用言:動><レベル:C><区切:5-5><ID:(文末)><係:文末><提題受:30><主節><格要素><連用要素><正規化代表表記:晴れる/はれる><用言代表表記:晴れる/はれる><格関係0:時間:明日><格解析結果:晴れる/はれる:動7:ガ/U/-/-/-/-;ニ/U/-/-/-/-;デ/U/-/-/-/-;時間/N/明日/0/0/1;外の関係/U/-/-/-/-;修飾/U/-/-/-/-;ノ/U/-/-/-/->" [12] "晴れる はれる 晴れる 動詞 2 * 0 母音動詞 1 基本形 2 \"代表表記:晴れる/はれる 自他動詞:他:晴らす/はらす 反義:動詞:曇る/くもる\" <代表表記:晴れる/はれる><自他動詞:他:晴らす/はらす><反義:動詞:曇る/くもる><正規化代表表記:晴れる/はれる><かな漢字><活用語><自立><内容語><タグ単位始><文節始><文節主辞>" [13] "と と と 助詞 9 格助詞 1 * 0 * 0 NIL <かな漢字><ひらがな><付属>" [14] "いい いい いい 形容詞 3 * 0 イ形容詞イ段 19 基本形 2 \"代表表記:良い/よい 反義:形容詞:悪い/わるい\" <代表表記:良い/よい><反義:形容詞:悪い/わるい><正規化代表表記:良い/よい><かな漢字><ひらがな><活用語><付属>" [15] "です です です 助動詞 5 * 0 無活用型 26 基本形 2 NIL <かな漢字><ひらがな><活用語><付属>" [16] "ね ね ね 助詞 9 終助詞 4 * 0 * 0 NIL <表現文末><かな漢字><ひらがな><付属>" [17] "。 。 。 特殊 1 句点 1 * 0 * 0 NIL <文末><英記号><記号><付属>" [18] "EOS" [19] "" [20] "C:\\Users\\XXXXXXXX\\Documents>"
これでRでもKNPを使って係り受け解析ができます。やったね!