言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。
第8章: 機械学習
本章では,Bo Pang氏とLillian Lee氏が公開しているMovie Review Dataのsentence polarity dataset v1.0を用い,文を肯定的(ポジティブ)もしくは否定的(ネガティブ)に分類するタスク(極性分析)に取り組む.
70. データの入手・整形
文に関する極性分析の正解データを用い,以下の要領で正解データ(sentiment.txt)を作成せよ.
- rt-polarity.posの各行の先頭に"+1 "という文字列を追加する(極性ラベル"+1"とスペースに続けて肯定的な文の内容が続く)
- rt-polarity.negの各行の先頭に"-1 "という文字列を追加する(極性ラベル"-1"とスペースに続けて否定的な文の内容が続く)
- 上述1と2の内容を結合(concatenate)し,行をランダムに並び替える
sentiment.txtを作成したら,正例(肯定的な文)の数と負例(否定的な文)の数を確認せよ.
出来上がったコード:
# coding: utf-8
import codecs
import random
fname_pos = 'rt-polaritydata/rt-polarity.pos'
fname_neg = 'rt-polaritydata/rt-polarity.neg'
fname_smt = 'sentiment.txt'
fencoding = 'cp1252' # Windows-1252らしい
result = []
# ポジティブデータの読み込み
with codecs.open(fname_pos, 'r', fencoding) as file_pos:
result.extend(['+1 {}'.format(line.strip()) for line in file_pos])
# ネガティブデータの読み込み
with codecs.open(fname_neg, 'r', fencoding) as file_neg:
result.extend(['-1 {}'.format(line.strip()) for line in file_neg])
# シャッフル
random.shuffle(result)
# 書き出し
with codecs.open(fname_smt, 'w', fencoding) as file_out:
print(*result, sep='\n', file=file_out)
# 数の確認
cnt_pos = 0
cnt_neg = 0
with codecs.open(fname_smt, 'r', fencoding) as file_out:
for line in file_out:
if line.startswith('+1'):
cnt_pos += 1
elif line.startswith('-1'):
cnt_neg += 1
print('pos:{}, neg:{}'.format(cnt_pos, cnt_neg))
実行結果:
pos:5331, neg:5331
機械学習の勉強のススメ
ここまでのノックは適当にググりながら耐えてきましたが、ここから先はボールじゃなく砲丸とかヤリとか飛んできます^^ そのため、先に機械学習を軽く勉強されることをお勧めします。
私は、ネットで評判の良い無料のオンライン講座を受けてみました。Courseraというオンライン講座のサービスの中でStanford Universityが提供している講義Machine Learningです。実際にやってみましたが、確かにお勧めです。有志の方が日本語字幕を付けてくれているので、英語が苦手でもなんとかなりました。特に私は外出中のスキマの時間で勉強することが多かったので、スマホアプリに付いてる講義動画のダウンロード機能(オフラインでパケット気にせず動画が繰り返し見れる)が、大変ありがたかったです。
この講座の受け方については、daxanya1さんがまとめられている数学を避けてきた社会人プログラマが機械学習の勉強を始める際の最短経路が分かりやすいです。また、受けた後の振り返りには、katsu1110さんがまとめられている数学の苦手なバイオの学生がCourseraの機械学習コースを修了して気づいたことの一連の過去記事がオススメです。
なお、言語処理100本ノックの第8章を進めるには、機械学習の1つの手法であるロジスティック回帰の理解が必要になります。Machine LearningであればWeek3までを終わらせておくとスムーズに進めるのではないかと思います。
###第8章でやろうとしていること
映画に対するいろんな人のレビューコメントに対して、それが映画を褒めている肯定的な内容なのか、それとも映画が気に入らなかった人の否定的な内容なのか、このどちらなのかをコンピューターに自動的に分類させよう!というのがこの第8章のゴールです。ネガティブなのかポジティブなのかを判定するので、ネガポジ判定とか呼んだりもします。
自動分類の機械学習
現在の技術で今回のような自動分類を機械にやらせるには、事前準備として、こういったレビューが肯定的で、こういったレビューが否定的だよ、と機械に繰り返し教え込まないといけません。事前に機械に学習させる必要があるので、機械学習というわけですね。
自動分類のための機械学習は、ペットのしつけに似ています。良いことをすれば褒め、悪いことをすれば叱ります。これを繰り返すと、何が良いことで何が悪いことかをペットは学んでくれます。
今回は機械にレビューを与えて、それが肯定的なのか否定的なのかを判定させます。そしてそれが正解なら褒め、不正解なら叱ります。これを繰り返すことで、レビューを分類できるように育てます。もちろん実際には機械を褒めたり叱ったりはできないので、代わりにプログラムの中で数値をごにょごにょ調整することになります。
###正解データとラベル
今回の学習で使う正解データは、個々のレビューとそれに対する正しい結果(肯定的/否定的のどちらなのか)のペアになります。このペアの後者(正しい結果)を「ラベル」と呼びます。
機械学習の手法によっては、学習で使うデータにラベルがない場合もあります。正しい結果を教えずに何を学習させるんだ?と思われるかも知れませんが、ヒトが正解を知らず、ラベルが付けられないような問題を解かせる時に使います。
教師あり学習/教師なし学習
ラベル付きデータで学習する手法を教師あり学習、ラベルなしデータで学習する手法を教師なし学習と呼びます。この第8章では、ラベル付きデータによる教師あり学習を進めます。
今回のデータの文字コード
今回の問題70は約1万件の正解データを整形してシャッフルするだけなので簡単なはずでしたが、1つだけつまずきました。それは「rt-polarity.pos」や「rt-polarity.neg」の文字コードがUTF-8ではないことです。
結果としてgeditではラテン文字の文字コード「WINDOWS-1252」を選ぶと読み込めたので、それで扱うことにしました。ラテン文字特有の「á」や「é」も正しく読み込めているので、おそらくこれで大丈夫かと思います。
Pythonではcodecs.open()
を使えばファイルの文字コード変換をお任せできるので、その形で実装しました。
71本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。
実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。