astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

英文の自然言語処理におススメ!お手軽なPolyglotを使ってみた。

f:id:astamuse:20170719113042j:plain

こんにちは。白木(@YojiShiraki)です。デザイナーです。
今日はPythonで英文形態素解析をする上でお手軽便利なpolyglotについて紹介します。

背景

当社ではデータを分析・解析する機会がままありまして、こうしたときに自然言語解析の処理のツールを利用しています。特に最近では英語データが多く、このあたりのツールのニーズが高くなっています。

しかし、いざ英語の解析となると意外に情報がありません

例えば、日本語の解析ならMeCabChaSenKuromojiといったものはすぐ見つかります。しかし英文の自然言語解析ではTreeTaggerの情報は目につくもののイマイチまとまった情報がありません(このページこのページに他の選択肢がまとまっていますが)。

おそらくこの領域ではNLTKが王道なのかと思いますが、やや重厚感あります。

そこでもう少しライトなものをということでPolyglot*1をご案内します。

Polyglotとは?その特徴

Polyglotは様々な機能を持つPythonの自然言語解析モジュールです。対応している自然言語も幅広くインストールも非常に簡単です。サンプル実装のドキュメントも一通りそろっており、ちょっと真似すれば簡単に自然言語解析ができます。

まずはざっと特徴を見てみましょう(公式ままです)。

機能 機能(英語) 対応言語
分かち書き(トークン化) Tokenization 165 言語
言語判定 Language detection 196 言語
固有表現抽出 Named Entity Recognition 40 言語
品詞タグ付け Part of Speech Tagging 16 言語
センチメント分析・感情分析 Sentiment Analysis 136 言語
分散表現 Word Embeddings 137 言語
形態素解析 Morphological analysis 135 言語
翻字 Transliteration 69 言語

分かち書きの165言語対応もさることながら、言語判定196言語というのが凄まじいです。この辺りは後ほど一つずつ見ていきます。

またコマンドラインから直接叩けるのも魅力的です。例えば言語判定の機能をコマンドから呼ぶときは

polyglot detect --input testdata/cricket.txt

というコマンドによって、testdata/cricket.txtに記載されている言語の判定を行ってくれます。

ライセンス

PolyglotはGPLv3 licenseにて公開されています(2017年7月18日現在)。一般的なOSSのライセンスですね。商用利用可能です。

インストール方法

では早速インストールしてみましょう。 今回の開発環境は以下の通りです。

  • Ubuntu 14.04 @GCP
  • Python 3.4.3

なお、Polyglotは Python >=2.7 もしくは Python >=3.4. をサポートしています。

パッケージ・モジュールのインストール

ざっと以下のパッケージやモジュール等をインストールします。

公式ドキュメントにはnumpylibicu-devが必要とのことですが、それだけでは足りませんでした。経験的には以下のようにインストール進めれば問題ないと思います。

$ sudo apt-get update
$ sudo apt-get install libicu-dev
$ sudo apt-get install python3-pip
$ sudo -H pip3 install --upgrade pip
$ sudo -H pip3 install numpy
$ sudo -H pip3 install polyglot
$ sudo -H pip3 install pyicu
$ sudo -H pip3 install pycld2
$ sudo -H pip3 install morfessor

モデルのインストール

Polyglotは使う機能と対象とする自然言語に応じてモデルをダウンロードする必要があります。例えば英文に対して品詞抽出する場合は以下のようにembeddings2.enpos2.enをインストールします。

# 英語の品詞抽出用のモデルをDL
$ polyglot download embeddings2.en pos2.en

どの処理に対してどのモジュールをインストールすべきかは、エラーメッセージに書いてくれるのでそちらを参考にするのがよいです。例えば以下のようなエラーです。

ValueError: This resource is available in the index but not downloaded, yet. Try to run
polyglot download embeddings2.fr    # -> フランス語のモデルをダウンロードするように言われている

