日本語の自然言語処理 - nltk と Janome -

 前回英文を nltk で読み込んだ際、言葉の集計や描画に matplotlib 等のライブラリが使えたので、日本語についてもそのつもりでいたのですが…。

 何日かの印象でしかありませんが、(少なくとも私にとって)Python 自体の恩恵を簡単に受けられるという点では、Janome というライブラリの方がとっかかりは良いのかもしれない、と感じています。

 

目次

1.nltk による日本語の取り扱い

2.Janome を試してみる

3.まとめ ~ 自然言語処理と可視化

 

1.nltk による日本語の取り扱い

 すでに色々な方が試していらっしゃいますし、「Python による日本語自然言語処理」という、本の 1 章にもなっている詳しいサイトもあります。ニーズやお好みに合わせて参考にされるのが良いかと思います。

www.nltk.org

 nltk を使った日本語読み込みでは、PlaintextCorpusReader という宣言を使って読み込んだファイルのトークン化やコンコーダンス等の例が出ています。

import nltk
from nltk.corpus.reader import *
from nltk.corpus.reader.util import *
from nltk.text import Text

sent_tokenizer = nltk.RegexpTokenizer(u'[^ ()『』【】「」!?。]*[!?。]')
chartype_tokenizer = nltk.RegexpTokenizer(u'([ぁ-んー]+|[ァ-ンー]+|[\u4e00-\u9FFF]+|[^ぁ-んァ-ンー\u4e00-\u9FFF]+)')

jp_text = PlaintextCorpusReader(".",r'*****.txt',
encoding='utf-8',
para_block_reader=read_line_block,
sent_tokenizer=sent_tokenizer,
word_tokenizer=chartype_tokenizer) # *****.txt : File Name

 読み込んだ jp_text に対しトークン化等の命令をするのですが、英文の時とどうも命令が違います。

print(jp_text.raw())                       # jp_text の中身を表示
print(' '.join(jp_text.words()[0:50])) # jp_text のトークン表示

 日本語と英語の違いがあるのは分かりますが、どうも違うことをやっているような気がしたので、PlaintextCorpusReader で読み込んだ jp_text のデータ型を見てみました。

<class 'nltk.corpus.reader.plaintext.PlaintextCorpusReader'>

 英文をトークン化した時はリストであったので、その後 matplotlib 等のライブラリをそのまま使えましたが、PlaintextCorpusReader を使って読み込んだ場合、その中身についてひと手間かけないといけないようです。nltk を使えば、英語と日本語と同様に扱えると思ったのですが、違う操作とデータを扱うのであれば、特に nltk を使って日本語をを操作する積極的な理由がなくなりました。もう少し色々分かってくると解決するかもしれませんが、いったんここで別のライブラリを試してみることにしました。

 

2.Janome を試してみる

 PurePython で書かれた日本語自然言語処理のライブラリで、なんといっても、公式 documentation がとても分かりやすいです。

mocobeta.github.io

 インストールは以下のみで完了です。

pip install janome

 トークン化も、(少なくとも私にとっては)非常に直感的で、以下の script で

from janome.tokenizer import Tokenizer
t = Tokenizer()
for token in t.tokenize(トークン化したいテキスト):
print(token)

トークンの一覧が出ます。

 こうやって token が取り出せるということは、t.tokenize(…) のデータ型は、

<class 'list'>

リストです。つまり、前回英語に関してやったように、collections 等を使って seaborn 等による可視化が出来るということです。

 出来ることが一つでも多いことは、初学者にとってはとてもありがたいことです。が、公式ページには、速度は 10 倍程度 MeCab というライブラリより遅いともあります。現時点では、私は単なるライブラリユーザーなので、ドキュメントやライブラリが使いやすいというのは、十分過ぎるメリットです。 

 

3.まとめ ~ 自然言語処理と可視化

 自然言語データを可視化しようというニーズは、自然言語処理に取り組んでいる方にとっては、おそらくかなり二次的なニーズかとも思います。けれども、分析に改善すべき点があったとしても、ある段階でどこまで到達できたのかについて可視化できることは、少なくとも実務的にはとても意味があると個人的には感じます。

 自然言語と一口に言っても、英語と日本語では構造や単語の処理も違います。自然言語処理にとってはいわば、他の場合におけるデータの前処理、つまり様々な処理を行う前に意味のあるデータの形に整えるための操作がメインターゲットになっている、と言えます。人間にとって全体として意味があるものから、意味を持つ最も小さな単位への細分化。言語自体の分析と並んで、Computer 特有の文字コード等の技術的な違いも相まって、やはりなかなか煩雑な世界のようですね。

 

 本日も最後までお付き合いありがとうございました。

 

