Se diminuirmos o falso negativo (selecione mais pontos positivos), a rechamada sempre aumenta, mas a precisão pode aumentar ou diminuir. Geralmente, para modelos melhores que aleatórios, precisão e recall têm uma relação inversa ( resposta do @thinkinker ), mas para modelos piores que aleatórios, eles têm uma relação direta ( exemplo de @kbrose ).
Vale a pena notar que podemos artificialmente construir uma amostra que faz com que um modelo que seja melhor que aleatório na distribuição verdadeira tenha um desempenho pior que aleatório, por isso estamos assumindo que a amostra se assemelha à distribuição verdadeira.
Recordar
Temos
, portanto, o recall seria
que sempre aumenta com a diminuição do .TP= P- FN
r =P- FNP= 1 -FNP
FN
Precisão
Por precisão, a relação não é tão direta. Vamos começar com dois exemplos.
Primeiro caso : diminuição da precisão, diminuição do falso negativo:
label model prediction
1 0.8
0 0.2
0 0.2
1 0.2
Para o limite (falso negativo = ),0,5{ ( 1 , 0,2 ) }
p =1 11 + 0= 1
Para o limite (falso negativo = ),0,0{ }
p =22 + 2= 0,5
Segundo caso : aumento da precisão, diminuição do falso negativo (o mesmo que no exemplo @kbrose ):
label model prediction
0 1.0
1 0.4
0 0.1
Para o limite (falso negativo = ),0,5{ ( 1 , 0,4 ) }
p=00+1=0
Para o limite (falso negativo = ),0.0{}
p=11+2=0.33
Vale ressaltar que a curva ROC para este caso é
Análise de precisão com base na curva ROC
Quando abaixamos o limiar, a falsa negativa diminui e a verdadeira [taxa] positiva aumenta, o que equivale a mover para a direita no gráfico ROC . Fiz uma simulação para modelos melhores que aleatórios, aleatórios e piores que aleatórios, e plotei ROC, recall e precisão:
Como você pode ver, movendo para a direita, no modelo melhor que o aleatório, a precisão diminui; no modelo aleatório, a precisão apresenta flutuações substanciais e, no modelo pior que o aleatório, a precisão aumenta. E há pequenas flutuações nos três casos. Portanto,
Pelo aumento da recordação, se o modelo é melhor que aleatório, a precisão geralmente diminui. Se o modo for pior que aleatório, a precisão geralmente aumenta.
Aqui está o código para simulação:
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()