Punto di partenza della curva PR e del valore AUCPR per un classificatore ideale

Aug 23 2020

Ho due domande sulla curva PR:

  1. Qual è il punto di partenza della curva PR?
    Intendo il punto che corrisponde alla soglia più alta possibile (cioè quando tutti i punteggi sono al di sotto di questa soglia). È chiaro che in questo caso tutte le etichette rigide sono uguali a zero. Quindi,$\text{TP}=\text{FP}=0$ e $\text{Recall}=0$, ma $\text{Precision}=\frac{0}{0}$. Sklearn utilizza$\text{Precision}=1$per questo punto. È una regola generale o altri valori di precisione potrebbero essere utilizzati per questo punto in diverse librerie (ad esempio, in R)?
  2. Qual è il valore AUCPR per un classificatore ideale ?
    Intendo l'area sotto la curva PR (AUCPR) per un classificatore binario ideale (cioè c'è un valore di soglia tale che tutti i campioni siano classificati correttamente dal modello). È chiaro che la curva PR di tale classificatore passa per il punto$(1,1)$. Inoltre, qualsiasi curva PR passa per il punto descritto sopra in "1." e punto$(1, \frac{n_+}{n})$ (questo è il punto della soglia più bassa possibile quando tutti i punteggi sono al di sopra di questa soglia), dove $n_+$ è il numero totale di campioni positivi e $n$è il numero totale di campioni. Ciò significa che AUCPR è uguale a 1 in questo caso (come AUCROC del classificatore ideale) o può essere inferiore a 1?

Risposte

1 usεr11852 Aug 23 2020 at 08:01

Convenzione di lavoro: Point $(0,1)$ è l'angolo superiore sinistro e corrisponde a $0$ Recall (cioè nessun richiamo) e $1$ Precisione (ovvero precisione perfetta).

Per quanto riguarda la prima domanda: il punto di partenza può essere in qualsiasi punto lungo $0$ o $\frac{1}{n_+}$Ricorda, dove l'inizio della curva PR dipende dalle prestazioni del classificatore. Mentre speriamo di iniziare dal punto$(\frac{1}{n_+},1)$e aumenteremo lentamente il nostro richiamo con poca spesa per la precisione (cioè siamo molto precisi per cominciare e lentamente sacrificheremo la precisione per il richiamo) che non è affatto garantito. L'esempio ovvio è quando classifichiamo erroneamente il nostro esempio "più probabile" del nostro set di test. In tal caso abbiamo entrambi$0$-th Recall e $0$-th Precision, cioè partiamo dal punto $(0,0)$. Ad esempio, nel grafico più a sinistra mostrato sotto (linea rossa), abbiamo un esempio artificiale in cui iniziamo dal punto$(0,0.5)$ perché il primo $\frac{N}{2}$i punti sono indistinguibili l'uno dall'altro. Classifichiamo "immediatamente" correttamente alcuni esempi (cioè otteniamo TP e quindi Recall diverso da zero) ma allo stesso tempo otteniamo un numero uguale di FP che ci portano a$0.5$ Precisione.

Si noti che nel caso in cui non vengano trovati esempi positivi (TP o FP), la precisione non ha senso. Non esiste una regola generale su ciò che facciamo lì. sklearnimposta questo per essere$1$che rigorosamente per sua comodità e dice esplicitamente che questi punti " non hanno una soglia corrispondente ". A questo proposito, in Davis & Goadrich (2006) la procedura per costruire una curva PR quando viene presentato un algoritmo che restituisce probabilità è: " prima trova la probabilità che ogni esempio di set di test sia positivo, poi ordina questo elenco e poi attraversa l'elenco ordinato in ordine crescente. "; in quanto tale è implicito / suggerito che per una probabilità che nessun esempio sia positivo, non ha senso costruire una curva PR. In R PRROC::pr.curvefa una cosa simile dove si trova l'origine$(0,0$) dal primo esempio positivo (esempio mostrato pr3sotto).

