knitr::opts_chunk$set(
  tidy = "styler",
  collapse = TRUE,
  comment = "#>"
)

これは何?

RcppKagomeは、Rで形態素解析するためのパッケージです。Pure Goで辞書同梱な形態素解析器として知られるikawaha/kagomeをラップしています。

使い方

インストール

remotes::install_github(
  "paithiov909/RcppKagome"
  #, INSTALL_opts = "--no-multiarch" # for windows user
)

なお、ソースパッケージからビルドするため、インストールにはSystem Requirementsにあげられているものが必要です。

形態素解析

character vectorを渡せます。戻り値はリストです。

res <- RcppKagome::kagome("雨にも負けず 風にも負けず")
str(res)

結果をデータフレームに整形できます。

res <- RcppKagome::kagome(
    c("陽が照って鳥が啼き あちこちの楢の林も、けむるとき",
    "ぎちぎちと鳴る 汚い掌を、おれはこれからもつことになる"))
res <- RcppKagome::prettify(res)
print(res)

整形されたデータフレームは次のカラムからなります。

このうちtoken列だけを半角スペースでcollapseして返す(分かち書きにする)ことができます。

RcppKagome::pack_df(res)

なお、prettifyを経由しなくても同じかたちのデータフレームを得ることができます。

res <- RcppKagome::kagome("雨にも負けず 風にも負けず")
RcppKagome::pack_list(res)

速度比較

RcppMeCabと速度比較しています。

単文を渡す場合

単文の解析速度としてはとくに遅いということはないはずです。

bench-plot-1

このグラフからだとやや遅く見えるかもしれませんが、同じ実行環境でspacyrを用いてPOS tagging('ja_core_news_md'モデルを使用、spacyr::spacy_parse(lemma = FALSE, entity = FALSE, mutlithread = TRUE))すると、平均で90ms程度かかります。sapCyはUniversal Dependenciesを扱うライブラリであってそもそも「形態素解析」をする実装ではないのですが、あえて比較するならば、RcppKagomeでも明らかに速いです。

複数の文を渡す場合

ベクトル(2258 elements, 1.1MB)を渡す場合、ふつうに使うかぎりではRcppMeCabが速いと思われます。

bench-plot-2

このような結果になる理由として、RcppMeCabはC++のレベルでvectorizeされているという点があります。RcppMeCab::posはMeCabのタガーインスタンスを一つだけつくってそれぞれの文をひとつずつ解析する処理を繰り返します。一方で、RcppMeCab::posParallelはマルチスレッドで、スレッドごとにMeCabのタガーインスタンスを生成します。いずれにせよ、RcppMeCabではベクトルを与えられた場合、各文の解析に用いるタガーを内部的に使いまわしています。形態素解析をするライブラリでは一般にタガーインスタンスの生成はコストが高い処理であるため、解析の際にタガーの生成が繰り返されるとそれがボトルネックになって、解析に時間がかかります(これはRcppMeCabだけについてみても同様で、たとえばスレッドごとに処理する文の分量が極端に少ない場合、個々の文の解析にかかる時間の割にインスタンスの生成にコストが割かれることになって、RcppMeCab::posよりRcppMeCab::posParallelのほうがかえってパフォーマンスが悪化することがあります)。

RMeCabやRcppKagomeでは解析するたびごとにタガーの生成を繰り返す必要があるため、実用上はおそらくRcppMeCabに比べて遅くなります。

なお、この記事の主旨から外れますが、これくらいの分量のベクトルをspacyrで解析しようとすると結果をデータフレームにパースするコストが高すぎて死ぬほど時間がかかるので、そういう使い方は避けたほうがよいです。

RとGoの連携について

日本語情報としては以下の記事があります。

この記事はもともとRomain Francois氏(RcppとかrJavaとかの開発にかかわっているスゴい人らしい)が書いたブログ記事を参考にしているものです。

Goにはcgoというコマンドが用意されていて、Goで書かれたコードをC言語から利用するためのライブラリにすることができます。この機能を利用して生成したC言語向けのライブラリをRパッケージから呼び出すことで、いちおうはGoの資産をRから利用することができます。

本来、Cなどで書かれた関数をRパッケージで直接呼ぶためには.Callを使って呼べる状態にするために関数のregistrationという操作が必要になります。この手間を省略するために、RcppKagomeではcgoで生成したライブラリをC++から利用するラッパーを書いて、それをRcppでエクスポートしています。

また、より便利に扱うためにはGoとのあいだに型マッピングを定義するのが望ましいのでしょうが、RcppKagomeではその点については深入りせず、文字列だけを受け渡しするようにしています。参考までに、Goとのあいだに型マッピングが定義されているほかの例を挙げておきます。

セッション情報

sessioninfo::session_info()


paithiov909/RcppKagome documentation built on Nov. 17, 2021, 3:43 a.m.