nikkie-ftnextの日記

イベントレポートや読書メモを発信

『入門 自然言語処理』5章から、英語テキストでも品詞分類できると知った私は、特定の品詞を取り出したWordCloudを試してみました

はじめに

頑張れば、何かがあるって、信じてる。nikkieです。
2019年12月末から自然言語処理のネタで毎週1本ブログを書いています。

先週から自然言語処理の基礎固めとして『入門 自然言語処理』に取り組んでいます。

入門 自然言語処理

入門 自然言語処理

今週は5章「単語の分類とタグ付け」の冒頭部分、品詞タグ付けの紹介から、英語のテキストについて品詞タグ付けを試してみました。

目次

前回までのブログ駆動開発!との関連

先日 janomeチュートリアル1の中で、「風の又三郎」(日本語テキスト)から名詞と動詞を取り出して、WordCloudを作りました。

チュートリアルは、英語テキストの例として、『不思議の国のアリス』でもWordCloudを作っています2

『入門 自然言語処理3で、英語テキストについての品詞タグ付け(以下、タグ付け)を知りました。
「『風の又三郎』の例で品詞を名詞と動詞に絞ったのと同じように、『不思議の国のアリス』でも品詞を絞れるのでは?」と着想し、試してみました。
不思議の国のアリス』の英語テキストから、名詞と動詞を使ってWordCloudを作ります

動作環境

先週と同じ環境に、WordCloud作成に必要なパッケージを追加しました。

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G103
$ python -V  # venvによる仮想環境を使用
Python 3.7.3
$ pip list  # grepを使って抜粋して表示
beautifulsoup4   4.8.2
ipython          7.12.0
matplotlib       3.1.3  # 追加
nltk             3.4.5
wordcloud        1.6.0  # 追加

WordCloudを作れるよう、janomeチュートリアルに沿った環境構築をします。

$ unzip ~/Downloads/ipagp00303.zip -d .
$ wget https://raw.githubusercontent.com/mocobeta/janome-tutorial/master/hands-on/data/alice_utf8.txt .

フォルダ配置

.
├── alice_utf8.txt
├── alice_word_cloud.py
├── env
├── ipagp00303
└── result  # 作成したWordCloudの画像を置く

nltk を使ったタグ付け

nltk.word_tokenize したテキスト(トークンのリスト)をnltk.tag.pos_tagでタグ付けできます。

Use NLTK’s currently recommended part of speech tagger to tag the given list of tokens.

今回使われたタガーは averaged_perceptron_tagger のようです(例のごとくnltk.downloadが必要でした)

以下は、同音異義語が登場する例です。

In [8]: text = nltk.word_tokenize("They refuse to permit us to obtain the refuse permit")

In [9]: nltk.pos_tag(text)
Out[9]:
[('They', 'PRP'),
 ('refuse', 'VBP'),
 ('to', 'TO'),
 ('permit', 'VB'),
 ('us', 'PRP'),
 ('to', 'TO'),
 ('obtain', 'VB'),
 ('the', 'DT'),
 ('refuse', 'NN'),
 ('permit', 'NN')]

結果から、

  • 名詞はNNで始まる
  • 動詞はVBで始まる

ようです。
書籍 例5-1 のプログラムを見たところ、これらはNNやVBで始まると仮定してよさそうだったので、続きを考えていきました(時間の制約により掘り下げられていません)。

ソースコード

import matplotlib.pyplot as plt
import nltk
from wordcloud import WordCloud


SEED = 42


def show_wordcloud(text, save_path):
    if isinstance(text, list):
        text = ' '.join(text)
    wordcloud = WordCloud(
        font_path='ipagp00303/ipagp.ttf',
        background_color='white',
        width=1024,
        height=674,
        random_state=SEED,
        collocations=False).generate(text)
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.savefig(save_path)


if __name__ == '__main__':
    with open('alice_utf8.txt', encoding='utf8') as f:
        concatenated_text = f.read()
        concatenated_text = concatenated_text.lower()  # 正規化
    show_wordcloud(concatenated_text, 'result/orig_alice_cloud.png')

    text = nltk.word_tokenize(concatenated_text)
    print(f'tokenized: {len(text)}')
    show_wordcloud(text, 'result/tokenized.png')

    tagged = nltk.pos_tag(text)
    nouns_and_verbs = [
        word for word, tag in tagged if tag.startswith(('NN', 'VB'))]
    print(f'tagged: {len(nouns_and_verbs)}')
    show_wordcloud(nouns_and_verbs, 'result/nouns_and_verbs.png')

作成されたWordCloud

上記のスクリプトを実行すると、3つのWordCloudができます。

  1. 元のファイルの全文から作ったWordCloud
  2. word_tokenizeした後の単語から作ったWordCloud
  3. 2から名詞と動詞を取り出して作ったWordCloud

1.元のファイルの全文から作ったWordCloud

f:id:nikkie-ftnext:20200216233810p:plain

2. word_tokenizeした後の単語から作ったWordCloud

f:id:nikkie-ftnext:20200216233826p:plain

n't という単語が現れているところにトークン化の効果が感じられます。

WordCloud.generateには、自然言語のテキスト(a natural text)を渡す必要があるため、単語のリストを半角スペースでjoinして自然言語のテキストのように見せました。

3. 2から名詞と動詞を取り出して作ったWordCloud

f:id:nikkie-ftnext:20200216233836p:plain

WordCloudに含まれる単語数は

  • トークン化で12460語
  • 名詞と動詞を取り出して4106語

と変化しました。
queen などの名詞が2より大きく表示されているところに効果を感じます。
風の又三郎の例のように、見ただけで内容が分かるようにしたいので、工夫の余地はありそうですね。

感想

今週平日は別に締切のあったタスクを進め、土日はOOC 2020の当日スタッフをし、いま、OOCの達成感と疲労の中でたびたび意識を飛ばしつつ、この記事を書いています。
これまでの週に比べると短縮版ではありますが、「『風の又三郎』の例でやったことは日本語に限らず英語でもできるんだ」という気づきがありました。

入門 自然言語処理』を読み進めることで、言語の違いによらない、自然言語処理の抽象的な方法を学べそうという印象です。
土曜日にお別れの会が執り行われたPython2系ですが、『入門 自然言語処理』を通して引き続き思い出作りをしていきます。

課題

  • startswith(('NN', 'VB'))よりも深堀りした名詞・動詞の取り出し方
    • そのために5章をもっと読む
  • 3章のステミングやレマタイズを取り入れる
  • WordCloudの余白は、matplotlibのコードのどこが原因?