Google Natural LanguageとMeCab それぞれで日本語を構文解析してみる

8/6 13:30 追記
内容・表現が適切でないというフィードバックをいただきまして、内容を加筆修正しました。ご指摘いただきありがとうございましたmm

日本語の文章を機械に理解してもらうために文章を「分かち書き」に変換することを考えます。例えば、

「今日はいい天気です」→「今日 は いい 天気 です」

のような感じです。

Google Natural LanguageとMeCabを使って構文を解析してみたのでその内容をメモします。

調査の背景

ラジオ番組のレコメンドAPIを作ろうとしています。

文章を分かち書きにするのにこれまではMeCabを使っていました。ここで、他の選択肢、例えばGoogle Natural Language APIを使ってみたらどうなのかが気になったので試してみました。

Google Natural Languageで解析する

Google Natural Languageでは下記のような機能が提供されています。

・構文解析(品詞の特定など)
・エンティティ分析(日付、人、商品などをラベル付け)
・感情分析
・コンテンツの分類

今回は文章から名詞を取り出すために構文解析を利用します。実装は以下のようになります。

from google.cloud import language
from google.cloud.language import enums

def parse(text):
   client = language.LanguageServiceClient()
   
   document = {"content": text,
               "type": enums.Document.Type.PLAIN_TEXT,
               "language": 'ja'}
               
   response = client.analyze_syntax(document, 
               encoding_type=enums.EncodingType.UTF8)
               
   words = []
   for token in response.tokens:       
       part_of_speech_tag = enums.PartOfSpeech.Tag(token.part_of_speech.tag)
       
       if part_of_speech_tag.name == "NOUN":
           words.append(token.text.content)

   return words

準備として、APIを有効にし、サービスアカウントキーファイルを用意することが必要です。
こちらのドキュメント通りに進めれば動くようになると思います。

analyze_syntax で構文解析し、その結果のうち NOUN(名詞)だけを選択して配列に格納しています。

今回はサンプルデータとして、バナナマンがMCを務めるラジオ番組「バナナムーンGOLD」の感想ツイート1,000件を入力してみます。(ツイートの取得方法はこちら

まずはツイートを読み込みます。

# ファイルを読み込み
test_tweets = []
for line in open('test/#bananamoon.txt', 'r'):
   test_tweets.append(line)
   
# 複数ツイートを一つに連結
tweet = " ".join(test_tweets)

print(len(tweet))  # -> 34213. 34,213文字のひとつの文章になっている

いま読み込んだ tweet を先ほどの parse に渡してみます。

# Google Natural Languageで名詞を取り出す
result = parse(tweet)

len(result)  # -> 3090. 3,090の単語を取り出せた

34,213文字の文書から3,090個の名詞を取り出すことができました。各単語の登場回数をカウントしてみましょう。

from collections import Counter

counter = Counter(result)

for word, count in counter.most_common():
   print(word, count)

結果は以下のようになりました:

お疲れ様 256
乃木坂 104
工事 101
:/ 65
スズキタケヤス 65
bananamoon 53
バナナムーン 4832
日村 31
設楽 31
バナナマン 30
包茎 28
ラジオ 24
今日 24
お疲れさま 23
笑笑 21
乃木 20
TF 19
ドロボー 17
ANN 16
キングダム 15
さま 15
ゲーム 14
www 14
リスナー 14

(...以下略)

バナナムーンGOLDのMCである「バナナマン」「日村」「設楽」や、番組で話題になった言葉「キングダム」「乃木坂」が確認できます。

番組を表現する単語としても違和感のないデータが取得できました。

MeCabで解析する

次はMeCabで構文解析してみます。

まずは、mecab-ipadic-neologd を使わずに解析します。

import MeCab

def mecab_parse(text):
   mecab = MeCab.Tagger('-Ochasen')
   mecab.parse('')  # 文字列がGCされるのを防ぐ
   node = mecab.parseToNode(text)
   words = list()
   while node:
       word = node.surface
       word_type = node.feature.split(",")[0]
       if word_type in ["名詞"]:
           if word != "*":
               words.append(word)
       node = node.next
   return words

インストールの方法などは以前の記事で書きました。こちらのコードを実行すると以下のようになります。

# 1216
bananamoon 990120112
乃木坂 105
工事 101
さん 92
/ 8480
. 72
バナナ 70
t 68
https 65
:// 65
co 65
w 64
スズキタケヤス 62
ムーン 46
2 41
マン 3332
設楽 31

(... 以下略)

MeCab + mecab-ipadic-NEologd で解析する

次は、MeCabとmecab-ipadic-NEologdで解析してみます。

mecab-ipadic-NEologdはMeCabと一緒に使える、新語や固有表現に強い辞書です。Web上のリソースから週に2回更新されており、利用することで新語・未知語の解析結果が改善することを期待できます。

詳細はこちら:

mecab-ipadic-neologd/README.ja.md - GitHub
新語・固有表現に強い「mecab-ipadic-NEologd」の効果を調べてみた
【Node.js】kuromoji.js + mecab-ipadic-neologdで形態素解析して遊ぶ

実装は以下のように変更します。

import MeCab

def mecab_parse(text):
   # ここを変更
   mecab = MeCab.Tagger('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
   
   mecab.parse('')  # 文字列がGCされるのを防ぐ
   node = mecab.parseToNode(text)
   words = list()
   while node:
       word = node.surface
       word_type = node.feature.split(",")[0]
       if word_type in ["名詞"]:
           if word != "*":
               words.append(word)
       node = node.next
   return wordsGoogle Natural Language が3,090個の名詞を取り出したのに対して、MeCabでは4,706個です。

単語ごとの登場回数は以下のようになります。

 #bananamoon  982
乃木坂工事中 93
さん 8969
https 65
t 65
co 65
w 6564
スズキタケヤス 6032
www 31
設楽 30
バナナムーン 29
chelmico 2928
包茎 28
日村 27
ちんぽ 27
ちゃん 2626
バナナマン 24
今日 24
ww 22
2 2121
TF 21
笑笑 21
乃木中 20

(.. 以下略)

「#bananamoon」や「乃木中」など、比較的最近に生まれた単語、ハッシュタグが正しく判別できています。

mecab-ipadic-NEologdは以下のようなエントリ内容から更新されます。

- ニュース記事から抽出した新語や固有名詞や未知語
- ネット上で流行した単語や慣用句やハッシュタグ
- 一般名詞/固有名詞/サ変接続名詞の表記ゆれ
- パターン生成した時間表現や数値表現
- Unicode 9.0 以下の絵文字
- 初期状態のスマホで入力できる顔文字

ツイートからデータを集めることを考えているので、mecab-ipadic-NEologdの恩恵を非常に受けられるように思います。

まとめ

Google Natural Language APIとMeCabを使って日本語の文書から名詞抽出してみました。MeCabはmecab-ipadic-NEologdを利用しなかった場合・利用した場合の2パターンで解析しました。

Google Natural Language APIの料金はこちらで確認できます。
無料枠も用意されており、小規模なプロジェクトではそこまで気にせずとも良さそうです。

参考リンク

↑文書から特徴量を抽出する部分の説明が分かりやすかったです

この記事が気に入ったらサポートをしてみませんか?