『伝道の書』を自然言語処理する - nltk の install、トークン化、使用頻度の plot まで -

 先日の記事を書き、とにかく始めようということで、ライブラリを Install、あれこれいじっていると…、こんなところにも matplotlib が使われているんですね。

目次

1.まずは Install

2.テキストデータの準備、読み込みあれこれ

 2-1.別にデータは何でもいいと思いますが…

 2-2.さあ、読み込みです

 2-3.単語のトークン化

3.トークンのカウントと視覚化

4.トークンのデータ型

5.英単語はやはり横書きがいい

 5-1.matplotlib の barh を使おう

 5-2.seaborn だって使える

6.まとめと野望

 

1.まずは Install 

 『Python による AI プログラミング入門』の 10 章、自然言語処理を片手に、言われるがままライブラリを Install します。

www.oreilly.co.jp

pip install nltk

 場合によっては、ライブラリの一部はすでに Install されているかもしれません。私は Anaconda 3 / Jupyter notebook を普段使っていますが、一部はすでに Install されているようでした。

 いずれにせよInstall が完了したら、次は nltk のデータセットのダウンロードです。このデータセットは、色々な分析の判断基準となる辞書や物語のようです。Python Shell からでも、Jupyter notebook からでもダウンロード可能です。

import nltk
nltk.download()

 Window が新しく出てくるので "ALL" を選びます。回線の早さにもよると思いますが、わりと時間がかかります(1,2 分ではないです)。

 結構色々なものをダウンロードしていたので公式ページを覗いてみると、リストがありましたが、膨大でした…。必要になったら見返そうということで、今回はスルーしました。

www.nltk.org

 ちなみに、データセットには以下の 9 つのお話(book と言うようです)が入っています。

from nltk.book import *
texts()

とすると、お話の一覧が得られます。

text1: Moby Dick by Herman Melville 1851
text2: Sense and Sensibility by Jane Austen 1811
text3: The Book of Genesis
text4: Inaugural Address Corpus
text5: Chat Corpus
text6: Monty Python and the Holy Grail
text7: Wall Street Journal
text8: Personals Corpus
text9: The Man Who Was Thursday by G . K . Chesterton 1908

ついでに、

sents()

とすると、それぞれの text の書き出しが見られます。

sent1: Call me Ishmael .
sent2: The family of Dashwood had long been settled in Sussex .
sent3: In the beginning God created the heaven and the earth .
sent4: Fellow - Citizens of the Senate and of the House of Representatives :
sent5: I have a problem with people PMing me to lol JOIN
sent6: SCENE 1 : [ wind ] [ clop clop clop ] KING ARTHUR : Whoa there !
sent7: Pierre Vinken , 61 years old , will join the board as a nonexecutive director Nov. 29 .
sent8: 25 SEXY MALE , seeks attrac older single lady , for discreet encounters .
sent9: THE suburb of Saffron Park lay on the sunset side of London , as red and ragged as a cloud of sunset .

 横道にそれました。あと一つ、gensim というライブラリも Install してひとまず準備完了です。

conda(あるいはpip) install gensim

 

2.テキストデータの準備、読み込みあれこれ

 2-1.別にデータは何でもいいと思いますが…

 何ができるのか、全く全貌は見えていませんが、まずは、色々操作するためのテキストデータが必要そうです。データセットの text 3 に旧約聖書の『創世記』が入っているのを見て、じゃあ私は、同じく旧約聖書から、『伝道の書』と呼ばれる『コヘレトの言葉(Ecclesiastes)』をデータとしようと決めました。

 興味のあるものをインターネットから探して、text ファイル等にすればよいと思います。

 

 2-2.さあ読み込みです

 何となく予想はしていたのですが、指定しないと文字コードのエラー等出る可能性が高いです。今回はひとまず先に進みたかったので、以下のようにしました。テキストデータは、"ecclesia" という名前にしました。読み込んだデータの一部を print してあります。

with open("Ecclesiastes.txt", mode="r", encoding="ms932", errors="ignore") as file:
ecclesia = file.read()
print(ecclesia)

 当たり前ですが、普通のテキストファイルです。

Ecclesiastes
or
The Preacher
1:1 The words of the Preacher, the son of David, king in Jerusalem.
1:2 Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
1:3 What profit hath a man of all his labour which he taketh …

 

