言語処理100本ノック 2015の70本目の記録です。
基本的に「素人の言語処理100本ノック」とほぼ同じ内容にしていたので、ブロクに投稿していなかったのですが、「第8章: 機械学習」については、真剣に時間をかけて取り組んでいてある程度変えているので投稿します。StanfordNLPをメインに使用していきます。
参考リンク
リンク | 備考 |
---|---|
070.データの入手・整形.ipynb | 回答プログラムのGitHubリンク |
素人の言語処理100本ノック:70 | 言語処理100本ノックで常にお世話になっています |
PythonによるStanfordNLP入門 | Stanford Core NLPとの違いがわかりやすかったです |
環境
種類 | バージョン | 内容 |
---|---|---|
OS | Ubuntu18.04.01 LTS | 仮想で動かしています |
pyenv | 1.2.15 | 複数Python環境を使うことがあるのでpyenv使っています |
Python | 3.6.9 | pyenv上でpython3.6.9を使っています 3.7や3.8系を使っていないことに深い理由はありません パッケージはvenvを使って管理しています |
問題
第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を作成したら,正例(肯定的な文)の数と負例(否定的な文)の数を確認せよ.
読み込むファイルの注意点
- 文字コードがUTF-8ではなくWINDOWS-1252らしい(しっかりと確認していませんが「素人の言語処理100本ノック:70」と同じふぁいる読み込みをしています)
- 英語だけでなくウムラウトを含むテキストがある(「Ü」みたいな文字)
- 基本的に全文字が小文字化されています
回答
回答前提
Jupyter Notebookのディレクトリの下にこんなフォルダ構成にしています。元データを解凍して置いています。
└── rt-polaritydata
├── rt-polarity.neg
└── rt-polarity.pos
回答プログラム 070.データの入手・整形.ipynb
import codecs
import random
FNAME_SMT = 'sentiment.txt'
pos_prefix = '+1'
neg_prefix = '-1'
result = []
def read_file(fname, prefix):
# codecsを使わずにopen関数で読み込めるか未確認()
with codecs.open(fname, encoding='cp1252') as file: # Encodingは Windows-1252
return ['{0} {1}'.format(prefix, line.strip()) for line in file]
# ポジティブ読込
result.extend(read_file('./rt-polaritydata/rt-polarity.pos', pos_prefix))
# ネガティブ読込
result.extend(read_file('./rt-polaritydata/rt-polarity.neg', neg_prefix))
random.shuffle(result)
with open(FNAME_SMT, 'w') as file_out:
file_out.write('\n'.join(result))
# 数の確認
cnt_pos = 0
cnt_neg = 0
with open(FNAME_SMT) as file:
for line in file:
if line.startswith(pos_prefix):
cnt_pos += 1
elif line.startswith(neg_prefix):
cnt_neg += 1
print('pos:{}, neg:{}'.format(cnt_pos, cnt_neg))
回答解説
基本的にファイル読込と書込なのであまり特筆することをしていないです。
ファイルオープンのためにcodecs
ライブラリを使っていますが、これは素人の言語処理100本ノック:70の該当箇所をコピペしただけなので、通常のopen
関数でも可能かは検証していません。
ただ、後続のプログラムでまたcodecs
ライブラリを使いたくなかったので保存はUTF-8にしています。それでもウムラウトを含んだ文字も正しく保存できています。
実行すると最後のprint
関数によって以下のように件数が出ます。
pos:5331, neg:5331