2016/09/10 機械学習 名古屋 第6回勉強会
後藤 俊介 ( @antimon2 )
○ | ○ | ○ | × | × | ○ | × | × | × | × |
※↑選ぶ人はどれが安全か知らない。
正解 | ○ | ○ | ○ | × | × | ○ | × | × | × | × |
---|---|---|---|---|---|---|---|---|---|---|
選択 | ○ | ○ | ○ | ○ | ○ | × | × | × | × | × |
※ うち3個が安全なキノコ、2個が毒キノコだった
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
この人は、どれくらいがんばった?
(=どう評価すれば良い?)
正解 | ○ | ○ | ○ | × | × | ○ | × | × | × | × |
---|---|---|---|---|---|---|---|---|---|---|
選択 | ○ | ○ | ○ | ○ | ○ | × | × | × | × | × |
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 簡単ですね!
※ でも、選択(抽出)の『精度』って、本当にこれで良いですか?
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 正解率が 100% ならば、適合率は 100%。
※ 適合率のことを単に「精度」とも言う(英語では同じく Precision)。
※ TensorFlow の公式チュートリアルのサンプルでは、よく "Precision"(精度)という名称で、こっちじゃなくて実際には Accuracy になってたりするので注意!
Q: 適合率が 100% なのに、正解率が 100% でないのは、どんな場合?
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 正解率が 100% ならば、再現率は 100%。
※ 再現率は「感度 (Sensitivity)」とも言う。
※ 適合率 と 再現率 は トレードオフ の関係。
Q: 再現率が 100% なのに、正解率が 100% でないのは、どんな場合?
※ 調和平均:逆数の平均(相加平均)の逆数。
※ 正解率が 100% ならば、F-値は 100%。
※ このF-値 (F1-Score) は、recall に $\beta^2$ の重みを乗せた重み付き調和平均で定義される Fβ-Score の特殊なもの(β=1)。
この人は、どれくらいがんばった?
(=どう評価すれば良い?)
(=どの評価指標で評価すれば良い?)
※ 問題の答えは置いといて、先ほどの 表 についてちょっと改めて説明してみます。
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
コレのこと。
※ データの分類で「うまくできた」「できなかった」を数え上げたクロス集計表のこと。
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ あまり日本語で「真陽」とか「偽陰」とか言わない。以降も英語の "True Positive" とか "False Negative" とかを用いる。
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 選択(=Positive)が正しかった(=True)、ということ。
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 選択(=Positive)が間違っていた(=False)、ということ。
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 選択しなかったこと(=Negative)が間違っていた(=False)、ということ。
安全なキノコ | 毒キノコ | |
---|---|---|
選んだキノコ | 3 | 2 |
選ばなかったキノコ | 1 | 4 |
※ 選択しなかったこと(=Negative)が正しかった(=True)、ということ。
+ | - | |
---|---|---|
(+) | TP | FP |
(-) | FN | TN |
※ TP
, FP
, FN
, TN
はそれぞれ、"True Positive", "False Positive", "False Negative", "True Negative" の頭文字。
+ | - | |
---|---|---|
(+) | TP | FP |
(-) | FN | TN |
+ | - | |
---|---|---|
(+) | TP | FP |
(-) | FN | TN |
+ | - | |
---|---|---|
(+) | TP | FP |
(-) | FN | TN |
+ | - | |
---|---|---|
(+) | TP | FP |
(-) | FN | TN |
※ 実際には元の定義のように precison と recall から計算することが多い。
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
※ NumPy を利用して、混同行列から TP/FP/FN/TN, Accuracy, Precision, Recall, F1Score をそれぞれ計算する実装例を示す。
cm = np.array([
[3, 2],
[1, 4]
]).astype(np.int64)
def get_tfpn(cm):
# assert cm.shape == (2, 2)
return tuple(cm.reshape([4]))
TP, FP, FN, TN = get_tfpn(cm)
(TP, FP, FN, TN)
(3, 2, 1, 4)
def calc_accuracy(cm):
# assert cm.shape == (2, 2)
TP, FP, FN, TN = get_tfpn(cm)
return (TP + TN) / (TP + FP + FN + TN)
calc_accuracy(cm)
0.69999999999999996
def calc_precision(cm):
# assert cm.shape == (2, 2)
TP, FP, _, _ = get_tfpn(cm)
return TP / (TP + FP)
calc_precision(cm)
0.59999999999999998
def calc_recall(cm):
# assert cm.shape == (2, 2)
TP, _, FN, _ = get_tfpn(cm)
return TP / (TP + FN)
calc_recall(cm)
0.75
def calc_f1score(cm):
# assert cm.shape == (2, 2)
TP, FP, FN, _ = get_tfpn(cm)
return 2 * TP / (2 * TP + FP + FN)
calc_f1score(cm)
0.66666666666666663
金メダル | 銀メダル | 銅メダル | |
---|---|---|---|
たぶん金メダル | 7 | 0 | 3 |
たぶん銀メダル | 1 | 8 | 1 |
たぶん銅メダル | 0 | 1 | 9 |
金メダル | 銀メダル | 銅メダル | |
---|---|---|---|
たぶん金メダル | 7 | 0 | 3 |
たぶん銀メダル | 1 | 8 | 1 |
たぶん銅メダル | 0 | 1 | 9 |
金メダル | 金メダルじゃない | |
---|---|---|
たぶん金メダル | 7 | 3 |
たぶん金メダルじゃない | 1 | 19 |
TP | FP | FN | TN | |
---|---|---|---|---|
金メダル | 7 | 3 | 1 | 19 |
銀メダル | 8 | 2 | 1 | 19 |
銅メダル | 9 | 1 | 4 | 16 |
※ 各クラス(この場合「金メダル」「銀メダル」「銅メダル」それぞれ)の視点で TP/FP/FN/TN を計算する!
これを後で利用する!
金メダル | 銀メダル | 銅メダル | |
---|---|---|---|
たぶん金メダル | 7 | 0 | 3 |
たぶん銀メダル | 1 | 8 | 1 |
たぶん銅メダル | 0 | 1 | 9 |
TP | FP | FN | TN | |
---|---|---|---|---|
金メダル | 7 | 3 | 1 | 19 |
銀メダル | 8 | 2 | 1 | 19 |
銅メダル | 9 | 1 | 4 | 16 |
TP | FP | FN | TN | |
---|---|---|---|---|
金メダル | 7 | 3 | 1 | 19 |
銀メダル | 8 | 2 | 1 | 19 |
銅メダル | 9 | 1 | 4 | 16 |
TP | FP | FN | TN | |
---|---|---|---|---|
金メダル | 7 | 3 | 1 | 19 |
銀メダル | 8 | 2 | 1 | 19 |
銅メダル | 9 | 1 | 4 | 16 |
※ 他にも指標はあるけれど、取り敢えずこのあたりを押さえておけば。
※ NumPy を利用して、混同行列から TP/FP/FN/TN, Accuracy, その他 をそれぞれ計算する実装例を示す。
cm = np.array([
[7, 0, 3],
[1, 8, 1],
[0, 1, 9]
])
def get_tfpn(cm):
tp = np.diag(cm)
fp = np.sum(cm, axis=1) - tp
fn = np.sum(cm, axis=0) - tp
tn = np.sum(cm) - tp - fp - fn
return (tp, fp, fn, tn)
TP, FP, FN, TN = get_tfpn(cm)
(TP, FP, FN, TN)
(array([7, 8, 9]), array([3, 2, 1]), array([1, 1, 4]), array([19, 19, 16]))
def calc_accuracy(cm):
# TP, FP, FN, TN = get_tfpn(cm)
TP = np.diag(cm)
return np.sum(TP) / np.sum(cm)
calc_accuracy(cm)
0.80000000000000004
def calc_avg_accuracy(cm):
TP, _, _, TN = get_tfpn(cm)
return np.mean((TP + TN) / np.sum(cm))
calc_avg_accuracy(cm)
0.8666666666666667
def calc_precision_M(cm):
TP, FP, _, _ = get_tfpn(cm)
return np.mean(TP / (TP + FP))
calc_precision_M(cm)
0.79999999999999993
def calc_recall_M(cm):
TP, _, FN, _ = get_tfpn(cm)
return np.mean(TP / (TP + FN))
calc_recall_M(cm)
0.81873219373219364
def calc_f1score_M(cm):
p = calc_precision_M(cm)
r = calc_recall_M(cm)
return 2 * p * r / (p + r)
calc_f1score_M(cm)
0.80925771109253308