偽陰性を減らす(より多くの陽性を選択する)場合、再現率は常に増加しますが、精度は増加または減少する可能性があります。一般に、ランダムより優れたモデルの場合、精度と再現率は逆の関係にありますが(@pythinkerの答え)、ランダムより悪いモデルの場合は直接的な関係にあります(@kbroseの例)。
真の分布でランダムよりも良いモデルをランダムよりも悪い性能で実行させるサンプルを人為的に構築できることは注目に値します。したがって、サンプルが真の分布に似ていると想定しています。
想起
我々は
従って、リコールのようになり
常に減少により増加。TP= P− FN
r =P− FNP= 1 −FNP
FN
精度
正確さのために、関係はそれほど単純ではありません。2つの例から始めましょう。
最初のケース:偽陰性の減少による精度の低下:
label model prediction
1 0.8
0 0.2
0 0.2
1 0.2
しきい値(偽陰性=)の場合、0.5{ (1 、0.2 )}
p =11 + 0= 1
しきい値(偽陰性=)の場合、0.0{ }
p =22 + 2= 0.5
2番目のケース:偽陰性の減少による精度の向上(@kbroseの例と同じ):
label model prediction
0 1.0
1 0.4
0 0.1
しきい値(偽陰性=)の場合、0.5{ (1 、0.4 )}
p =00 + 1= 0
しきい値(偽陰性=)の場合、0.0{ }
p =11 + 2= 0.33
この場合のROC曲線は、
ROCカーブに基づく精度の分析
しきい値を下げると、偽陰性が減少し、真陽性[率]が増加します。これは、ROCプロットを右に移動することと同じです。ランダムよりも良いモデル、ランダムなモデル、ランダムよりも悪いモデルのシミュレーションを行い、ROC、再現率、精度をプロットしました。
ご覧のとおり、右に移動すると、ランダムモデルよりも精度が低くなり、ランダムモデルでは精度が大幅に変動し、ランダムモデルよりも精度が高くなります。また、3つのケースすべてにわずかな変動があります。したがって、
再現率が増加することにより、モデルがランダムよりも優れている場合、精度は一般に低下します。モードがランダムよりも悪い場合、一般に精度が向上します。
シミュレーションのコードは次のとおりです。
import numpy as np
from sklearn.metrics import roc_curve
from matplotlib import pyplot
np.random.seed(123)
count = 2000
P = int(count * 0.5)
N = count - P
# first half zero, second half one
y_true = np.concatenate((np.zeros((N, 1)), np.ones((P, 1))))
title = 'Better-than-random model'
# title = 'Random model'
# title = 'Worse-than-random model'
if title == 'Better-than-random model':
# GOOD: model output increases from 0 to 1 with noise
y_score = np.array([p + np.random.randint(-1000, 1000)/3000
for p in np.arange(0, 1, 1.0 / count)]).reshape((-1, 1))
elif title == 'Random model':
# RANDOM: model output is purely random
y_score = np.array([np.random.randint(-1000, 1000)/3000
for p in np.arange(0, 1, 1.0 / count)]).reshape((-1, 1))
elif title == 'Worse-than-random model':
# SUB RANDOM: model output decreases from 0 to -1 (worse than random)
y_score = np.array([-p + np.random.randint(-1000, 1000)/1000
for p in np.arange(0, 1, 1.0 / count)]).reshape((-1, 1))
# calculate ROC (fpr, tpr) points
fpr, tpr, thresholds = roc_curve(y_true, y_score)
# calculate recall, precision, and accuracy for corresponding thresholds
# recall = TP / P
recall = np.array([np.sum(y_true[y_score > t])/P
for t in thresholds]).reshape((-1, 1))
# precision = TP / (TP + FP)
precision = np.array([np.sum(y_true[y_score > t])/np.count_nonzero(y_score > t)
for t in thresholds]).reshape((-1, 1))
# accuracy = (TP + TN) / (P + N)
accuracy = np.array([(np.sum(y_true[y_score > t]) + np.sum(1 - y_true[y_score < t]))
/len(y_score)
for t in thresholds]).reshape((-1, 1))
# Sort performance measures from min tpr to max tpr
index = np.argsort(tpr)
tpr_sorted = tpr[index]
recall_sorted = recall[index]
precision_sorted = precision[index]
accuracy_sorted = accuracy[index]
# visualize
fig, ax = pyplot.subplots(3, 1)
fig.suptitle(title, fontsize=12)
line = np.arange(0, len(thresholds))/len(thresholds)
ax[0].plot(fpr, tpr, label='ROC', color='purple')
ax[0].plot(line, line, '--', label='random', color='black')
ax[0].set_xlabel('fpr')
ax[0].legend(loc='center left', bbox_to_anchor=(1, 0.5))
ax[1].plot(line, recall, label='recall', color='blue')
ax[1].plot(line, precision, label='precision', color='red')
ax[1].plot(line, accuracy, label='accuracy', color='black')
ax[1].set_xlabel('1 - threshold')
ax[1].legend(loc='center left', bbox_to_anchor=(1, 0.5))
ax[2].plot(tpr_sorted, recall_sorted, label='recall', color='blue')
ax[2].plot(tpr_sorted, precision_sorted, label='precision', color='red')
ax[2].plot(tpr_sorted, accuracy_sorted, label='accuracy', color='black')
ax[2].set_xlabel('tpr (1 - fnr)')
ax[2].legend(loc='center left', bbox_to_anchor=(1, 0.5))
fig.tight_layout()
fig.subplots_adjust(top=0.88)
pyplot.show()