2-3.単語のトークン化

 文章の分析にあたり、単語やカンマ、ピリオドなどに分割し、分割したものをトークン、作業をトークン化というそうです。ひとまずやってみます。

import nltk
from nltk import word_tokenize,sent_tokenize   # import library

token = nltk.word_tokenize(ecclesia)        # トークン化

stop_words = nltk.corpus.stopwords.words('english')
symbol = ["'", '"', ':', ';', '.', ',', '-', '!', '?', "'s"]
clean_token = [w.lower() for w in token if w.lower() not in stop_words + symbol]

print(clean_token)

 トークン化すると、カンマやピリオドも一つのデータとなるため、そういったものを除外し、また、文頭に来た単語は、最初の文字が大文字になるので、それを小文字にする作業をします。そうすれば、テキストデータは意味のある単語に分割されるはずです。上の結果は、次のようになりました。

['ecclesiastes', 'preacher', '1:1', 'words', 'preacher', 'son', 'david', 'king', 'jerusalem', '1:2', 'vanity', 'vanities', 'saith', 'preacher', 'vanity', 'vanities', 'vanity', '1:3', 'profit', 'hath', 'man', 'labour', 'taketh', 'sun', '1:4', 'one', 'generation', 'passeth', 'away',  …

 確かになっているようです。

 

3.トークンのカウントと視覚化

 いろいろ解析はあるのでしょうが、各トークンがどのくらい現れているのか、言い換えれば、ある単語がどの位使われているかを数えるコマンドがあり、しかも図示も出来ます。詳しくは、公式サイトをご覧頂くとして、使用頻度上位 20 個を図示してみました。

clean_frequency = nltk.FreqDist(w.lower() for w in token if w.lower() not in stop_words + symbol)
clean_frequency.plot(20, cumulative=False)

f:id:ohigehige:20201022174012p:plain

 横軸が左から、使用頻度の多いトークン、縦軸がその回数です。便利です。でも、日本語や中国語は、縦書き横書きあっても良いと思うのですが、英語で縦書きはちょっとなあ、というのが否定できない印象だったりもします。

 しかし…、これは何となく(いえ、どう見ても)matplotlib ですよねー。トークンのデータ 型 を見てみることにしました。

 

4.トークンのデータ型

  clean_token の type を調べてみると、予想通り、

<class 'list'>

となり、list でした。というか、「2-3.単語のトークン化」で print した clean_token は、よく見ればリストそのものですね。

 リストと分かれば、あとは単なる視覚化の問題です。こうして nltk から Visualization へと脱線して行きました。

 

5.英単語はやはり横書きがいい

 5-1.matplotlib の barh を使おう

 nltk.FreqDist で試した時同様、使用頻度の高いトークン上位 20 個を横棒グラフにしてみました。やっぱり、英単語は横書きが良いと思うのですが。 

f:id:ohigehige:20201023000420p:plain

 matplotlib で棒グラフに出来ると分かると、色もちょっといじりたくなってしまいました。

import collections

c = collections.Counter(clean_token)
c20 = c.most_common(20)
c20r =list(reversed(c20))

import matplotlib.pyplot as plt
import numpy as np

sns.set()
sns.set_style=("darkgrid")
fig=plt.figure(figsize=(7,7))

y_pos = range(0, 20)
clrs = ['darkolivegreen', 'limegreen', 'greenyellow', 'darkkhaki']
plt.yticks(y_pos, word, fontweight='bold', rotation=10, fontsize='14')
plt.barh(y_pos, count, color=clrs)
plt.xlabel('\nWord Count', fontweight='bold', color = 'black', fontsize='14', verticalalignment='center')
plt.ylabel('Word\n', fontweight='bold', color='black', fontsize='14', verticalalignment='center')

plt.show()

 

5-2.seaborn だって使える

 seaborn なら、countplot があるので、上位 20 語の指定はもっと簡単です。

f:id:ohigehige:20201023001301p:plain

 

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({'Word':clean_token})

fig=plt.figure(figsize=(7,7))
sns.countplot(y="Word", data=df, palette="magma",
order=df.Word.value_counts().iloc[:20].index)

 もっとも、FreqDist 一行で済んだ code をここまで増やすことに価値を見出すかどうかは、やっぱりお好みでしょうね…。

 

6.まとめと野望

 今回は、nltk を Install し、トークン化を試みました。そして、トークンのカウントと視覚化で、大きく脱線して行きました。

 英語の NLP でやることもたくさんあるようですが、まずは日本語が扱える環境を整えたいと思います。

 

 本日も最後までお付き合いありがとうございました。

Python の岐路

 長いこと Python を使っている方には自明なのかもしれませんが、Python の得意、不得意分野、そして行く末に関する記事がありました。

www.zdnet.com

 得意分野は、特にデータサイエンス、機械学習といった流行りの分野、一方、不得意というかほとんど使われていない分野は、Web、Browser Application あるいは Smartphone に関する分野なのだとか。そしてこのままでは、汎用プログラミング言語としての魅力が薄れ、特定の分野にのみ利用される言語に成り下がってしまう可能性がある、と危惧されています。

 私が Python を使おうかなと思った理由は、色々な可視化が出来る Seaborn を使いたかったからでした。そして可視化だけでなく、様々な形式のデータやファイルを扱うのにもめちゃめちゃ便利だったので一気に Python から抜けられなくなり、現在に至ります。

 特定の分野であっても、多くの人が使いたいと引き寄せられるものには、間違いなく意義があると思うのですが、言語自体を作って維持する人達からすれば、多くの人が継続的に関われなくなるものは、衰退の始まりなのかもしれませんね。あるいは、Python 自体の問題というよりは、Web や Smartphone の分野で使われている言語や環境の完成度が高過ぎるのかもしれませんね。

 また、現在の形から改良するよりも、場合によってはゼロから作る方が楽かもしれないし、あるいはまったく別の言語にシフトするかもしれない、とも指摘されています。不完全であっても使われるものは、どんどん改良発展し、完成度が高くても使われる頻度が低いものは、徐々に忘れられてゆく。盛者必衰、スパンの長さに違いはあれど、時の試練を受けているという点では、プログラミング言語と言えども、世の中のものとなんら変わらないということでしょうか。事あるごとに、人気、収入別ランキングといった序列にさらされる、あるいは競争や移り変わりの実に激しい世界なんでしょうね、きっと。

 個人的には、可視化の他には、日本語の自然言語処理をぼちぼちやってみたいと思っているのですが、あまり呑気に構えていると、プログラミング言語の勢力図が大きく変わる可能性は、高くないまでも、決して否定はできないということですね。確かに、また別の言語を覚えなければいけないのは、面白いような、やっぱり面倒のような…。

 本日も最後までお付き合いありがとうございました。

 

気象予報をもう一度見直す - 2020.10.20 -

 今月に入ってから、東京が晴れたのはわずか1日だけだとか。なるほど、何時だったのか確かに思い出せませんが、自分のブログから察するに(あやしいですね!)、どうやらそれは 10/2 のようです。それはともかく、今日朝 9 時の水蒸気画像は、季節の移ろいをはっきり感じさせるものでした。

続きを読む

成層圏を舞うグライダー

 成層圏を Solarglider が飛んで、それが通信基地局となる。色々な意味でブレイクスルーを感じさせる、久しぶりにワクワク感の止まない話だ。

www.softbank.jp

続きを読む

気象予報をもう一度見直す - 2020.10.15 -

  晴れ曇り時雨は定めなきものを

    ふりはてぬるは我が身なりけり (道因、新古今和歌集

 昨晩の予報通り、関東は曇り時々小雨のようで、スカイツリーの先端にも微妙に雲がかかっています。

続きを読む

気象予報をもう一度見直す - 2020.10.13 -

予報時間の一般的な意味での有用性とは

 台風 14 号が南に進路を変える予報を、欧州中期予報センターが予報していたと報じられていました。10 日先まで予測しているということですが、気象庁GSM も 264 時間先までの予報を配信しているので、そういう意味では、11 日先の予報まで出していると言えます。もっとも、台風の予報は 5 日先までなので、一般向けとしては、その位のスパンを対象としているということだと思います。実際、10 日先の天気を言われても、日常生活では話のタネにはなりますが、現実的には、もう少し日が近づいてからと考えるのが普通ですね。

続きを読む

気象予報をもう一度見直す - 2020.10.12 -

はじめに…

 今日東京では、午後になってようやく本格的に晴れ間が覗いてきました。昨日一昨日、台風 14 号通過後、文字通り台風一過の晴天に恵まれた大阪や愛知とはどうも違い、今月東京では、秋の晴天にはもちろん恵まれているものの、見上げると目を細めたくなる抜けるような青空は、愛知以西に比べるとやや少なめのような気がします。

続きを読む