RでMeCab(RcppMeCab)を利用して形態素解析する方法
RcppMeCabとは
RcppMeCabは、Junhewk Kim氏が開発している、MeCabとRcppを利用して形態素解析するためのRパッケージです。
RcppMeCabによる形態素解析の例
形態素解析するための関数として、RcppMeCab::pos
とRcppMeCab::posParallel
の2つがあります。両者はまったく同じ機能を提供するものですが、posParallel
のほうは形態素解析の処理を内部的にマルチスレッドで回すことができます。posParallel
が対応しているOS・プラットフォームならば、基本的にposParallel
を使っておくほうが速いです。
渡す引数によって、以下のような出力を得ることができます。
require(RcppMeCab)
sentence <- c("陽が照って鳥が啼き あちこちの楢の林も、けむるとき", "ぎちぎちと鳴る 汚い掌を、おれはこれからもつことになる")
## テキストだけ与える場合、デフォルトの戻り値はnamed list of character vectors.
## リストの各要素は、表層形(surface form)と素性情報の1番目(IPA辞書では「品詞」)を'/'で区切ってつなげた文字列ベクトルになる。
RcppMeCab::pos(sentence)
#> $`1`
#> [1] "陽/名詞" "が/助詞" "照っ/動詞" "て/助詞"
#> [5] "鳥/名詞" "が/助詞" "啼き/動詞" " /記号"
#> [9] "あちこち/名詞" "の/助詞" "楢/名詞" "の/助詞"
#> [13] "林/名詞" "も/助詞" "、/記号" "けむる/動詞"
#> [17] "とき/名詞"
#>
#> $`2`
#> [1] "ぎちぎち/副詞" "と/助詞" "鳴る/動詞" " /記号"
#> [5] "汚い/形容詞" "掌/名詞" "を/助詞" "、/記号"
#> [9] "おれ/名詞" "は/助詞" "これから/副詞" "もつ/動詞"
#> [13] "こと/名詞" "に/助詞" "なる/動詞"
## 'join = FALSE'を指定すると、戻り値はnamed list of named character vectorsになる。
## Neologd辞書などでは収録されている語彙そのものに'/'が含まれていることがあるため、使用ケースによって使い分けるとよい。
RcppMeCab::pos(sentence, join = FALSE)
#> $`1`
#> 名詞 助詞 動詞 助詞 名詞 助詞 動詞
#> "陽" "が" "照っ" "て" "鳥" "が" "啼き"
#> 記号 名詞 助詞 名詞 助詞 名詞 助詞
#> " " "あちこち" "の" "楢" "の" "林" "も"
#> 記号 動詞 名詞
#> "、" "けむる" "とき"
#>
#> $`2`
#> 副詞 助詞 動詞 記号 形容詞 名詞 助詞
#> "ぎちぎち" "と" "鳴る" " " "汚い" "掌" "を"
#> 記号 名詞 助詞 副詞 動詞 名詞 助詞
#> "、" "おれ" "は" "これから" "もつ" "こと" "に"
#> 動詞
#> "なる"
## 'format = data.frame'にすると、戻り値は以下のようなデータフレームになる。
## pos列・subtype列は素性情報の1~2番目(IPA辞書では「品詞」と「品詞細分類1」)、
## analytic列は素性情報の8番目(IPA辞書の「読み」)だが、
## 未知語で推定されない素性だった場合などには'NA_character_'が含まれることがある。
RcppMeCab::pos(sentence, format = "data.frame") %>%
head(16L)
#> doc_id sentence_id token_id token pos subtype analytic
#> 1 1 1 1 陽 名詞 一般 ヒ
#> 2 1 1 2 が 助詞 格助詞 ガ
#> 3 1 1 3 照っ 動詞 自立 テッ
#> 4 1 1 4 て 助詞 接続助詞 テ
#> 5 1 1 5 鳥 名詞 一般 トリ
#> 6 1 1 6 が 助詞 格助詞 ガ
#> 7 1 1 7 啼き 動詞 自立 ナキ
#> 8 1 1 8 記号 空白
#> 9 1 1 9 あちこち 名詞 代名詞 アチコチ
#> 10 1 1 10 の 助詞 連体化 ノ
#> 11 1 1 11 楢 名詞 一般 ナラ
#> 12 1 1 12 の 助詞 連体化 ノ
#> 13 1 1 13 林 名詞 一般 ハヤシ
#> 14 1 1 14 も 助詞 係助詞 モ
#> 15 1 1 15 、 記号 読点 、
#> 16 1 1 16 けむる 動詞 自立 ケムル
いずれの関数についても、sys_dic
とuser_dic
という引数から任意の辞書を指定できるほか、開発版(v0.0.1.3 or higher?)ではoptions
から次のようにしてシステム辞書を指定することもできます。
options(mecabSysDic = "/home/rstudio-user/.local/mecab-dic/ipadic-utf8")
RcppMeCabはv0.0.1.2までのCRANリリースがありますが、それほどアクティブに開発されているわけではないため、筆者が個人的にforkしたうえで修正したりしています。
このforkでは 'format = data.frame'として得られるデータフレームから、token列についてdoc_idごとの分かち書きへと整形するRcppMeCab::pack
という関数などを追加しています。RcppMeCab::pack
は、たとえばquantedaと組み合わせて次のように使用することができます。
require(RcppMeCab)
require(quanteda)
sentence <- c("陽が照って鳥が啼き あちこちの楢の林も、けむるとき", "ぎちぎちと鳴る 汚い掌を、おれはこれからもつことになる")
(df <- RcppMeCab::pos(sentence, format = "data.frame") %>% RcppMeCab::pack())
#> doc_id text
#> 1 1 陽 が 照っ て 鳥 が 啼き あちこち の 楢 の 林 も 、 けむる とき
#> 2 2 ぎちぎち と 鳴る 汚い 掌 を 、 おれ は これから もつ こと に なる
df %>%
quanteda::corpus() %>%
quanteda::tokens(what = "fastestword") %>%
quanteda::dfm()
#> Document-feature matrix of: 2 documents, 29 features (48.28% sparse) and 0 docvars.
#> features
#> docs 陽 が 照 っ て 鳥 啼 き あちこち の
#> 1 1 2 1 1 1 1 1 1 1 2
#> 2 0 0 0 0 0 0 0 0 0 0
#> [ reached max_nfeat ... 19 more features ]
RcppMeCabの使用上の注意点
CRANにある最新リリース(2018-07-04)であるv0.0.1.2の注意点として、64bitのWindows環境ではインストールに失敗します。また、CRANリリースには日本語のIPA辞書などを使用時に未知語があると落ちるバグが残っているため、GitHubにある開発版を利用することをおすすめします。
以下は、いずれも筆者がメンテナンスしているfork(paithiov909/RcppMeCab)についての情報です。
Changes
-
RcppMeCab::pack
など、いくつかの関数を追加。 - 'format = data.frame'時のdoc_id列をfactor型にする(v0.0.1.2では見た目は数字だがcharacter型になっている)など、軽微な挙動の修正・リファクタリング。
-
'format = data.frame'時のsentence_id列の削除。この変更は元とほぼ同じ挙動に戻しました。- デフォルトでは、MeCab側ではなく、R側で文区切り(
stringi::stri_split_boundaries(type = "sentence")
による)します。 -
options(mecabSplit = FALSE)
とすることで、この文区切り処理をスキップできます。
- デフォルトでは、MeCab側ではなく、R側で文区切り(
- OS・プラットフォームを問わず、渡したcharacter vectorを
stringi::stri_enc_toutf8
でUTF-8に変換するように。 - Windowsでのソースパッケージからのインストールの改善。
- 'format = data.frame'時のC++側の処理の高速化。
Known Issues
- RcppParallelと同様の範囲でTinyThreadにそのうち対応したいです。
Limitations
- OS・プラットフォームを問わず、MeCabの辞書はUTF-8でコンパイルしたものを使用する前提なので、Shift-JISなどの辞書を使用することはできません。
- RcppParallelのAPIではなく、Intel Threaded Building Blocks(v.4.3)のAPIを直接触っているため、Windows, OSX, Linux, Solaris(x86 only)以外のプラットフォームでは
posParallel
は動きません。
Performance
あくまで目安ですが、夏目漱石「吾輩は猫である」の全文(2258 elements. メモリ上のサイズで700KB~1.1MB程度?)を同じ環境で解析させると、次のようになります。
require(RMeCab)
require(RcppMeCab)
sentences <- ldccr::NekoText ## paithiov909/ldccr
dplyr::glimpse(sentences)
#> chr [1:2258] "吾輩は猫である" "夏目漱石" "一" " 吾輩は猫である。名前はまだ無い。" ...
vec <- iconv(sentences, from = "UTF-8", to = "CP932")
df <- data.frame(text = vec)
tm <- microbenchmark::microbenchmark(
RMeCabC = lapply(vec, function(elem) {
RMeCabC(elem, mecabrc = "/MeCab/ipadic-shiftjis/mecabrc")
}),
RMeCabDF = RMeCabDF(df, 1, mecabrc = "/MeCab/ipadic-shiftjis/mecabrc"),
pos = pos(sentences),
posParallel = posParallel(sentences),
times = 10L
)
summary(tm)
#> expr min lq mean median uq max neval
#> 1 RMeCabC 7197.2222 7296.917 7369.802 7341.859 7400.890 7680.760 10
#> 2 RMeCabDF 7643.6918 7696.169 7787.620 7728.074 7769.400 8301.763 10
#> 3 pos 1355.6821 1392.607 1442.339 1397.141 1448.497 1693.051 10
#> 4 posParallel 996.5137 1008.699 1028.882 1014.281 1035.060 1144.857 10
ggplot2::autoplot(tm)
他の方の記事ですでに紹介されているように、従来のRcppMeCabについてはRMeCabの同等の処理のほうが速いケースがありましたが、MeCabそのものの解析速度には差はないため、RパッケージからMeCabを利用する際にはC/C++部分の書き方によってパフォーマンスに差が出ます。筆者のforkではそのあたりはある程度リファクタリングされているため、単純に文字列ベクトルを形態素解析するかぎりではRcppMeCabのほうが速いです。
MeCabのインストール
Windows
64bit/32bitを問わず、基本的にこれを使うことをオススメします。使っているR/RStudioのアーキテクチャにあわせて以下のいずれかを選び、展開して生成されるファイルをすべてC:/mecab
に移動してください。
その後、C:/mecab
にパスを通してください。
なお(きちんと確認していませんが)、mecab-ko-msvcも元のMeCabのソースコードをMicrosoft Visual C++でビルドできるように弄った野良ビルドのひとつで、生成されているバイナリとしては他の日本語向けの野良ビルドとほとんど同じものだと思われます。日本語向けと韓国語向けとの主な違いは、デフォルトで見に行く辞書の場所くらいなので、たとえば日本語と韓国語を切り替えたいという場合であっても、後からRcppMeCabパッケージのインストールをし直したりする必要はありません。
OSX
homebrew経由でインストールできます。
brew install mecab
brew install mecab-ipadic
M1/arm64の場合、homebrewからインストールできるバイナリがarm64向けビルドでないらしく、正しく動かないことが報告されています(未確認)。その場合は、自分でMeCabをソースからビルドしてインストールすると動かせるらしいです。
Linux
リポジトリからインストールする場合
apt(apt-get)などからインストールできます。
sudo apt install mecab
sudo apt install libmecab-dev
sudo apt install mecab-ipadic-utf8
RStudio Cloudなど、sudoできない環境で自分でビルドする場合
MeCabを公式で案内されている手順にしたがってビルド・インストールしようとするとsudoが必要になりますが、以下の記事などで案内されているように、makeするときにprefixを指定すれば書き込み権限がある場所にインストールできるため、たとえばRStudio Cloudなどでも、実はMeCabを使うことは可能です。
例として、RStudio CloudでMeCabを利用する場合、Terminalペインから次のようにしてインストールします。
wget "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE" -O mecab-0.996.tar.gz
tar xvf mecab-0.996.tar.gz
cd mecab-0.996
./configure --prefix=$HOME/.local --with-charset=utf8 --enable-utf8-only
make
make install
この後で、Rコンソール側からパスを追記します。また、/home/rstudio-user/.local/lib/libmecab.so.2
を明示的に読み込んでおかないと後でパッケージの読み込みに失敗するため、ここで読み込んでおきます。なお、この手順はRのセッションを立ち上げるたびごとに行う必要があります。
Sys.setenv(PATH = paste(Sys.getenv("PATH"), "/home/rstudio-user/.local/bin", sep = ":"))
dyn.load("/home/rstudio-user/.local/lib/libmecab.so.2")
UTF-8の辞書もあわせてビルドします。あらかじめ、Terminalでダウンロードして展開しておきます。
wget "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM" -O mecab-ipadic-2.7.0-20070801.tar.gz
tar xvzf mecab-ipadic-2.7.0-20070801.tar.gz
これで辞書がビルドできます。こちらもTerminalからでもできますが、mecab-configにパスが通っていないといけないので、Rコンソール側でやってしまうと便利です。
Rコンソールからやる場合、たとえば次のようにします。
setwd("./mecab-ipadic-2.7.0-20070801")
system("bash ./configure --with-charset=utf8 --with-dicdir=/home/rstudio-user/.local/dic/ipadic-utf8")
system("make")
system("make install") ## `sys_dic`に辞書のパスを指定して呼ぶので本当はインストールは不要ですが、いちおう
setwd("../")
## この場合、たとえば以下のようにシステム辞書のパスを指定して使う
# options(mecabSysDic = file.path("/home/rstudio-user/.local/dic/ipadic-utf8"))
# RcppMeCab::pos(c("この木なんの木", "気になる木", "見たこともない木ですから"))
RcppMeCabのインストール
ソースパッケージからビルドする場合、以下のようにしてインストールできます。
# Sys.setenv(MECAB_LANG = "ja") ## Windowsの場合
remotes::install_github("junhewk/RcppMeCab")
筆者がメンテナンスしているforkからは次のようにしてインストールできます。
remotes::install_github("paithiov909/RcppMeCab")
Windowsの場合、筆者のdratリポジトリからバイナリパッケージをインストールすることもできます。
drat::addRepo("paithiov909")
install.packages("RcppMeCab")
# or
update.packages()
Discussion