我进行了一些搜索以了解准确率和召回率,我看到一些图表表示准确率和召回率之间的反比关系,我开始考虑它以澄清主题。我想知道反比关系总是成立吗?假设我有一个二元分类问题,并且有正负标记类。在训练之后,一些实际的正例被预测为真正例,其中一些为假负例,一些实际负例被预测为真负例,其中一些为假正例。为了计算精度和召回率,我使用以下公式:
准确率和召回率之间的反比关系
如果我们减少假阴性(选择更多的阳性),召回率总是会增加,但精度可能会增加或减少。通常,对于比随机更好的模型,精度和召回具有反比关系(@pythinker的答案),但对于比随机更差的模型,它们具有直接关系(@kbrose的示例)。
值得注意的是,我们可以人为地构建一个样本,使在真实分布上优于随机的模型表现得比随机差,因此我们假设样本类似于真实分布。
记起
我们有
精确
为了精确,这种关系并不那么简单。让我们从两个例子开始。
第一种情况:通过减少假阴性来降低精度:
label model prediction
1 0.8
0 0.2
0 0.2
1 0.2
对于阈值 (假阴性= ),
对于阈值 (假阴性= ),
第二种情况:通过减少假阴性来提高精度(与@kbrose示例相同):
label model prediction
0 1.0
1 0.4
0 0.1
对于阈值 (假阴性= ),
对于阈值 (假阴性= ),
值得注意的是,这种情况下的 ROC 曲线是
基于ROC曲线的精度分析
当我们降低阈值时,假阴性减少,真阳性[率]增加,相当于在ROC图中向右移动。我对优于随机、随机和劣于随机的模型进行了模拟,并绘制了 ROC、召回率和精度:
如您所见,通过向右移动,对于优于随机模型的模型,精度会降低,对于随机模型,精度有很大的波动,对于差于随机模型的模型精度会增加。并且在这三种情况下都有轻微的波动。所以,
通过增加召回率,如果模型优于随机模型,则精度通常会降低。如果模式比随机差,精度通常会增加。
下面是模拟代码:
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()
你是对的@Tolga,两者都可以同时增加。考虑以下数据:
Prediction | True Class
1.0 | 0
0.5 | 1
0.0 | 0
如果您将截止点设置为 0.75,那么您有
那么如果你将截止点降低到 0.25,你有
所以你可以看到,当我们减少假阴性的数量时,准确率和召回率都增加了。
感谢您清楚地说明问题。关键是,如果你想减少假阴性,你应该充分降低你的决策函数的阈值。正如您所提到的,如果假阴性减少,真阳性会增加,但假阳性也会增加。结果,召回率会增加,而准确率会降低。