2019年末版 形態素解析器の比較

形態素解析は日本語処理の初歩であり、文を単語に分割したり、品詞や活用形、基本形を分析するために行います。本記事では形態素解析のツールをいくつかの出力例を交えて比較していきます。

（SentencePieceでいいじゃん、という人はお呼びでないですが、そういう方には、Twitterのトレンドが変な分割になってたら嫌では？と申し上げておきたいです）

# [MeCab](https://taku910.github.io/mecab/)
言わずと知れた形態素解析器。とりあえずMeCabを使うという人は今なお多いことでしょう。とにかく高速であるということと、システムと辞書が分離されているのが特徴です。またPythonから使うのも簡単になりました（[Janome](https://mocobeta.github.io/janome/)というものがありましたが[mecab-python3](https://pypi.org/project/mecab-python3/)の方が高速です）。Javaから使いたい人は[Kuromoji](https://www.atilika.com/ja/kuromoji/)を使えばmecab(+ipadic)相当の結果が得られるはずです。

辞書はIPA辞書が推奨されていますが、Unidic辞書やNEologdもよく使われます。

（12/19追記）
@chezou さんからご指摘を頂きました。MeCabのPythonラッパについては、現在mecab-python3のメモリリーク問題を解決する[PR](https://github.com/SamuraiT/mecab-python3/pull/37)が放置されている状況なので、[fugashi](https://github.com/polm/fugashi)か[natto-py](https://github.com/buruzaemon/natto-py)を使う方が良いそうです。
（12/26追記）
@KoichiYasuoka さんより、mecab-python3の件のPRはマージされたそうです。

## IPA辞書
IPA辞書は学校文法に似た品詞体系なので非常にわかりやすいです。導入もたいへん楽です。

```sh
% mecab
太郎が歩いている。
太郎    名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
歩い    動詞,自立,*,*,五段・カ行イ音便,連用タ接続,歩く,アルイ,アルイ
て      助詞,接続助詞,*,*,*,*,て,テ,テ
いる    動詞,非自立,*,*,一段,基本形,いる,イル,イル
。      記号,句点,*,*,*,*,。,。,。
EOS
りんごジュースを飲んだ。
りん    副詞,助詞類接続,*,*,*,*,りん,リン,リン
ご      接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
ジュース        名詞,一般,*,*,*,*,ジュース,ジュース,ジュース
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
飲ん    動詞,自立,*,*,五段・マ行,連用タ接続,飲む,ノン,ノン
だ      助動詞,*,*,*,特殊・タ,基本形,だ,ダ,ダ
。      記号,句点,*,*,*,*,。,。,。
EOS
```
MeCab+IPAdicを使うと「りん/ご/ジュース」のように、たまに妙な分割になることが知られています。「リンゴジュース」とカタカナで書けば正しく解析してくれるのですが。

## [Unidic](https://unidic.ninjal.ac.jp/download#unidic_bccwj)
（現代書き言葉）Unidicは国語研が[現代日本語書き言葉均衡コーパス](https://pj.ninjal.ac.jp/corpus_center/bccwj/)において用例収集がしやすくなるように定義した「短単位」を元に構築した辞書です。自然言語処理で構文解析や意味解析などをする上では分割が短過ぎて使いにくいです（短単位をまとめ上げて長単位にするツール、[Comainu](http://comainu.org/)があるのですが、この長単位をベースに依存構造解析ができるツールが無いという事情もあり、なかなか使われません）。

一方で検索システムにおいては「単語分割の一貫性」（クエリ中と文書中の同じ語が同じ分割になること）という観点が重要で、Unidicは一貫性が高いということが報告されています（[文献](https://www.anlp.jp/proceedings/annual_meeting/2016/pdf_dir/D6-5.pdf)）。

```sh
都道府県知事
都      名詞,普通名詞,一般,,,,ト,都,都,ト,都,ト,漢,,,,,,B1SjS,B1S8SjS,体,ト,ト,ト,ト,1,C3,,7100654715806208,25832
道      名詞,普通名詞,一般,,,,ドウ,道,道,ドー,道,ドー,漢,,,,,,,体,ドウ,ドウ,ドウ,ドウ,1,C3,,7415115041350144,26976
府      名詞,普通名詞,一般,,,,フ,府,府,フ,府,フ,漢,フ半濁,基本形,,,,,体,フ,フ,フ,フ,1,C3,,8876091116757504,32291
県      名詞,普通名詞,一般,,,,ケン,県,県,ケン,県,ケン,漢,ケ濁,基本形,,,,B1S6SjShS,体,ケン,ケン,ケン,ケン,1,C3,,3094034344190464,11256
知事    名詞,普通名詞,一般,,,,チジ,知事,知事,チジ,知事,チジ,漢,,,,,,,体,チジ,チジ,チジ,チジ,1,C1,,6468160651928064,23531
EOS
りんごジュースを飲んだ。
りんご  名詞,普通名詞,一般,,,,リンゴ,林檎,りんご,リンゴ,りんご,リンゴ,漢,,,,,,,体,リンゴ,リンゴ,リンゴ,リンゴ,0,C2,,11102602163003904,40391
ジュース        名詞,普通名詞,一般,,,,ジュース,ジュース-juice,ジュース,ジュース,ジュース,ジュース,外,,,,,,,体,ジュース,ジュース,ジュース,ジュース,1,C1,,5072330640466432,18453
を      助詞,格助詞,,,,,ヲ,を,を,オ,を,オ,和,,,,,,,格助,ヲ,ヲ,ヲ,ヲ,,動詞%F2@0,名詞%F1,形容詞%F2@-1,,11381878116459008,41407
飲ん    動詞,一般,,,五段-マ行,連用形-撥音便,ノム,飲む,飲ん,ノン,飲む,ノム,和,,,,,,,用,ノン,ノム,ノン,ノム,1,C1,,8033590399083141,29226
だ      助動詞,,,,助動詞-タ,終止形-一般,タ,た,だ,ダ,だ,ダ,和,,,,,,,助動,ダ,ダ,ダ,ダ,,動詞%F2@1,,5948924875645611,21642
。      補助記号,句点,,,,,,。,。,,。,,記号,,,,,,,補助,,,,,,,,6880571302400,25
EOS
```
短単位なのでかなり細切れになるときがあります。一方で「りんごジュース」を正しく分割している点はIPAdicより優秀です。

（最新のver.2.3.0はサイズが非常に大きいので、気軽に試したい人は前のバージョンを使うか後述のSudachiで代用するのが良いと思います）

## [NEologd](https://github.com/neologd/mecab-ipadic-neologd)
Web上のあらゆる新語が追加された巨大な辞書です。今もなお頻繁に更新されています。Twitterデータなどを解析するときの助けになります。

```sh
天気の子を見た。
天気の子        名詞,固有名詞,一般,*,*,*,天気の子,テンキノコ,テンキノコ
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
見      動詞,自立,*,*,一段,連用形,見る,ミ,ミ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。      記号,句点,*,*,*,*,。,。,。
```


# [JUMAN](http://nlp.ist.i.kyoto-u.ac.jp/index.php?JUMAN)
京大黒橋研が開発した形態素解析器です。MeCabより歴史が古いので（最新版はJUMANの方が新しいようです）形態素解析器としてはMeCabの方が多機能です。しかし依存構造などを解析できる[KNP](http://nlp.ist.i.kyoto-u.ac.jp/index.php?KNP)が使えるというのはMeCabに無い利点です。

後継機であるJUMAN++については後で紹介しますが、JUMANはJUMAN++よりもインストールが楽な場合が多く、解析も高速という利点はあります。

JUMANでは益岡田窪文法と呼ばれる、とっつきにくい体系を採用しています。これは学校文法が計算機向きではないという仮説に基づいているようです。「ナ形容詞」「イ形容詞」など、（非ネイティブ向け）日本語教育に用いられる体系に似ているのは興味深いです。また、Wikipedia記事名を辞書に含んでいるので固有表現にもある程度対応しています。

Pythonから呼び出したい方は[PyKNP](http://nlp.ist.i.kyoto-u.ac.jp/index.php?PyKNP)を使いましょう（KNPに用が無くてもです）。


```sh
% ./juman-7.01/juman/juman
太郎が歩いている。
太郎 たろう 太郎 名詞 6 人名 5 * 0 * 0 "人名:日本:名:45:0.00106"
が が が 助詞 9 格助詞 1 * 0 * 0 NIL
歩いて あるいて 歩く 動詞 2 * 0 子音動詞カ行 2 タ系連用テ形 14 "代表表記:歩く/あるく"
いる いる いる 接尾辞 14 動詞性接尾辞 7 母音動詞 1 基本形 2 "代表表記:いる/いる"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS
ぶん殴る
ぶん ぶん ぶん 接頭辞 13 動詞接頭辞 2 * 0 * 0 "代表表記:ぶん/ぶん"
殴る なぐる 殴る 動詞 2 * 0 子音動詞ラ行 10 基本形 2 "代表表記:殴る/なぐる"
EOS
りんご りんご りんご 名詞 6 普通名詞 1 * 0 * 0 "代表表記:林檎/りんご カテゴリ:植物;人工物-食べ物 ドメイン:料理・食事"
ジュース じゅーす ジュース 名詞 6 普通名詞 1 * 0 * 0 "代表表記:ジュース/じゅーす カテゴリ:人工物-食べ物;抽象物 ドメイン:料理・食事"
を を を 助詞 9 格助詞 1 * 0 * 0 NIL
飲んだ のんだ 飲む 動詞 2 * 0 子音動詞マ行 9 タ形 10 "代表表記:飲む/のむ ドメイン:料理・食事"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS
辛い からい 辛い 形容詞 3 * 0 イ形容詞アウオ段 18 基本形 2 "代表表記:辛い/からい 反義:形容詞:甘い/あまい"
@ 辛い つらい 辛い 形容詞 3 * 0 イ形容詞アウオ段 18 基本形 2 "代表表記:辛い/つらい"
もの もの もの 名詞 6 形式名詞 8 * 0 * 0 NIL
が が が 助詞 9 格助詞 1 * 0 * 0 NIL
あった あった あう 動詞 2 * 0 子音動詞ワ行 12 タ形 10 "代表表記:会う/あう 反義:動詞:分かれる/わかれる;動詞:別れる/わかれる"
@ あった あった あう 動詞 2 * 0 子音動詞ワ行 12 タ形 10 "代表表記:合う/あう 付属動詞候補（基本） 自他動詞:他:合わす/あわす 反義:動詞:離れる/はなれる"
@ あった あった ある 動詞 2 * 0 子音動詞ラ行 10 タ形 10 "代表表記:有る/ある 補文ト 反義:形容詞:無い/ない"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS
ビミョーだ
ビミョーだ ビミョーだ ビミョーだ 形容詞 3 * 0 ナ形容詞 21 基本形 2 "代表表記:微妙だ/びみょうだ 自動獲得:テキスト 既知語帰着:表記・出現類似"
EOS
行きたぁぁい
行き いき 行く 動詞 2 * 0 子音動詞カ行促音便形 3 基本連用形 8 "代表表記:行く/いく 付属動詞候補（タ系） ドメイン:交通 反義:動詞:帰る/かえる"
たぁぁい たい たい 接尾辞 14 形容詞性述語接尾辞 5 イ形容詞アウオ段 18 基本形 2 "代表表記:たい/たい 長音挿入"
EOS
```
MeCab+IPAdicと比べてみると、「歩いて」が「歩く」の連用テ形になっているところが違います。このようにIPAdicにおける助詞・助動詞の一部が自立語の活用形に吸収されるのが特徴です。一方でMeCab+IPAdicだと「ぶん殴る」一語ですがJUMANだと「ぶん/殴る」と分かれます。また、「りんごジュース」は正しく解析できています。

また、JUMANはオプションをつけないと曖昧性のある形態素に対して、候補の形態素をアットマーク@付きで出力します（「@ 辛い」「@ あった」）。`-b`をつけると黙殺できますが、曖昧性をちゃんと解消したいときはKNPを使います。他の形態素解析器ではあまり意識されていない部分だと思います。

最新版では「ビミョーだ」などの長音記号による非標準表記に対応していて、「行きたぁぁい」などの長音化は正規化されるそうです。

# [JUMAN++](http://nlp.ist.i.kyoto-u.ac.jp/index.php?JUMAN++)
体系はJUMANのまま、RNN言語モデルを使うことで非常に高精度な形態素解析を実現しています。公式リリースされているバージョン1は解析速度がとても遅いです。開発版であるバージョン2は大分速くなってますが、それでもJUMANより倍遅いそうです。Pythonからは同じくPyKNPで呼び出せます。

```shell
% ./bin/jumanpp
外国人参政権
外国 がいこく 外国 名詞 6 普通名詞 1 * 0 * 0 "代表表記:外国/がいこく ドメイン:政治 カテゴリ:場所-その他"
人 じん 人 名詞 6 普通名詞 1 * 0 * 0 "代表表記:人/じん カテゴリ:人 漢字読み:音"
参政 さんせい 参政 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:参政/さんせい ドメイン:政治 カテゴリ:抽象物"
権 けん 権 名詞 6 普通名詞 1 * 0 * 0 "代表表記:権/けん カテゴリ:抽象物 漢字読み:音"
EOS
辛いものがあった。
辛い つらい 辛い 形容詞 3 * 0 イ形容詞アウオ段 18 基本形 2 "代表表記:辛い/つらい"
もの もの もの 名詞 6 形式名詞 8 * 0 * 0 NIL
が が が 助詞 9 格助詞 1 * 0 * 0 NIL
あった あった ある 動詞 2 * 0 子音動詞ラ行 10 タ形 10 "代表表記:有る/ある 反義:形容詞:無い/ない 補文ト"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS
```

形態素解析業界の有名な難問、「外国人参政権」を「外国/人参/政権」のように間違えないのはJUMAN++くらいでしょう。

JUMANでは@まみれになった「辛いものがあった。」もJUMAN++なら解消してくれます。この例はうまくいきましたが、うまくいかずにスコアが同じになった形態素はJUMAN同様（デフォルトでは）@付きで出力されます。真剣に解消したいときも同様でKNPを使います。

# [Sudachi](https://github.com/WorksApplications/Sudachi)
ワークスアプリケーションズ徳島人工知能NLP研究所が開発した形態素解析器です。商用利用に耐えうる高品質な解析性能を持つらしいです。これまで紹介したものの中で最も後発の形態素解析器です。

企業のバックアップのもと、辞書の継続的なメンテナンスが保証されているのは非常に大きな特徴です。また、分割の長さをA単位（Unidic相当）、B単位（IPAdic相当）、C単位（NEologd相当）から選べるのも特徴です。Unidicを採用していること、表記を正規化する機能があること、Elasticsearchプラグインが開発されているなど、検索システムでの利用が強く意識されているようです。

公式によると、MeCabと精度は同じくらいで、速度はMeCabに劣るが、省メモリの工夫をしているそうです。

Python版である[SudachiPy](https://github.com/WorksApplications/SudachiPy)もあります。

```sh
% sudachipy
太郎はシュミレーションした。
太郎    名詞,固有名詞,人名,名,*,*       太郎
は      助詞,係助詞,*,*,*,*     は
シュミレーション        名詞,普通名詞,サ変可能,*,*,*    シミュレーション
し      動詞,非自立可能,*,*,サ行変格,連用形-一般        為る
た      助動詞,*,*,*,助動詞-タ,終止形-一般      た
。      補助記号,句点,*,*,*,*   。
EOS
りんごジュースを飲んだ。
りんご  名詞,普通名詞,一般,*,*,*        林檎
ジュース        名詞,普通名詞,一般,*,*,*        ジュース
を      助詞,格助詞,*,*,*,*     を
飲ん    動詞,一般,*,*,五段-マ行,連用形-撥音便   飲む
だ      助動詞,*,*,*,助動詞-タ,終止形-一般      た
。      補助記号,句点,*,*,*,*   。
EOS
aとαは違うYO
a       名詞,普通名詞,助数詞可能,*,*,*  a
と      助詞,格助詞,*,*,*,*     と
α       記号,文字,*,*,*,*       アルファ
は      助詞,係助詞,*,*,*,*     は
違う    動詞,一般,*,*,五段-ワア行,終止形-一般   違う
YO      助詞,終助詞,*,*,*,*     よ
EOS
hello
hello   名詞,普通名詞,一般,*,*,*        ハロー
EOS
身長2㍍欲しい
身長    名詞,普通名詞,一般,*,*,*        身長
2       名詞,数詞,*,*,*,*       2
㍍      名詞,普通名詞,助数詞可能,*,*,*  メートル
欲しい  形容詞,非自立可能,*,*,形容詞,終止形-一般        欲しい
EOS
おーーー😀
おーーー        感動詞,フィラー,*,*,*,* おー
😀      補助記号,一般,*,*,*,*   😀
EOS
```
「シュミレーション」の基本形が「シミュレーション」になってるのは地味にすごいです。辞書がUnidic辞書ベースなのでりんごジュースにも正解できます。
他の形態素解析器では、入力に半角文字や特殊記号があると大抵変な結果になるのですが、Sudachiはその辺の正規化を頑張っているのか、まともな解析をしてくれます。Web上のテキストに対して形態素解析を行うときは前処理をするのが普通ですが、Sudachiを使うときは不要かもしれません。


# 速度比較
手元にあった（[100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100/)からダウンロードしてきた）夏目漱石の「吾輩は猫である」の文章でやってみます。少々少ない気がしますが9964行（空行を除くと9210行）です。初期化の時間を含んでしまっていることは見逃してください。timeコマンドを使ってすべてデフォルトオプションで動作させたときのテキトーな比較です。また[こちらの記事](https://qiita.com/sugiyamath/items/69047b6667256034fa5e)もご参考に。

|解析器  |時間|
|---|---|
|MeCab  |0.226s|
|JUMAN |3.661s|
|JUMAN++(v2)|6.706s|
|Sudachi|4.119s|
|SudachiPy|74.872s|



# 使い分け
* mecab→速度最優先のとき、IPAdicやNEologdを使いたいとき、係り受け解析器[Cabocha](https://taku910.github.io/cabocha/)を使いたいとき
* JUMAN→JUMAN辞書を使いたいとき、[KNP](http://nlp.ist.i.kyoto-u.ac.jp/index.php?KNP)で依存構造などを（ほどほどの速度と精度で）解析したいとき
* JUMAN++→精度を優先したいとき、精度を気にしてKNPを使いたいとき
* Sudachi→検索システムに使いたいとき、表記正規化機能を使いたいとき、Unidicを使いたいとき
* SudachiPy→[GiNZA](https://github.com/megagonlabs/ginza)（spaCy）を使ってUD（単語単位の依存構造）解析したいとき、これを使うしかないので比較に入れました

##　補足（係り受け解析まわり）
- Cabochaは並列句の係り受けに弱いです
- KNPは単なる係り受けだけでなく、依存関係の種類、述語項構造や照応関係まで分析してくれます。最強。
- KNPの依存構造解析は文節ベースなのに対し、GiNZAの依存構造解析は単語ベースです（がCaboCha形式の出力もできます）。PythonのspaCyから呼び出せるので非常に使いやすいです。現在定期的にアップデートされています。