Edited at

素人の言語処理100本ノック:77

More than 1 year has passed since last update.

言語処理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を用い,文を肯定的(ポジティブ)もしくは否定的(ネガティブ)に分類するタスク(極性分析)に取り組む.



77. 正解率の計測


76の出力を受け取り,予測の正解率,正例に関する適合率,再現率,F1スコアを求めるプログラムを作成せよ.



出来上がったコード:


main.py

# coding: utf-8


fname_result = 'result.txt'

def score(fname):
'''結果ファイルからスコア算出
結果ファイルを読み込んで、正解率、適合率、再現率、F1スコアを返す

戻り値:
正解率,適合率,再現率,F1スコア
'''
# 結果を読み込んで集計
TP = 0 # True-Positive 予想が+1、正解も+1
FP = 0 # False-Positive 予想が+1、正解は-1
FN = 0 # False-Negative 予想が-1、正解は+1
TN = 0 # True-Negative 予想が-1、正解も-1

with open(fname) as data_file:
for line in data_file:
cols = line.split('\t')

if len(cols) < 3:
continue

if cols[0] == '+1': # 正解
if cols[1] == '+1': # 予想
TP += 1
else:
FN += 1
else:
if cols[1] == '+1':
FP += 1
else:
TN += 1

# 算出
accuracy = (TP + TN) / (TP + FP + FN + TN) # 正解率
precision = TP / (TP + FP) # 適合率
recall = TP / (TP + FN) # 再現率
f1 = (2 * recall * precision) / (recall + precision) # F1スコア

return accuracy, precision, recall, f1

# スコア算出
accuracy, precision, recall, f1 = score(fname_result)
print('正解率 \t{}\n適合率 \t{}\n再現率 \t{}\nF1スコア \t{}'.format(
accuracy, precision, recall, f1
))



実行結果:


実行結果

正解率     0.8660664040517726

適合率  0.8675833490299492
再現率  0.8640030013130745
F1スコア  0.8657894736842107


正解率

正解率は、すべてのレビューのうち、正しく予測できたものの割合です。


正例に関する適合率

正例(肯定的)に対する適合率とは、肯定的と予測したレビューの中で、実際に肯定的だったものの割合です。

例えば、キノコ狩りにいって食べられるキノコ(これを正例とします)を選ぶ場合、間違って毒キノコ(負例)を選んでしまったら大変です。でも、食べられるキノコを毒キノコだと思って見逃してしまっても、食べられるキノコの量が減ってしまうだけで、それほど実害はありません。

このように、正例を多少見逃しても構わないから、確実に正例のものだけを選びたい場合に重視する指標です。間違ったものを選ぶことに厳しく、正しいものを見逃してしまうことには寛容な場合の指標といえます。

極端な例ですが、肯定的かどうか怪しいものや良く分からないものは全部否定的という乱暴な予測ロジックにすると、適合率は上げることができます。


正例に関する再現率

正例(肯定的)に対する再現率は、実際に肯定的なレビューの中で、肯定的と予測できたものの割合です。

例えば商品の出荷前のチェックで不良品を検出する(これを正例とします)場合、不良品を見逃して出荷してしまうと大騒ぎになってしまいます。そうなるくらいなら、良品を不良品と誤判定して出荷対象から外してしまった方が実害がありません。その後の再検査で良品と分かれば出荷できます。

このように、多少は間違って負例を選んでしまってもいいから、とにかく正例を見逃すのを避けたいといった場合に重視する指標です。間違ったものも選んでしまうことには寛容ですが、正しいものを見逃すことには厳しい指標です。

肯定的かどうか怪しいものや良く分からないものを全部肯定的という予測にしてしまえば、再現率は上げることができます。


正例に関するF1スコア

F1スコア(Fスコア、F値、F-尺度などとも呼ばれます)は適合率と再現率のバランスを定量化したもので、次の式で求められます。

$$ F1スコア = 2 \times \frac{適合率 \times 再現率}{適合率 + 再現率} $$

F1スコアの計算には適合率と再現率の計算が必要です。その際、True Positive、False Positive、False Negative、True Negativeの4つの数字をカウントすると計算が楽になります。

実際が1(陽性)
実際が0(陰性)

予測が1(陽性)
True Positive(真陽性)
False Positive(偽陽性)

予測が0(陰性)
False Negative(偽陰性)
True Negative(真陰性)

今回のコードでも、この4つの数字をカウントしてから、各値を算出しています。

なお、適合率や再現率とF1スコアの関係は問題79で可視化してみます。


学習データでの検証結果

いずれも0.86前後の値でした。86%くらいの予測精度ということですね。肯定的と否定的のデータが半分半分なので、当てずっぽうでも50%は当たることを考えると、ちょっと低いような気がしないでもありませんが...

 

78本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。


実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。