Nota a margine: in Python questo porta nella situazione leggermente imbarazzante di avere Recall 0with Precision 0e 1allo stesso tempo.

import numpy as np
from sklearn.metrics import precision_recall_curve 
print(__doc__)

my_ytest = np.concatenate([np.array(['1'] * 50), np.array(['2'] * 50)])
my_yscore = np.concatenate([ [0.95], np.random.uniform(0.0, 0.5, 49),
                            np.random.uniform(0.5, 0.9, 50) ])
prec, recall, _ = precision_recall_curve(my_ytest, my_yscore, pos_label="2")
prec[recall==0] 
# array([0., 1.])

Per quanto riguarda la seconda domanda: Sì, il classificatore ideale ha AUCPR uguale a 1. L'unico modo per avere un classificatore ideale (cioè prestazioni che $(1,1)$) ma AUCPR inferiore a $1$, è se in qualche modo ci siamo spostati verso $(1,1)$ pur non avendo già una precisione perfetta (es $y=1$). A volte le curve PR hanno la forma "a dente di sega" (ad esempio il grafico centrale mostrato sotto (verde scuro)), che suggerisce un significativo salto di prestazioni. Quel "dente" però non potrà mai raggiungere il punto$(1,1)$perché per definizione ci sono già alcuni punti classificati male. L '"effetto dente di sega" è dovuto al fatto che abbiamo un lotto di punti classificati correttamente, che ci aiuta a spostare sia la nostra Precisione che il Richiamo più in alto, seguiti da un lotto di punti classificati erroneamente che causano il forte profondo in Precisione. Per ottenere la pendenza verso l'alto abbiamo aumentato i nostri numeri TP mentre i nostri numeri FP e FN sono rimasti gli stessi, ma questo non significa che abbiamo rimosso i nostri punti precedentemente classificati erroneamente; non possiamo quindi mai raggiungere la perfetta precisione a$y=1$. Ad esempio, nel grafico più a destra mostrato sotto (blu) un singolo punto ci vieta di colpire$\text{AUCPR} = 1$; quel punto FP classificato in modo errato è effettivamente più alto di qualsiasi altro punto nella classe positiva e quindi costringe la nostra curva PR a iniziare da$(0,0)$.

OK e un po 'di codice R per vedere questo in prima persona:

library(PRROC)
N = 30000
set.seed(4321)

# The first N/2 points from each population are indistinguishable 
pr0 <- pr.curve(scores.class0=c(rep(0.5, N/2), runif(n = N/2, max=0.4)), 
                scores.class1=c(rep(0.5, N/2), runif(n = N/2, min=0.4, max = 0.49)), 
                curve = TRUE)

# The [0.5, 0.7] space allows us to have the performance increase
pr1 <- pr.curve(scores.class0=c(runif(N/3, min=0.9, max=1.0), 
                                runif(N/3, min=0.5, max=0.7), 
                                runif(N/3, max=0.25)),
                scores.class1=c(runif(N/2, min=0.7, max=0.9), 
                                runif(N/2, min=0.0, max=0.5)),
                curve=TRUE)

# The single point causes us to start from (0,0)
pr2 <- pr.curve(scores.class0=runif(n = N, min=0.999), 
                scores.class1=c(1, runif(N-1, max=0.999)), 
                curve = TRUE)


par(mfrow=c(1,3))
plot(pr0, legend=FALSE, col='red', panel.first= grid(), 
     cex.main = 1.5, main ="PR-curve starting at (0,0.5)")
plot(pr1, legend=FALSE, col='darkgreen', panel.first= grid(), 
     cex.main = 1.5, main ="PR-curve with a sawtooth!")
plot(pr2, legend=FALSE, col='blue', panel.first= grid(), 
     cex.main = 1.5, main ="PR-curve from a nearly ideal classifier")