では引き続き個別の実装についてみていきます。

実装:言語判定

まずは言語判定からいきましょう。言語判定はモデルのダウロード不要です。インストールしたら即使えます。 ここでは試しにフランス語を判定させます。

# -*- coding:utf-8 -*-

from polyglot.detect import Detector

t = "Hé ! bonjour, Monsieur du Corbeau.Que vous êtes joli ! Que vous me semblez beau !"
detector = Detector(t)
print(detector)

結果はこちら。

Prediction is reliable: True
Language 1: name: French      code: fr       confidence:  98.0 read bytes:   811
Language 2: name: un          code: un       confidence:   0.0 read bytes:     0
Language 3: name: un          code: un       confidence:   0.0 read bytes:     0

フランス語が信頼度98.0で返ってきます。

特定の値だけ抽出したい場合は以下のように書きます。

print(detector.language.name)       # -> French
print(detector.language.code)       # -> fr
print(detector.language.confidence) # -> 98.0
print(detector.language.read_bytes) # -> 811

またdetecotr.languagesがイテレーターとなっているので

for lang in detector.languages:
    print(lang.name)

といった使い方もできます。

実装:分かち書き、品詞タグ付け

続いて分かち書きと品詞タグ付けです。先ほどのフランス語を対象にやってみます。 が、その前にフランス語を分かち書きするためにモデルをダウンロードします。

$ polyglot download embeddings2.fr pos2.fr

そのうえで、下記のコードを実行してみてください。

# -*- coding:utf-8 -*-

from polyglot.text import Text

t = "Hé ! bonjour, Monsieur du Corbeau.Que vous êtes joli ! Que vous me semblez beau !"
tokens = Text(t)
print(tokens.words)

結果としては

['Hé', '!', 'bonjour', ',', 'Monsieur', 'du', 'Corbeau.Que', 'vous', 'êtes', 'joli', '!', 'Que', 'vous', 'me', 'semblez', 'beau', '!']

が返ってきており分かち書きされていることが確認できます。 なお「なぜフランス語?」というツッコミは無しでお願いします(気づいたらそうなってただけです)。

引き続き品詞タグ付けします。

# -*- coding:utf-8 -*-

from polyglot.text import Text

t = "Hé ! bonjour, Monsieur du Corbeau.Que vous êtes joli ! Que vous me semblez beau !"
tokens = Text(t)
for token in tokens.pos_tags:
    print(token)

おそらくこのような結果が返ってきたかと思います。

('Hé', 'PROPN')
('!', 'PUNCT')
('bonjour', 'PROPN')
(',', 'PUNCT')
('Monsieur', 'PROPN')
('du', 'DET')
('Corbeau.Que', 'PUNCT')
('vous', 'PRON')
('êtes', 'VERB')
('joli', 'ADJ')
('!', 'PUNCT')
('Que', 'PRON')
('vous', 'PRON')
('me', 'PRON')
('semblez', 'VERB')
('beau', 'ADJ')
('!', 'PUNCT')

よさそうです。 単語と品詞を別々に取り出すにはこんな感じです。

# -*- coding:utf-8 -*-

from polyglot.text import Text

t = "Hé ! bonjour, Monsieur du Corbeau.Que vous êtes joli ! Que vous me semblez beau !"
tokens = Text(t)
for token in tokens.pos_tags:
    print("{0:20s}{1}".format(token[0], token[1]))

結果はこちら。

Hé                  PROPN
!                   PUNCT
bonjour             PROPN
,                   PUNCT
Monsieur            PROPN
du                  DET
Corbeau.Que         PUNCT
vous                PRON
êtes                VERB
joli                ADJ
!                   PUNCT
Que                 PRON
vous                PRON
me                  PRON
semblez             VERB
beau                ADJ
!                   PUNCT

ちなみに、分かち書きの際に言語判定も行っているのでこんな使い方もできます。

