1、一般的なモデル分類評価指標#
正確率 Accuracy#
正確率:予測が正しい結果の総サンプルに対する割合
code
from sklearn.metrics import accuracy_score
y_pred = [0, 2, 1, 3]
y_true = [0, 1, 2, 3]
accuracy_score(y_true, y_pred)
欠点
サンプルが不均衡な場合、正確率は無効になります。例えば、ショッピングサイトを閲覧しているユーザーが購入するかどうかを判断する場合、100 人の閲覧ユーザーのうち、購入するのは 1 人だけかもしれません。その場合、モデルが購入しないと無思考で予測すれば、正確率は 99% になります。
1️⃣ サンプルの不均衡を処理する:リサンプリング、アンダーサンプリング、オーバーサンプリングなど
2️⃣ 適切な指標に変更する:F1 スコア。これは、モデルの予測の誤りの数だけでなく、誤りの種類も考慮します。
混同行列#
対角線を見ます。
code
import matplotlib.pyplot as plt
import scikitplot as skplt
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_digits
X, y = load_digits(return_X_y=True)
clf = RandomForestClassifier(n_estimators=5, max_depth=5, random_state=1)
clf.fit(X, y)
clf.score(X, y)
pred = clf.predict(X)
skplt.metrics.plot_confusion_matrix(y, pred, normalize=True)
plt.show()
二項分類の対角線派生指標#
-
真陽性 (True Positive, TP):モデルが正と予測した正のサンプル;
-
偽陽性 (False Positive, FP):モデルが正と予測した負のサンプル;
-
偽陰性 (False Negative, FN):モデルが負と予測した正のサンプル;
-
真陰性 (True Negative, TN):モデルが負と予測した負のサンプル;
-
精度 Precision= TP/(TP+FP)
-
再現率 Recall=TP/(TP+FN)
-
F1 スコア=2*(P * R)/(P+R)
精度 Precision#
モデルが 1 と予測した場合、実際に 1 である割合
ケース:
-
株式を予測する際、私たちは精度を重視します。つまり、私たちが上昇すると予測した株の中で、実際に上昇したものがどれだけあるかです。なぜなら、私たちが上昇すると予測した株は、私たちが投資するものだからです。
-
例えば、犯罪者の予測において、私たちは予測結果が非常に正確であることを望みます。つまり、本物の犯罪者を見逃しても、善人を誤って疑ってはいけません。
code
from sklearn.metrics import precision_score
from sklearn.metrics import accuracy_score
y_true = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
# None 各クラスの精度(平均なし)
precision_score(y_true, y_pred, average=None)
# [0.375 1. ]
# 'macro' 各クラスの精度の平均(加重なし)
precision_score(y_true, y_pred, average='macro')
# (0.375 + 1.)/2 = 0.6875
# 'weighted' 各クラスのサンプル数に基づく加重平均精度
precision_score(y_true, y_pred, average='weighted')
# 0.375*0.3+1*0.7 = 0.8125
# 'micro' 全サンプルの全体精度
precision_score(y_true, y_pred, average='micro')
# Accuracyと等しい 0.5
accuracy_score(y_true, y_pred)
# 0.5
再現率 Recall#
実際に 1 であるサンプルが、再度モデルによって召回される確率、または完全性とも呼ばれます。
ケース:
-
もし地震が合計で 10 回発生した場合、私たちは 1000 回警報を発することを望みます。そうすれば、この 10 回の地震をすべてカバーできます(この時、再現率は 100%、精度は 1% です)。100 回の警報を発することは避けたいです。その中で 8 回の地震が予測されましたが、2 回を見逃しました(この時、再現率は 80%、精度は 8% です)。
-
患者の予測のシナリオでは、私たちは再現率により注目します。つまり、実際に病気の人の中で、私たちが予測を間違えたケースはできるだけ少ない方が良いです。なぜなら、実際に病気があるのに検出されないと、結果は非常に深刻だからです。以前の無思考なアルゴリズムでは、再現率は 0 でした。
code
from sklearn.metrics import recall_score
from sklearn.metrics import accuracy_score
y_true = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
recall_score(y_true, y_pred, average=None)
# 3つの0が召回され、7つの1のうち2つだけが召回されました [1. 0.28571429]
recall_score(y_true, y_pred, average='macro')
# (1. + 0.28571429)/2 = 0.6428571428571428
recall_score(y_true, y_pred, average='weighted')
# 1*0.3+0.28571429*0.7 = 0.5
recall_score(y_true, y_pred, average='micro')
# Accuracyと等しい =0.5
accuracy_score(y_true, y_pred)
# 0.5
なぜ精度と再現率は矛盾するのか#
1️⃣ より高い再現率を望む場合、モデルの予測がより多くのサンプルをカバーする必要がありますが、そうするとモデルは間違いを犯す可能性が高くなり、つまり精度が低くなります。
2️⃣ モデルが非常に保守的で、確信のあるサンプルしか検出できない場合、精度は非常に高くなりますが、再現率は相対的に低くなります。
F1 スコア#
調和平均#
- 調和平均とは何ですか?
🔴 これは変数の逆数に基づいて計算されるため、逆数平均とも呼ばれます。
-
2 キロメートルの距離を移動し、最初の 1 キロメートルは 20km/h、次の 1 キロメートルは 10km/h の速度で移動した場合、平均速度は?
単純平均:
(20+10)/2 = 15時間加重:
総時間 = (1/20 + 1/10)= 0.15
最初の 1 キロメートルの時間:1/20=0.05 重み 33%
次の 1 キロメートルの時間:1/10=0.1 重み 66%
平均時間 = 20 * 33% + 10 * 66% = 13.33
調和平均
なぜ F1 は調和平均を使用するのか?#
- 単純平均を使用すると、P=0.8,R=0.8 と P=0.7,R=0.9 の算術平均はどちらも 0.8 になり、精度と再現率が互換性があることになります。
- 調和平均は、より高い値に対してより低い重みを与えるという罰則メカニズムを追加します(例えば、上記の例では、20 の速度の重みは 33% しかありません)。
そのため、算術平均を使用する際に、一方が非常に高く、もう一方が低い場合に、平均が虚高になる現象を避けることができます。(仮に p と r の一方が 1.0 で、もう一方が 0.1 の場合、算術平均は約 0.5 に近づき、調和平均は約 0.2 に近づきます)。
F1 値の背後にある考え方は、精度と再現率の両方が平凡なアルゴリズムは、一方の指標が非常に良く、もう一方の指標が非常に悪いアルゴリズムよりも信頼性が高いということです。
まとめ:二つとも良いことが本当に良いことです。
code
from sklearn.metrics import f1_score
from sklearn.metrics import accuracy_score
y_true = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
f1_score(y_true, y_pred, average=None)
# [0.54545455 0.44444444]
f1_score(y_true, y_pred, average='macro')
# (0.54545455+0.44444444)/2 = 0.4949494949494949
f1_score(y_true, y_pred, average='weighted')
# 0.54545455*0.3+0.44444444*0.7 = 0.47474747474747475
f1_score(y_true, y_pred, average='micro')
# Accuracyと等しい 0.5
accuracy_score(y_true, y_pred)
# 0.5