Python & NLTKでなんちゃって機械学習を体験してみる

  • #技術ブログ 

お久しぶりです!!って前回の更新から3か月経過、、、。
さぼり癖が止まらないうえピーです。

なんとか年の瀬前に更新をねじ込めて良かったとほっと胸を撫で下ろした
今回は、「自然言語処理のNLTKパッケージ」を使って遊んでみたいと思います。
きっかけは、最近じーっと本棚を眺めていて、そういえばオライリーの「入門 自然言語処理」面白かったなぁって感じです。

この本を私が大好きな理由は、

  1. 4章の内容がPython初学者だった私にベストフィットした甘い思い出
  2. 初版から10年たつので、Python 3と最新のNLTKで動かそうとするとサンプルプログラムが動かない場所が多々ある
  3. それを少し調査して動かすのがたまらなく楽しい
  4. 英語とはいえNLTKのサンプルデータが多彩なので、本を少しアレンジして自分なりに分析したりする敷居が低い

ちょっと待て、Prediction Oneの続きじゃないんかーいという突っ込みは華麗にスルーして、

今回のPlay環境は以下の通りです。

  1. Windows 7 64bit
  2. Anaconda 3.4.2
  3. Python 3.7.4
  4. NLTK 3.4.5

何して遊ぶかといいますと
NLTKのブラウンコーパスに含まれるNewsセクションのテキストを使って、自動で品詞タグ(名詞とか冠詞とか動詞とか)を単語につけてみようと思います。
ちなみにブラウンコーパスとはブラウン大学で作成されたたくさんのテキストデータです。
ちゃんと正しく品詞タグがついたデータも存在しているので、教師あり学習にぴったりです。

さて、事前準備は、シンプルでして、
コマンドプロンプトを立ち上げまして、

> conda install nltk

そして、Pythonのインタプリタでコーパスをダウンロードします。

>>> import nltk
>>> nltk.download()

brownを選択してダウンロードです。

準備できたら、さっそく品詞タグの自動タグ付けを実装してみます。
詳しくは、5章 単語の分類とタグ付けをみてね!!
本は、Python 2系でNLTKも古いからかなり読み替えなきゃだけど!!

01: import nltk
02: from nltk.corpus import brown
03: from nltk.tag import brill
04: from nltk.tag.brill_trainer import BrillTaggerTrainer
05:
06: brown_tagged_sents = brown.tagged_sents(categories=’news’)
07: size = int(len(brown_tagged_sents) * 0.9)
08: train_sents = brown_tagged_sents[:size]
09: test_sents = brown_tagged_sents[size:]
10:
11: t0 = nltk.DefaultTagger(‘NN’)
12: t1 = nltk.UnigramTagger(train_sents, backoff=t0)
13: t2 = nltk.BigramTagger(train_sents, backoff=t1)
14: t3 = nltk.tag.sequential.AffixTagger(train_sents,affix_length=-4,min_stem_length=5, backoff=t2)
15: t4 = nltk.tag.sequential.AffixTagger(train_sents,affix_length=2,min_stem_length=11,backoff=t3)
16: t5 = BrillTaggerTrainer(t4, brill.fntbl37(), trace=3).train(train_sents, max_rules=50)
17: print(“DefaultTagger.evaluate = “, t0.evaluate(test_sents))
18: print(“UnigramTagger.evaluate = “, t1.evaluate(test_sents))
19: print(“BrillTaggerTrainer.evaluate = “, t2.evaluate(test_sents))
20: print(“AffixTaggerTrainer.evaluate(suffix) = “, t3.evaluate(test_sents))
21: print(“AffixTaggerTrainer.evaluate(prefix) = “, t4.evaluate(test_sents))
22: print(“BigramTagger.evaluate = “, t5.evaluate(test_sents))
23: print(t5.tag(nltk.word_tokenize(“They wind back the clock, while we chase after the wind.”)))

では、折角なので実行前に簡単にプログラムの説明を。
まず、01~04は必要なライブラリのインポートです。
06~09は、ブラウンコーパスのニュースセクションから品詞タグ付け済みの教師データを検証データを生成しています。
11~16は、自動タグ付け機を以下の順番で、実行している感じです。

  1. BrillTaggerでタグ付け
  2. 上記でタグ付けできなかったデータに対して、AffixTagger(接頭辞)でタグ付け
  3. 上記でタグ付けできなかったデータに対して、AffixTagger(接尾辞)でタグ付け
  4. 上記でタグ付けできなかったデータに対して、BigramTaggerでタグ付け
  5. 上記でタグ付けできなかったデータに対して、UnigramTaggerでタグ付け
  6. 上記でタグ付けできなかったデータに対して、DefaultTaggerでタグ付け

17~22は、各自動タグ付け機を検証データで評価(正答率にて)しています。
23行目は、適当な文章にタグ付けしてみました。

さて、最終的な評価結果は、正答率85.4%!!
まぁまぁといった感じでしょうか?

DefaultTagger.evaluate = 0.1262832652247583
UnigramTagger.evaluate = 0.8361407355726104
BrillTaggerTrainer.evaluate = 0.8452108043456593
AffixTaggerTrainer.evaluate(suffix) = 0.8466061995415131
AffixTaggerTrainer.evaluate(prefix) = 0.8469052127977673
BigramTagger.evaluate = 0.8541812020332902
[(‘They’, ‘PPSS’), (‘wind’, ‘VB’), (‘back’, ‘RB’), (‘the’, ‘AT’), (‘clock’, ‘NN’), (‘,’, ‘,’), (‘while’, ‘CS’), (‘we’, ‘PPSS’), (‘chase’, ‘NN’), (‘after’, ‘CS’), (‘the’, ‘AT’), (‘wind’, ‘NN’), (‘.’, ‘.’)]

各自動タグ付け機、どんな風にタグ付けしているのか調べてみると面白いですよ!!
※決して説明が面倒なわけではありません。

それでは、大晦日の前にもう一度お会いしましょう!!