NLP本読み進めシリーズ

「入門 自然言語処理」第1回

(オライリー・ジャパン)

主体:とりさん(@torithetorick
代役:nezuq(@nezuq

#NLPStudy

シリーズについて

「入門 自然言語処理」を章ごとに読み進めます。
発表する予定があると、NLPを学ぶモチベーションが上がります!
一緒に発表しましょう!

「入門 自然言語処理」 is 何?

「入門 自然言語処理」 is 「NLTK Book」の翻訳本 .

×NLPの入門書
○NLTK(Python製のNLP用ライブラリ)の入門書

学びたいのは"NLP"であって、"NLTK"ではない。
そういう方でも、NLP入門にオススメです。

  • NLPの基礎も説明されている。
  • Python(データ分析で定番のプログラミング言語)を使い、手を動かしながら覚えられる。
  • 原書と日本語版で追加された12章は、Web上で無料公開されている。
     → NLTK Book
     → Python による日本語自然言語処理

読み進めると、具体的にどのような事ができる?

ex.文書分類(文書を自動でカテゴリ分けする)
 NLTKを使い、政治家のつぶやきから政党を当てる試みをしている方がいました。
  → 200行で書けるテキスト分類

さっそく、第1回の発表を行います。

第1回の発表は「1章 言語処理とPython」を対象にします、

1章 言語処理とPython

そもそもPythonとは?

  • オブジェクト指向型のスクリプト言語です。#Rubyと立ち位置は同じ
  • シンプルさを追求とした文法で、初心者が扱いやすいです。#Google3大言語の一つ
  • データ分析界隈で良く使われます。#Rと並ぶ

基本

In [57]:
#関数を定義する
def add(x, y):
  return x + y

print(add(1, 2))
3
In [62]:
#繰り返し文と条件分岐
xs = [-3,0,3]
for x in xs:
  if x > 0:
    print('正の値です。', x)
  elif x == 0:
    print('0です。', x)
  else:
    print('負の値です。', x)
負の値です。 -3
0です。 0
正の値です。 3

リスト/文字列

要素数のカウント

In [19]:
#リストの要素数を取得する。
len(['aaa', 'bbb', 'ccc'])
Out[19]:
3
In [15]:
# ※文字列も文字のリストとして扱える。
len('abc')
Out[15]:
3

重複削除・ソート

In [16]:
#要素の重複がないリストを作る。
set(['a', 'b', 'c', 'a'])
Out[16]:
{'a', 'b', 'c'}
In [17]:
#要素を順番に並べる。
sorted(['b', 'a', 'c'])
Out[17]:
['a', 'b', 'c']

要素の追加・結合

In [18]:
#リストを結合する。
['a', 'b'] + ['c', 'd']
Out[18]:
['a', 'b', 'c', 'd']
In [34]:
#リストを繰り返す。
['a', 'b', 'c'] * 2
Out[34]:
['a', 'b', 'c', 'a', 'b', 'c']
In [36]:
# ※文字列も繰り返せる。
'abc' * 2
Out[36]:
'abcabc'

スライシング

In [30]:
#要素から値を取得する。
x = ['a', 'b', 'c', 'd', 'e']
x[1]
Out[30]:
'b'
In [31]:
#要素から値を取得する。(〜以上〜未満)
x[1:3]
Out[31]:
['b', 'c']
In [32]:
#要素から値を取得する。(〜以上)
x[1:]
Out[32]:
['b', 'c', 'd', 'e']
In [33]:
#要素から値を取得する。(〜以下)
x[:3]
Out[33]:
['a', 'b', 'c']
In [38]:
# 文字列にも同じ指定ができる。
'abcde'[1:3]
Out[38]:
'bc'
In [40]:
#要素から値を取得する。(後ろから〜以上)
x[-2:]
Out[40]:
['d', 'e']
In [41]:
#要素から値を取得する。(後ろから〜未満)
x[:-2]
Out[41]:
['a', 'b', 'c']

リスト⇔文字列

In [43]:
#リスト→文字列
'|'.join(['a','b','c'])
Out[43]:
'a|b|c'
In [44]:
#文字列→リスト
'a|b|c'.split('|')
Out[44]:
['a', 'b', 'c']

リスト内包表記

In [51]:
[x.upper() for x in ['dddd', 'bb', 'ccc', 'a' ,'eeeee'] if len(x) > 2]
Out[51]:
['DDDD', 'CCC', 'EEEEE']

外部ライブラリの呼び出し

In [65]:
import nltk
In [ ]:
from nltk.book import *
In [ ]:
from nltk.text import Text

NLTKとは?

  • Python用のNLPツールキット(Natural Language Toolkit)です。
  • 大量の英語コーパスが付属しています。
  • 日本語を扱う為には、12章の処理が必要です。

NLTKの関数

日本語を使う為の設定

$MeCabとそのPythonバインディングをインストールする。
sudo apt-get install libmecab-dev
sudo apt-get install mecab mecab-ipadic-utf8
pip install mecab-python3

In [67]:
#Plotのフォントで、日本語フォントを指定する。
import matplotlib
import matplotlib.font_manager as font_manager
font_path = '/usr/share/fonts/truetype/fonts-japanese-gothic.ttf'
font_prop = font_manager.FontProperties(fname = font_path)
matplotlib.rcParams['font.family'] = font_prop.get_name() #font_prop.get_name()でフォント名を文字列指定するなら、前2行は不要
In [68]:
import nltk
from nltk.corpus.reader import *
from nltk.corpus.reader.util import *
from nltk.probability import *
from nltk.tokenize.api import *
from nltk.text import Text
In [69]:
#MeCabでの文書解析器
class JPMeCabTokenizer(TokenizerI):
    def __init__(self):
        import MeCab
        self.mecab = MeCab.Tagger('-Owakati')

    def tokenize(self, text):
        result = self.mecab.parse(text)
        return result.strip().split(' ')

jp_sent_tokenizer = nltk.RegexpTokenizer('[^ 「」!?。]*[!?。]')

NLP関数

In [ ]:
#NLTKパッケージ(ex.コーパス)をダウンロードする。
nltk.download()
In [ ]:
#文書内から指定単語が使われている文を探す。
text1.concordance("単語")
In [ ]:
#文書内から指定単語と同じ文脈で使われている文を探す。
text1.similar("単語")
In [ ]:
#文書内から指定単語(複数)と同じ文脈で使われている文を探す。
text1.common_contexts(["単語1", "単語2"])

描画

In [70]:
#文書内の単語を取得
reader = PlaintextCorpusReader(
    "/home/owner/data/小説", r'A_NKMK_4099483.txt',
    para_block_reader=read_line_block,
    sent_tokenizer=jp_sent_tokenizer,
    word_tokenizer=JPMeCabTokenizer())
words = reader.words()
texts = Text(reader.words())
#頻度分布を作る
fdist = FreqDist(words)
-c:8: ResourceWarning: unclosed file <_io.BufferedReader name='/home/owner/data/小説/A_NKMK_4099483.txt'>
In [71]:
#Plotで日本語を使う為の設定
import matplotlib
import matplotlib.font_manager as font_manager
font_path = '/usr/share/fonts/truetype/fonts-japanese-gothic.ttf'
font_prop = font_manager.FontProperties(fname = font_path)
matplotlib.rcParams['font.family'] = font_prop.get_name() #font_prop.get_name()でフォント名を文字列指定するなら、前2行は不要
In [74]:
#描画(単語の累積比率)
fdist.plot(30, cumulative = True)
In [76]:
#描画(単語の出現位置)
from nltk.draw.dispersion import dispersion_plot
dispersion_plot(texts, ['ちゃん', 'さん', '君'])