【形態素解析】AWS ComprehendやGoogle Natural Language APIで「進撃の巨人」を固有名詞に判定できるか？

# 追記
この記事を書いたのはChatGPT出現前(2022年）です。ChatGPTが出てAIの固有名詞判定能力も大きく伸びたと思いますので、今なら辞書よりAIのほうが良い（記事と逆の結論）かもしれません。ご注意ください。
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

# 概要
## やりたいこと
この記事は、AWSとGoogleの自然言語処理サービスにおける、
固有名詞（新語）の判定能力を確かめた記録です。

具体的には、
`私の好きなアニメはドラゴンボールと幽遊白書と進撃の巨人とハウルの動く城と千と千尋の神隠しです。好きなタレントは平野紫耀です。`
といったような文章から、
- ドラゴンボール
- 幽遊白書
- 進撃の巨人
- ハウルの動く城
- 千と千尋の神隠し
- 平野紫耀
 
といった固有名詞を抽出できるか？を確認しました。
検証したサービスは、
- AWS Comprehend
- Google Natural Language API
- （比較用）Mecab+Neologd辞書
になります。

## 結果
AWS Comprehend も、Google Natural Language APIでも、上記の一部の固有名詞を抽出できませんでした。
Mecab＋Neologdはほぼ完璧な判定結果を得られましたが、Neologdの更新が止まっているため、
今後は判定精度は低下していくと思われます。

# AWS Comprehendの様子
AWS Copmprehendにおける固有名詞（Entity）抽出を、Pythonで行いました。
準備として、AWSアカウントを取得済み、環境にaws cliをインストール済み、aws configによりAWSへの接続情報が登録済みとします。
準備についてはこちらを参照してください。
Amazon Comprehend デベロッパーガイド
https://docs.aws.amazon.com/ja_jp/comprehend/latest/dg/what-is.html

```python
import boto3
comprehend = boto3.client(service_name='comprehend')
text = """私の好きなアニメはドラゴンボールと幽遊白書と進撃の巨人とハウルの動く城と千と千尋の神隠しです。好きなタレントは平野紫耀です。"""
print("Entities")
result = comprehend.detect_entities(Text = text, LanguageCode='ja')
for r in result["Entities"]:
    print(r)
```
その結果、
```python
Entities
{'Score': 0.9905611872673035, 'Type': 'TITLE', 'Text': 'ドラゴンボール', 'BeginOffset': 9, 'EndOffset': 16}
{'Score': 0.8984922766685486, 'Type': 'TITLE', 'Text': '幽遊白書', 'BeginOffset': 17, 'EndOffset': 21}
{'Score': 0.7571380138397217, 'Type': 'TITLE', 'Text': '進撃', 'BeginOffset': 22, 'EndOffset': 24}
{'Score': 0.5530967116355896, 'Type': 'TITLE', 'Text': 'ハウル', 'BeginOffset': 28, 'EndOffset': 31}
{'Score': 0.685460090637207, 'Type': 'TITLE', 'Text': '千尋', 'BeginOffset': 38, 'EndOffset': 40}
{'Score': 0.6708135604858398, 'Type': 'PERSON', 'Text': '平野紫耀', 'BeginOffset': 55, 'EndOffset': 59}
```
となりました。ドラゴンボールや幽遊白書といったカタカナや漢字で、明らかにタイトルとわかる単語は「TITLE」として判別できています。
一方で、「進撃の巨人」や「ハウルの動く城」のような、一見すると文章に見えるようなタイトルは、固有名詞として抽出できませんでした。

なお、例文をGoogle翻訳で英文にして、
`My favorite anime are Dragon Ball, Yu Yu Hakusho, Attack on Titan, Howl's Moving Castle and Spirited Away. My favorite talent is Sho Hirano.`
これを固有名詞抽出にかけると、
```python
import boto3
comprehend = boto3.client(service_name='comprehend')
text = """My favorite anime are Dragon Ball, Yu Yu Hakusho, Attack on Titan, Howl's Moving Castle and Spirited Away. My favorite talent is Sho Hirano.
"""
print("Entities")
result = comprehend.detect_entities(Text = text, LanguageCode='en')
for r in result["Entities"]:
    print(r)
```
結果、見てください。完璧に固有名詞が抽出できています。
```
Entities
{'Score': 0.998566210269928, 'Type': 'TITLE', 'Text': 'Dragon Ball', 'BeginOffset': 22, 'EndOffset': 33}
{'Score': 0.9931883811950684, 'Type': 'TITLE', 'Text': 'Yu Yu Hakusho', 'BeginOffset': 35, 'EndOffset': 48}
{'Score': 0.9984961152076721, 'Type': 'TITLE', 'Text': 'Attack on Titan', 'BeginOffset': 50, 'EndOffset': 65}
{'Score': 0.9974145293235779, 'Type': 'TITLE', 'Text': "Howl's Moving Castle", 'BeginOffset': 67, 'EndOffset': 87}
{'Score': 0.9986575245857239, 'Type': 'TITLE', 'Text': 'Spirited Away', 'BeginOffset': 92, 'EndOffset': 105}
{'Score': 0.9764893651008606, 'Type': 'PERSON', 'Text': 'Sho Hirano', 'BeginOffset': 129, 'EndOffset': 139}
```
これは英語のもつ「複数列記をカンマで区切る」「固有名詞には大文字を使う」といった文法の影響が大きいと思われます。つまり固有名詞判定し易い言語と言えます。

と、ここで１つ重要な事実が発覚します。Google翻訳で
`私の好きなアニメはドラゴンボールと幽遊白書と進撃の巨人とハウルの動く城と千と千尋の神隠しです。好きなタレントは平野紫耀です。`
という文章を
`My favorite anime are Dragon Ball, Yu Yu Hakusho, Attack on Titan, Howl's Moving Castle and Spirited Away. My favorite talent is Sho Hirano.`
と正確に英題に翻訳できたということは、Googleさんは各作品を固有名詞判定できているということになります。
であれば、Googleの固有名詞判定能力はAWSより優れているのでしょうか？

これを次のGoogle Natural Language APIで確認します。

# Google Natural Language APIの様子
Google Natural Languageの詳細・始め方についてはこちらを参照してください。
https://cloud.google.com/natural-language?hl=ja
上記URLにデモ機能があるので、誰でも試すことはできるのですが、
念のためAPIとしてローカルのPythonから実行してみました。

Pythonのコードはこちらです。
上記URLを参考に色々と準備がありますが、済ませてあります。
```python
from google.cloud import language_v1
client = language_v1.LanguageServiceClient()

text_content = """私の好きなアニメはドラゴンボールと幽遊白書と進撃の巨人とハウルの動く城と千と千尋の神隠しです。好きなタレントは平野紫耀です。"""
document = {"content": text_content, "type_": language_v1.Document.Type.PLAIN_TEXT, "language": "ja"}
encoding_type = language_v1.EncodingType.UTF8
response = client.analyze_entities(
    request={"document": document, "encoding_type": encoding_type}
)
for entity in response.entities:
    print(["Text: {}".format(entity.name) ,"Type: {}".format(language_v1.Entity.Type(entity.type_).name) ,"Score: {}".format(entity.salience)])
```
結果はこちら。
```python
['Text: アニメ', 'Type: WORK_OF_ART', 'Score: 0.12745632231235504']
['Text: ハウル', 'Type: OTHER', 'Score: 0.11885740607976913']
['Text: ドラゴンボール', 'Type: CONSUMER_GOOD', 'Score: 0.10858309268951416']
['Text: 千尋', 'Type: PERSON', 'Score: 0.10424114763736725']
['Text: 神隠し', 'Type: OTHER', 'Score: 0.093153215944767']
['Text: 巨人', 'Type: ORGANIZATION', 'Score: 0.08835809677839279']
['Text: 動く城', 'Type: EVENT', 'Score: 0.08835809677839279']
['Text: 進撃', 'Type: OTHER', 'Score: 0.08298821747303009']
['Text: 幽遊白書', 'Type: OTHER', 'Score: 0.08298821747303009']
['Text: タレント', 'Type: PERSON', 'Score: 0.05433204025030136']
['Text: 平野紫耀', 'Type: PERSON', 'Score: 0.05068415403366089']
['Text: 千', 'Type: NUMBER', 'Score: 0.0']
```
AWS同様、ドラゴンボールと幽遊白書は固有名詞として判定できていますが、
「進撃の巨人」や「ハウルの動く城」のような、一見すると文章に見えるようなタイトルは、固有名詞として抽出できませんでした。

これは一体どういうことなのでしょう？
Googleは翻訳においては「進撃の巨人」を固有名詞として「Attack on Titan」という英題に翻訳してくれるというのに、テキスト解析においては判別できず、「進撃」などとバラバラにしてしまっています。
あくまで「形態素解析」なので、進撃の巨人を分解するのが正しいと考えているのか、
単純に翻訳と自然言語処理で使われている辞書・エンジンが異なるということかもしれません。

いずれにせよ、AWSやGoogleを用いた自然言語処理では、日本の「○○の○○」などの固有名詞は
判別できずにバラバラに分解されてしまう、というのが現状（2022年12月現在）のようです。

# Mecab＋Neologd
最後に比較として、日本語の形態素解析の定番ライブラリであるMecabと、固有名詞を大量に含む辞書Neologdを使って品詞分解してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/1fbf12ce-3293-0158-ad45-3d2371b97d36.png)

結果、見事に「進撃の巨人」「ハウルの動く城」「千と千尋の神隠し」を
固有名詞判定できています。

# まとめ

というわけで、こういった固有名詞が多くでてくるテキストを解析処理するためには、
AWSやGoogleよりもMecab＋Neologdが最適と言えるのですが、
残念ながらNeologdは2021年頃から更新が止まっています。
そのため「○○の○○」といった判別の難しい固有名詞が新しく出現した場合には、
今後はNeologdでも固有名詞判別ができない、といった状況になっていくものと思われます。