親です。

子ども産まれたんで育児とかについて書きます。映画とか心理学とかITとかの趣味についても書きます。

【Python】自然言語処理 テキスト分類の学習

どもっす。テキスト分類の学習についてまとめる。参考にしたテキストは『入門書 自然言語処理』。

概要

テキスト分類が何なのかっつーと、単語の連なった「テキスト」がどんな文章なのかを分類する。たとえばニュース記事だとか、小説だとか。

どうテキストを分類するか?

では、どのようにテキストを分類するのか。ここではテキストの分類を実現させる機械学習のテクニックについて、そしてその技術では言語のどんな面に注目しているのかまとめる。

教師あり分類

教師あり学習とは、あらかじめ分類されたテキストを使って分類器を学習させ、その分類器で分類することだ。もっと詳しくいうと、テキストからそのテキストがどのタグになるのか判断できるような素性(特徴量)を抽出し、そこにクラスラベルを対応させることで分類器の学習を行う。
前回の品詞分類の時はタガーでタグ付けしたが、今回はクラスラベルを貼り付ける。ちなみに、クラスラベルはあらかじめ種類を決めておく。

分類の実例

とか言われてもよく分からんと思うので参考書に書いてあった実例交えて考える。
・性別の決定の場合
ヨーロッパ系の名前は、女性だとa,e,iで終わることが多く、男性ではk,o,r,s,tで終わることが多い。この違いを元に分類器を作成する。
いきなり『入門 自然言語処理』を引用するけど、

分類器を作るための最初のステップは、入力におけるどんな素性が関連しているかを決定することと、その素性をどのように符号化するかを決定することである。

これちょっと何言ってるのか分かんなかったんだけど、たぶん、男女っつー見分けたい物があり、どんな特徴(素性)が分類に影響するものとするか、そしてその特徴(素性)をどんな形でデータに持っておく(符号化)か、って話だと思う。
で、符号化は素性の名前をその値にマップする。〜を〜にマップする、ってのは前回の辞書の章で出た表現で、つまりは{素性名:素性値}の形で辞書型に格納することだ。

def gender_features(word):
    return {'last_letter': word[-1]}
gender_features('Shrek')
{'last_letter': 'k'}

素性抽出関数の様子。こんな感じ。
さて、これで名前から素性を抽出することはできそうだ。ならあとは学習用のサンプルデータを用意すればいい。(学習用なのでもちろんクラスラベルが付いているぞ)

from nltk.corpus import names
import random
names = ([(name, 'male') for name in names.words('male.text')] +
         [(name, 'female') for name in names.words('female.txt')])
random.shuffle(names)

male.txtの中身をバーっと読んでいって(名前, 'male')のタプルにしてざっとリストに並べている。ある名前とそのクラスラベルが一緒になった状態ができたわけだ。じゃあ次は? そりゃ素性抽出関数を使ってこの名前を処理するしかねえだろ。

featuresets = [(gender_features(n), g) for (n, g) in names]
train_set, test_set = featuresets[500:], featuresets[:500]
classifier = nltk.NaiveBayesClassifier.train(train_set)

(素性, クラスラベル)のリストを作り、半分を機械学習の訓練に渡している。

classifier.classify(gender_features('Neo'))
classifier.classify(gender_features('Trinity'))
'male'
'female'

こんなもん。機械学習の結果、正しく判定された。やったぜ!

素性抽出をめぐる問題

・キッチンシンクアプローチ
教師あり学習をとりあえずやってみて思うことは、まあこれどうやって素性を決めるかがキモっぽいよなってこと。何を素性とするかってつまり、対象とするテキストを分類する上で何を手掛かりにするかってことだ。それ次第で分類の精度が左右されるし、すげーセンスいりそう。
じゃあ皆さんどうやって素性を得ているのか。『入門 自然言語処理』では「キッチンシンクアプローチ」という方法が紹介されている。これは、直観的に素性を選んで試行錯誤して素性を決めるやり方らしい。はあ?なんだそれ。
過学習
また、テキストの特徴を多くとればその分精密な分類ができる、とはならない。素性を細かく取得すると、教師データの特徴を詳しく得過ぎてしまい、学習の成果を一般に適用できなくなる。それを過学習というらしい。(ただ、そんなの統計的なスケールを大きくすればいいんじゃないのって思ってしまう。教師データが一般のデータを代表しないわけがないし、教師データが大きくなれば、統計的威力によって偏りは均されるんじゃないの? なんで一般データを弾くレベルで基準が厳しくなるのか理解できない。)
・エラー分析
過学習を回避しつつ学習を洗練させていく手立てとして、エラー分析というのがある。これはまあキッチンシンクアプローチとも似ているんだが、一度教師あり学習を行った上で、分類エラーを起こしたものについてどんなエラーを起こしたのか分析して適切な素性を追加する、というものだ。
この手法はエラーの分析を繰り返していくのだが、その際に使うデータは毎度作り直したほうがいい。なぜなら検証するデータが偏っているとまずいから。また、最終判断は完全に新しいデータを使ってテストする必要がある。

活用方法

実装