spaCy vs. MeCab vs. UDPipe - Rで日本語形態素解析対決!

日本語の品詞を分解して判別することができる**spaCy, MeCab, UDpipe**ですが触っているうちにそれぞれ分解した結果が違うなと感じることがあったのでいくつかの文例を分解してもらいながらそれぞれの能力の限界を探ってみたいと思います。

## とりあえず結論

先にそれぞれ優れている点の結論をば。どれでも同じく動かせるのであれば、**総合ではspaCy**、**細かい分析をするならMeCab**、**信頼性を犠牲にした手軽さを求めるならUDpipe**が優れていると思います。

## 実行準備

Rでそれぞれのプログラムを実行する準備をしておきましょう。

- Mecabの準備

MeCabはRで`RMeCab`というパッケージがあるのですがこれを動かすためには**MeCabをインストールしなければなりません**。MeCabのインストール、RでのMeCabの動かし方は[公式のドキュメント](https://taku910.github.io/mecab/)をご覧ください 。ここではMeCabのインストール手順は省略します。

```{r}
library(RMeCab)
```

- spaCy

spaCyはそもそもPythonのライブラリーです。Rにおいては`spacyr`というパッケージがありますが、これは**Pythonがインストールされていないと動作しません**。また、すでにPythonがインストールされていてもWindowsでR(もしくはRstudio)を**「管理者として実行」して起動**させないと動いてくれません。ご注意ください。

これらがクリアされている（Pythonインストール済、Windowsユーザーは「管理者から実行」で起動済み）前提で以下を実行すると日本語の形態素解析ができるようになります。

```{r}
library(spacyr)
spacy_install() #初回のみ実行。spaCyがインストールされます。途中コンソールで入力を求められます。
spacy_download_langmodel("ja_core_news_md") #初回のみ実行。日本語モデルのインストール。
spacy_initialize(model = "ja_core_news_md")
```

- UDPipe

Rには`udpipe`というパッケージがありますが、今回は`cleanNLP`というtidyパッケージからUDpipeを動かします。設定が極めて楽ですし、**R以外に何かインストールする必要はありません**。cleanNLPからspaCyも動かせることになっているみたいですが、「Python側で`cleanNLP`のライブラリーをインストールしろ」といわれてしまうので今回はspaCyは`spacyr`、UDPipeは`cleanNLP`から動かします。

```{r}
library(cleanNLP)
cnlp_init_udpipe(model_name = "japanese")
```

## いざ対決

それではいざいざ動かしていきましょう。今回解析してもらう文章は以下の6つです。

1. **"学校へ行った。しかし今日は休校日だった。"**
　→通常の文章。

2. **"元気がないですね、朝はご飯を食べないのですか。"**
　→1個目の"ない"と2個目の"ない"の品詞の区別はつきますか？

3. **"もしもし、株式会社ゴリラデータサイエンスの田中と申します。"**
　→固有名詞(架空)の判別力テスト。

4. **"Rei、ファースト・アルバム『REI』のInternational EditionがVerve Forecastレーベルより全世界配信決定"**
　→英語が入った記事タイトルでも大丈夫？(出典は[こちら](https://spice.eplus.jp/articles/282995):SPICE, 2021年2月15日)

5. **"すもももももももものうち"**
　→もももも…

6. **"白熊のやうな犬を二疋つれて、だいぶ山奥の、木の葉のかさ／＼したとこを、こんなことを云ひながら、あるいてをりました。"**
　→[宮沢賢治『注文の多い料理店』](https://www.aozora.gr.jp/cards/000081/files/1927_17906.html)の旧仮名遣いverより、冒頭部分から抜粋。

実行のためのコマンドは以下の通りです。コマンドの`text`の部分をこれらの文章置き換えて実行します。

```r
#spaCy
spacy_parse(text, lemma = FALSE)
#MeCab
RMeCabC(text) %>% unlist()
#UDPipe
annotation <- cnlp_annotate(input = iconv(text, to = "UTF-8"))#Windowsは文字コード変換
     ##For Mac/Linux: annotation <- cnlp_annotate(text)
annotation$token
```

以下出力結果の形態素解析結果のみ書いていきます。


**1. "学校へ行った。しかし今日は休校日だった。"**

```
#spaCy
    token   pos
1    学校  NOUN
2      へ   ADP
3    行っ  VERB
4      た   AUX
5      。 PUNCT
6  しかし CCONJ
7    今日  NOUN
8      は   ADP
9    休校  NOUN
10     日  NOUN
11   だっ   AUX
12     た   AUX
13     。 PUNCT

#MeCab
    名詞     助詞     動詞   助動詞     記号   接続詞 
  "学校"     "へ"   "行っ"     "た"     "。" "しかし" 
    名詞     助詞     名詞     名詞   助動詞   助動詞 
  "今日"     "は"   "休校"     "日"   "だっ"     "た" 
    記号 
    "。" 

#UDPipe
   token  token_with_ws lemma  upos 
   <chr>  <chr>         <chr>  <chr>
 1 学校   学校          学校   NOUN 
 2 へ     へ            へ     ADP  
 3 行っ   行っ          行う   VERB 
 4 た     た            た     AUX  
 5 。     。            。     PUNCT
 6 しかし しかし        しかし CCONJ
 7 今日   今日          今日   NOUN 
 8 は     は            は     ADP  
 9 休校日 休校日        休校日 NOUN 
10 だっ   だっ          だ     AUX  
11 た     た            た     AUX  
12 。     。            。     PUNCT
```

UDPipeのみ"休校日"を分解していませんが大きな問題はないでしょう。品詞も間違いがないようです。

**2. "元気がないですね、朝はご飯を食べないのですか。"**

```
#spaCy
   token   pos
1   元気  NOUN
2     が   ADP
3   ない   ADJ
4   です   AUX
5     ね  PART
6     、 PUNCT
7     朝  NOUN
8     は   ADP
9   ご飯  NOUN
10    を   ADP
11  食べ  VERB
12  ない   AUX
13    の SCONJ
14  です   AUX
15    か  PART
16    。 PUNCT

#MeCab
  名詞   助詞 形容詞 助動詞   助詞   記号   名詞   助詞 
"元気"   "が" "ない" "です"   "ね"   "、"   "朝"   "は" 
  名詞   助詞   動詞 助動詞   名詞 助動詞   助詞   記号 
"ご飯"   "を" "食べ" "ない"   "の" "です"   "か"   "。" 

#UDPipe
   token    token_with_ws lemma  upos 
   <chr>    <chr>         <chr>  <chr>
 1 元気     元気          元気   NOUN 
 2 が       が            が     ADP  
 3 ないです ないです      ない   ADJ  
 4 ね       ね            ね     PART 
 5 、       、            、     PUNCT
 6 朝       朝            朝     NOUN 
 7 は       は            は     ADP  
 8 ご飯     ご飯          ご飯   NOUN 
 9 を       を            を     ADP  
10 食べ     食べ          食べる VERB 
11 ない     ない          ない   AUX  
12 の       の            の     SCONJ
13 です     です          だ     AUX  
14 か       か            か     PART 
15 。       。            。     PUNCT
```

お、**2つの"ない"の品詞の違いがどれも区別されています**。この点はどれも問題がないみたいです。

**3. "もしもし、株式会社ゴリラデータサイエンスの田中と申します。"**

```
#spaCy
        token   pos
1    もしもし  INTJ
2          、 PUNCT
3        株式  NOUN
4        会社  NOUN
5      ゴリラ  NOUN
6      データ  NOUN
7  サイエンス  NOUN
8          の   ADP
9        田中 PROPN
10         と   ADP
11       申し  VERB
12       ます   AUX
13         。 PUNCT

#MeCab
                  感動詞                     記号 
              "もしもし"                     "、" 
                    名詞                     名詞 
              "株式会社" "ゴリラデータサイエンス" 
                    助詞                     名詞 
                    "の"                   "田中" 
                    助詞                     動詞 
                    "と"                   "申し" 
                  助動詞                     記号 
                  "ます"                     "。" 

#UDPipe
   token           token_with_ws      lemma          upos 
   <chr>           <chr>              <chr>          <chr>
 1 も              も                 も             ADP  
 2 しもし          しもし             しもす         VERB 
 3 、              、                 、             PUNCT
 4 株式会社        株式会社           株式会社       NOUN 
 5 ゴリラデータサイエンス~ ゴリラデータサイエンス~ ゴリラデータサイエンス~ NOUN 
 6 の              の                 の             ADP  
 7 田中            田中               田中           PROPN
 8 と              と                 と             ADP  
 9 申し            申し               申す           VERB 
10 ます            ます               ます           AUX  
11 。              。                 。             PUNCT
```

**ここらで大きな違いが**。spaCyは固有名詞"ゴリラデータサイエンス"を一般名詞"ゴリラ","データ","サイエンス"に分割しています。その点MeCabは固有名詞はそのまま残してくれています。UDPipeも同様に…と思ったら**"もしもし"がぶっ壊されている**。これに形態素解析を任せておくのは不安ですね…

**4. "Rei、ファースト・アルバム『REI』のInternational EditionがVerve Forecastレーベルより全世界配信決定"**

```
#spaCy
           token   pos
1            Rei PROPN
2             、 PUNCT
3     ファースト  NOUN
4             ・   SYM
5       アルバム  NOUN
6             『 PUNCT
7            REI PROPN
8             』 PUNCT
9             の   ADP
10 International  NOUN
11       Edition  NOUN
12            が   ADP
13         Verve PROPN
14      Forecast  NOUN
15      レーベル  NOUN
16          より   ADP
17            全  NOUN
18          世界  NOUN
19          配信  NOUN
20          決定  NOUN

#MeCab
           名詞            記号            名詞 
          "Rei"            "、"    "ファースト" 
           記号            名詞            記号 
           "・"      "アルバム"            "『" 
           名詞            記号            助詞 
          "REI"            "』"            "の" 
           名詞            名詞            助詞 
"International"       "Edition"            "が" 
           名詞            名詞            名詞 
        "Verve"      "Forecast"      "レーベル" 
           助詞          接頭詞            名詞 
         "より"            "全"          "世界" 
           名詞            名詞 
         "配信"          "決定" 

#UDPipe
   token          token_with_ws    lemma          upos 
   <chr>          <chr>            <chr>          <chr>
 1 Rei            "Rei"            Rei            PROPN
 2 、             "、"             、             PUNCT
 3 ファースト     "ファースト"     ファースト     PROPN
 4 ・             "・"             ・             SYM  
 5 アルバム       "アルバム"       アルバム       NOUN 
 6 『             "『"             『             PUNCT
 7 REI            "REI"            REI            PROPN
 8 』             "』"             』             PUNCT
 9 の             "の"             の             ADP  
10 International  "International " International  PROPN
11 Edition        "Edition"        Edition        PROPN
12 が             "が"             が             ADP  
13 Verve          "Verve "         Verve          PROPN
14 Forecast       "Forecast"       Forecast       PROPN
15 レーベル       "レーベル"       レーベル       NOUN 
16 より           "より"           より           ADP  
17 全世界配信決定 "全世界配信決定" 全世界配信決定 NOUN 
```

文章に日本語以外が入っていても日本語部分は影響はなく解析ができるようですが、"International"などの形容詞であっても**英語はすべて名詞と判断されます**。

**5. "すもももももももものうち"**

```
#spaCy
   token  pos
1 すもも NOUN
2     も  ADP
3   もも NOUN
4     も  ADP
5   もも NOUN
6     の  ADP
7   うち NOUN

#MeCab
    名詞     助詞     名詞     助詞     名詞     助詞     名詞 
"すもも"     "も"   "もも"     "も"   "もも"     "の"   "うち"

#UDPipe
  token            token_with_ws    lemma            upos 
  <chr>            <chr>            <chr>            <chr>
1 すももももももも すももももももも すももももももも CCONJ
2 もの             もの             もの             NOUN 
3 うち             うち             うち             NOUN
```

**UDPipeが完全に混乱。**

**6. "白熊のやうな犬を二疋つれて、だいぶ山奥の、木の葉のかさ／＼したとこを、こんなことを云ひながら、あるいてをりました。"**

```
#spaCy
    token   pos
1    白熊  NOUN
2      の   ADP
3    やう  NOUN
4      な   AUX
5      犬  NOUN
6      を   ADP
7      二   NUM
8      疋  NOUN
9    つれ  VERB
10     て SCONJ
11     、 PUNCT
12 だいぶ   ADV
13   山奥  NOUN
14     の   ADP
15     、 PUNCT
16 木の葉  NOUN
17     の   ADP
18   かさ  NOUN
19     ／   SYM
20     ＼   SYM
21     し   AUX
22     た   AUX
23   とこ  NOUN
24     を   ADP
25     、 PUNCT
26 こんな  PRON
27   こと  NOUN
28     を   ADP
29   云ひ  VERB
30 ながら SCONJ
31     、 PUNCT
32 あるい  VERB
33     て SCONJ
34   をり   AUX
35   まし   AUX
36     た   AUX
37     。 PUNCT

#MeCab
    名詞     助詞     名詞   助動詞     名詞     助詞     名詞     名詞     動詞 
  "白熊"     "の"   "やう"     "な"     "犬"     "を"     "二"     "疋"   "つれ" 
    助詞     記号     副詞     名詞     助詞     記号     名詞     助詞     名詞 
    "て"     "、" "だいぶ"   "山奥"     "の"     "、" "木の葉"     "の"   "かさ" 
    記号     記号     動詞   助動詞     名詞     助詞     記号   連体詞     名詞 
    "／"     "＼"     "し"     "た"   "とこ"     "を"     "、" "こんな"   "こと" 
    助詞     名詞     動詞     助詞     記号     動詞     助詞     助詞   助動詞 
    "を"     "云"     "ひ" "ながら"     "、" "あるい"     "て"     "を"     "り" 
  助動詞   助動詞     記号 
  "まし"     "た"     "。" 

#UDPipe
   token      token_with_ws lemma      upos 
   <chr>      <chr>         <chr>      <chr>
 1 白熊       白熊          白熊       NOUN 
 2 の         の            の         ADP  
 3 やう       やう          やう       ADJ  
 4 な         な            だ         AUX  
 5 犬         犬            犬         NOUN 
 6 を         を            を         ADP  
 7 二         二            二         NUM  
 8 疋つれ     疋つれ        疋つれる   VERB 
 9 て         て            て         SCONJ
10 、         、            、         PUNCT
11 だいぶ     だいぶ        だいぶ     ADV  
12 山奥       山奥          山奥       NOUN 
13 の         の            の         ADP  
14 、         、            、         PUNCT
15 木の       木の          木の       DET  
16 葉         葉            葉         NOUN 
17 の         の            の         ADP  
18 かさ       かさ          かさ       NOUN 
19 ／         ／            ／         PUNCT
20 ＼         ＼            ＼         PUNCT
21 し         し            する       VERB 
22 た         た            た         AUX  
23 とこ       とこ          とこ       NOUN 
24 を         を            を         ADP  
25 、         、            、         PUNCT
26 こんな     こんな        こんな     ADJ  
27 こと       こと          こと       NOUN 
28 を         を            を         ADP  
29 云ひながら 云ひながら    云ひながる VERB 
30 、         、            、         PUNCT
31 あるいて   あるいて      あるいて   ADV  
32 をり       をり          をる       VERB 
33 まし       まし          ます       AUX  
34 た         た            た         AUX  
35 。         。            。         PUNCT
```

ここで**予想外にMeCabが旧仮名に弱いことが発覚**。"云ひながら, あるいてをりました。"の分割を完全に間違っています。ここに関しては一番spaCyが信頼できそうです。

## まとめと結論

3つの形態素解析ソフトを様々なタイプの文章の解析をしながら比較してきました。それぞれ長所と短所があり、目的に応じて使い分けていただければいいと思うのですが、まとめると以下のようになるでしょうか。

**1. spaCy**

どんな文章でも崩壊することなく**信用が置ける**うえ、旧仮名遣いにもうまく対応。また、今回紹介はできなかったが初期設定を変えるだけで**日本語以外の文章も同じコマンドで動かせる**のも便利。唯一固有名詞に弱そうなのが欠点か。

**2. MeCab**

こちらも**信用できる解析をしてくれる**が、旧仮名遣いにはうまく対応できていなかった。また、日本語以外の形態素解析向けに開発されていないため、同じコマンドを実行しても**英語などを解析できない拡張性のなさが難点**。今回紹介しなかったが品詞に加えて"自立語/非自立語"など細かい形態素解析も行ってくれるので、**細かな形態素解析を必要とする場合はMeCabがよい**。


**3. UDPipe**

簡単な文章は対応しており、R以外のものをインストールしなくてよい手軽さは**とりあえず触ってみる人にはお勧め**できるが、肝心の形態素解析自体が**信頼性に大きく欠ける**。


他にも形態素解析エンジンはあるので、今後試しましたらこれらと比較をしてみます。お読みいただきありがとうございました。