# -*- coding:utf-8 -*-

from polyglot.text import Text

t = "Hé ! bonjour, Monsieur du Corbeau.Que vous êtes joli ! Que vous me semblez beau !"
tokens = Text(t)
print(tokens.language)            # name: French   code: fr confidence:  98.0 read...
print(tokens.language.name)       # -> French
print(tokens.language.code)       # -> fr
print(tokens.language.confidence) # -> 98.0
print(tokens.language.read_bytes) # -> 811

実装:固有表現抽出

文章の中から固有表現の抽出を行います。これも実装は今までと大きく変わりません。 まずはモデルのダウンロード。今回は英文を対象に行うので英語用のモデルです。

$ polyglot download ner2.en

コードはこちら。文章はWikipediaの記事を一部利用しています(ref. New York)。

# -*- coding:utf-8 -*-

from polyglot.text import Text

t = ("New York is a state in the northeastern United States. "
     "New York is bordered by New Jersey and Pennsylvania to the south and Connecticut, Massachusetts, and Vermont to the east. "
     "The state has a maritime border in the Atlantic Ocean with Rhode Island, east of Long Island, "
     "as well as an international border with the Canadian provinces of Quebec to the north and Ontario to the northwest. "
     "New York was one of the original Thirteen Colonies that formed the United States. "
     "The state of New York, with an estimated 19.8 million residents in 2015,[9] is also referred to as New York State to distinguish it from New York City, "
     "the state's most populous city and its economic hub.")

tokens = Text(t)
for entity in tokens.entities:
    print(entity.tag, entity)

結果。

I-LOC ['York']
I-LOC ['United', 'States', '.', 'New', 'York']
I-LOC ['New', 'Jersey']
I-LOC ['Pennsylvania']
I-LOC ['Connecticut', ',', 'Massachusetts']
I-LOC ['Vermont']
I-LOC ['Rhode']
I-LOC ['Long']
I-LOC ['Canadian']
I-LOC ['Quebec']
I-LOC ['Ontario']
I-LOC ['.', 'New', 'York']
I-LOC ['United', 'States']
I-LOC ['New', 'York']
I-LOC ['New']
I-ORG ['New', 'York']
I-LOC ['New', 'York', 'State']
I-LOC ['New', 'York', 'City']

I-LOCと出ているのは場所の固有表現を表しています。ソースを見るとI-LOC以外にも組織を表すI-ORGや人物名を表すI-PERがあります。

その他

その他にも幾つか機能があります。特に面白いのは「センチメント分析・感情分析」と「分散表現」あたりですが、今回は時間の都合上割愛させてください(ソース読みきれませんでした・・)。後日、余力に応じて本稿に書き足します。

終わりに

いかがだったでしょうか、英文に限らず複数言語の自然言語に対応したPolyglot。

実は今回はgensimを使った英文のトピックモデルの実装(といってもコピペレベルですが)について書こうと思っていました。しかし英文自然言語解析の処理を書いてる時に「ライトで使いやすい自然言語解析ツール」の情報(日本語)が意外になく、「これ困っている人いるんじゃないか?」と思いテーマを変更したという経緯があります。

そういう意味では、この投稿をみて助かってくれる人が出てきたらいいな、と思います。そして英文の自然言語解析の世界が少しでも身近に感じてもらえれば嬉しいです。

なお、gensimからのLDAネタは今行っている実験うまくいったら書きます(フラグ)。

では、本日も最後までお読みいただきありがとうございました。

例によって当社では一緒に開発してくれるメンバーを募集しております。カジュアル面談も随時行っておりますので、「ちょっと話聞きたい」という方は、このブログのサイドバー下にあるアドレスか@YojiShirakiあたりにDMいただければと思います。

*1:Polyglotというと多言語プログラミング的なイメージが強いかもしれませんが、それとは別です。

Copyright © astamuse company, ltd. all rights reserved.