L'esempio quando si utilizza l'accuratezza come misura di risultato porterà a una conclusione errata


8

Sto esaminando varie misure di prestazione per i modelli predittivi. Molto è stato scritto sui problemi di utilizzo dell'accuratezza, invece di qualcosa di più continuo per valutare le prestazioni del modello. Frank Harrell http://www.fharrell.com/post/class-damage/ fornisce un esempio quando l'aggiunta di una variabile informativa a un modello porterà a una riduzione della precisione, una conclusione chiaramente controintuitiva e errata.

inserisci qui la descrizione dell'immagine

Tuttavia, in questo caso, ciò sembra essere causato dall'avere classi sbilanciate, e quindi può essere risolto solo usando invece un'accuratezza bilanciata ((sens + spec) / 2). C'è qualche esempio in cui l'uso dell'accuratezza su un set di dati bilanciato porterà a conclusioni chiaramente errate o controintuitive?

modificare

Sto cercando qualcosa in cui la precisione diminuirà anche quando il modello è chiaramente migliore o che l'uso della precisione porterà a una selezione falsa positiva di alcune funzionalità. È facile fare esempi falsi negativi, dove l'accuratezza è la stessa per due modelli in cui uno è chiaramente migliore usando altri criteri.



2
Il post di Stephan collegato sopra è una risorsa meravigliosa e ha tutto il necessario. Il tuo primo passo nel presupporre che sia necessaria una classificazione forzata (decisione prematura) ha portato a un problema. E (sens + spec) / 2 non è un punteggio di precisione adeguato; ottimizzarlo porterà a scegliere le caratteristiche sbagliate e dare loro i pesi sbagliati, per non parlare dell'ignorare informazioni utili che provengono da probabilità, come zone "nessuna decisione".
Frank Harrell,

Comprendo il valore delle previsioni probabilistiche, ma sto cercando esempi in cui queste cose brutte che hai citato in realtà accadono per dati bilanciati o precisione bilanciata.
rep_ho,

A proposito: secondo Gneiting & Raftery la precisione del 2007 è corretta (anche se non strettamente corretta). qualche commento al riguardo? amstat.tandfonline.com/doi/abs/10.1198/…
rep_ho

Spero che la mia risposta sia utile. (@FrankHarrell: qualsiasi commento sarebbe il benvenuto.) Anche la precisione bilanciata non sarà utile qui. Considerare l'accuratezza come una regola di punteggio corretta ma non strettamente corretta: potresti essere interessato a L' accuratezza è una regola di punteggio impropria in un'impostazione di classificazione binaria? Se quel thread non risponde alla tua domanda, considera di porre una nuova domanda (e di sottolineare perché il thread esistente non è una risposta, quindi non è chiuso in duplice copia).
Stephan Kolassa,

Risposte:


14

Io imbrogliamo.

In particolare, ho spesso sostenuto (ad esempio, qui ) che la parte statistica della modellistica e della previsione si estende solo alla previsione probabilistica per le appartenenze alle classi (o alla definizione di densità predittive, nel caso della previsione numerica). Trattare un'istanza specifica come se appartenesse a una classe specifica (o pronostici puntuali nel caso numerico), non è più correttamente una statistica. Fa parte dell'aspetto teorico della decisione .

E le decisioni non dovrebbero basarsi solo sulla previsione probabilistica, ma anche sui costi di classificazione errata e su una miriade di altre possibili azioni . Ad esempio, anche se hai solo due classi possibili, "malato" vs "sano", potresti avere una vasta gamma di possibili azioni a seconda della probabilità che un paziente soffra della malattia, di rimandarlo a casa perché lui è quasi sicuramente salutare, dargli due aspirine, eseguire ulteriori test, chiamare immediatamente un'ambulanza e metterlo in pronto soccorso.

La valutazione dell'accuratezza presuppone tale decisione. La precisione come metrica di valutazione per la classificazione è un errore di categoria .

Quindi, per rispondere alla tua domanda, seguirò il percorso di un simile errore di categoria. Prenderemo in considerazione uno scenario semplice con classi equilibrate in cui la classificazione senza tener conto dei costi di errata classificazione ci farà indurre in errore.


Supponiamo che un'epidemia di Maligno Gutrot si diffonda nella popolazione. Fortunatamente, possiamo selezionare facilmente tutti per qualche tratto ( ) e sappiamo che la probabilità di sviluppare MG dipende linearmente da , per alcuni parametri ( ). Il tratto è distribuita in modo uniforme nella popolazione.t0t1tp=γtγ0γ1t

Fortunatamente esiste un vaccino. Sfortunatamente, è costoso e gli effetti collaterali sono molto scomodi. (Lascerò che la tua immaginazione fornisca i dettagli.) Tuttavia, sono meglio che soffrire di MG.

Nell'interesse dell'astrazione, suppongo che ci siano davvero solo due possibili linee d'azione per ogni dato paziente, dato il loro valore di tratto : o vaccinare o non vaccinare.t

Quindi, la domanda è: come dovremmo decidere chi vaccinare e chi no, dato ? Saremo utilitari su questo e mireremo ad avere i costi previsti totali più bassi. È ovvio che ciò si riduce alla scelta di una soglia e alla vaccinazione di tutti con .tθtθ


Il modello e la decisione 1 sono guidati dalla precisione. Montare un modello. Per fortuna, abbiamo già conosciamo il modello. Scegli la soglia che massimizza la precisione durante la classificazione dei pazienti e vaccina tutti con . Vediamo facilmente che è il numero magico - tutti con hanno maggiori probabilità di contrarre MG che no, e viceversa, quindi questa soglia di probabilità di classificazione massimizzerà precisione. Supponendo classi equilibrate, , vaccineremo metà della popolazione. Stranamente, se , non vaccineremo nessunoθtθθ=12γtθγ=1γ<12. (Siamo per lo più interessati a classi equilibrate, quindi ignoriamo il fatto che abbiamo lasciato morire una parte della popolazione per una morte terribile orribile.)

Inutile dire che ciò non tiene conto dei costi differenziali di errata classificazione.


Il modello e la decisione 2 sfruttano sia la nostra previsione probabilistica ("data la tua caratteristica , la tua probabilità di contrarre MG è ") sia la struttura dei costi.tγt

Innanzitutto, ecco un piccolo grafico. L'asse orizzontale dà al tratto, l'asse verticale la probabilità MG. Il triangolo ombreggiato indica la proporzione della popolazione che contrarrà MG. La linea verticale fornisce un particolare . La linea tratteggiata orizzontale in renderà i calcoli sottostanti un po 'più semplici da seguire. Supponiamo , solo per rendere la vita più facile.θγθγ>12

classificazione

Diamo i nomi dei nostri costi e calcoliamo i loro contributi ai costi totali previsti, dati e (e il fatto che il tratto sia uniformemente distribuito nella popolazione).θγ

  • Lascia che denoti il ​​costo per un paziente che è stato vaccinato e avrebbe contratto la MG. Dato , la proporzione della popolazione che sostiene questo costo è il trapezio ombreggiato in basso a destra con area c++θ
    (1θ)γθ+12(1θ)(γγθ).
  • Lascia che denoti il ​​costo per un paziente che è stato vaccinato e non avrebbe contratto MG. Dato , la proporzione della popolazione che sostiene questo costo è il trapezio non ombreggiato in alto a destra con area c+θ
    (1θ)(1γ)+12(1θ)(γγθ).
  • Lascia che denoti il ​​costo per un paziente che non è stato vaccinato e non avrebbe contratto la MG. Dato , la proporzione della popolazione che sostiene questo costo è il trapezio non ombreggiato in alto a sinistra con area cθ
    θ(1γθ)+12θγθ.
  • Lascia che denoti il ​​costo per un paziente che non è stato vaccinato e avrebbe contratto la MG. Dato , la proporzione della popolazione che sostiene questo costo è il triangolo ombreggiato in basso a sinistra con area c+θ
    12θγθ.

(In ogni trapezio, prima calcolo l'area del rettangolo, quindi aggiungo l'area del triangolo.)

I costi totali previsti sono

c++((1θ)γθ+12(1θ)(γγθ))+c+((1θ)(1γ)+12(1θ)(γγθ))+c(θ(1γθ)+12θγθ)+c+12θγθ.

Differenziando e impostando la derivata su zero, otteniamo che i costi previsti siano ridotti al minimo di

θ=c+cγ(c++c+c++c).

Questo è solo uguale all'accuratezza che massimizza il valore di per una struttura di costi molto specifica, vale a dire se e solo se o θ

12γ=c+cγ(c++c+c++c),
12=c+cc++c+c++c.

Ad esempio, supponiamo che per le classi bilanciate e che i costi siano Quindi l'accuratezza che massimizza produrrà costi previsti di , mentre il costo che minimizza produrrà costi previsti di .γ=1

c++=1,c+=2,c+=10,c=0.
θ=121.875θ=2111.318

In questo esempio, basare le nostre decisioni su classificazioni non probabilistiche che massimizzavano la precisione ha portato a più vaccinazioni e costi più elevati rispetto all'utilizzo di una regola decisionale che ha esplicitamente utilizzato le strutture di costo differenziali nel contesto di una previsione probabilistica.


In conclusione: l'accuratezza è solo un criterio decisionale valido se

  • esiste una relazione uno a uno tra le classi e le possibili azioni
  • e i costi delle azioni applicate alle classi seguono una struttura molto specifica.

Nel caso generale, valutare l'accuratezza pone una domanda sbagliata e massimizzare l'accuratezza è un cosiddetto errore di tipo III: fornire la risposta corretta alla domanda sbagliata.


Codice R:

rm(list=ls())
gamma <- 0.7

cost_treated_positive <- 1          # cost of treatment, side effects unimportant
cost_treated_negative <- 2          # cost of treatment, side effects unnecessary
cost_untreated_positive <- 10       # horrible, painful death
cost_untreated_negative <- 0        # nothing

expected_cost <- function ( theta ) {
    cost_treated_positive * ( (1-theta)*theta*gamma + (1-theta)*(gamma-gamma*theta)/2 ) +
    cost_treated_negative * ( (1-theta)*(1-gamma) + (1-theta)*(gamma-gamma*theta)/2 ) +
    cost_untreated_negative *( theta*(1-gamma*theta) + theta*gamma*theta/2 ) +
    cost_untreated_positive * theta*gamma*theta/2
}

(theta <- optim(par=0.5,fn=expected_cost,lower=0,upper=1,method="L-BFGS-B")$par)
(cost_treated_negative-cost_untreated_negative)/
    (gamma*(cost_treated_negative+cost_untreated_positive-cost_treated_positive-cost_untreated_negative))

plot(c(0,1),c(0,1),type="n",bty="n",xaxt="n",xlab="Trait t",yaxt="n",ylab="MG probability")
rect(0,0,1,1)
axis(1,c(0,theta,1),c(0,"theta",1),lty=0,line=-1)
axis(2,c(0,1),lty=0,line=-1,las=1)
axis(4,c(0,gamma,1),c(0,"gamma",1),lty=0,line=-1.8,las=1)
polygon(c(0,1,1),c(0,0,gamma),col="lightgray")
abline(v=theta,col="red",lwd=2)
abline(h=gamma*theta,lty=2,col="red",lwd=2)

expected_cost(1/(2*gamma))
expected_cost(theta)

1
Ottimo post! Ho appena effettuato l'accesso per ringraziare!
Wolfone,

"ma anche sui costi delle classificazioni errate" Non credo sia vero: proprio come mostra il calcolo stesso, anche (abbastanza sorprendentemente!) dipende anche dal costo delle classificazioni corrette !
Tamas Ferenci,

Non volevo modificare la tua eccellente risposta così profondamente, ma sarebbe forse istruttivo notare che la soglia ottimale dipende dai quattro costi, ma solo attraverso e : . cd+=c+c++cd=c+cθ=cdγ(cd+cd+)
Tamas Ferenci,

Potremmo anche fare una trama di questo:levelplot( thetastar ~ cdminus + cdplus, data = data.table( expand.grid( cdminus = seq( 0, 10, 0.01 ), cdplus = seq( 0, 10, 0.01 ) ) )[ , .( cdminus, cdplus, thetastar = cdminus/(cdminus + cdplus) ) ] )
Tamas Ferenci il

"la soglia ottimale dipende dal costo quattro, ma solo attraverso" Più specificamente, solo attraverso il loro rapporto, scusate: . θ=1/γ1+cd+cd
Tamas Ferenci,

4

Potrebbe valere la pena aggiungere un altro esempio, forse più semplice, all'eccellente risposta di Stephen.

Consideriamo un test medico, il cui risultato è normalmente distribuito, sia nelle persone malate che in quelle sane, con diversi parametri ovviamente (ma per semplicità, assumiamo l'omoscedasticità, cioè che la varianza sia la stessa):Indichiamo la prevalenza della malattia con (cioè ), quindi questo, insieme a quanto sopra, che sono essenzialmente distribuzioni condizionate, specifica completamente la distribuzione articolare.

TDN(μ,σ2)TDN(μ+,σ2).
pDBern(p)

Quindi la matrice di confusione con soglia (cioè quelli con risultati del test sopra sono classificati come malati) èbb

(DDTp(1Φ+(b))(1p)(1Φ(b))TpΦ+(b)(1p)Φ(b)).


Approccio basato sulla precisione

La precisione è

p(1Φ+(b))+(1p)Φ(b),

prendiamo la sua derivata wrt , impostiamola uguale a 0, moltiplichiamo con e riordiniamo un po ': Il primo termine non può essere zero, quindi l'unico modo in cui il prodotto può essere zero è se il secondo termine è zero:b1πσ2

pφ+(b)+φ(b)pφ(b)=0e(bμ)22σ2[(1p)pe2b(μμ+)+(μ+2μ2)2σ2]=0
(1p)pe2b(μμ+)+(μ+2μ2)2σ2=02b(μμ+)+(μ+2μ2)2σ2=log1pp2b(μ+μ)+(μ2μ+2)=2σ2log1pp
Quindi la soluzione è
b=(μ+2μ2)+2σ2log1pp2(μ+μ)=μ++μ2+σ2μ+μlog1pp.

Si noti che questo - ovviamente - non dipende dai costi.

Se le classi sono bilanciate, l'ottimale è la media dei valori medi dei test nelle persone malate e sane, altrimenti viene spostato in base allo squilibrio.


Approccio basato sui costi

Utilizzando la notazione di Stephen, il costo complessivo previsto èPrendi il suo derivato wrt e impostalo uguale a zero:

c++p(1Φ+(b))+c+(1p)(1Φ(b))+c+pΦ+(b)+c(1p)Φ(b).
b
c++pφ+(b)c+(1p)φ(b)+c+pφ+(b)+c(1p)φ(b)==φ+(b)p(c+c++)+φ(b)(1p)(cc+)==φ+(b)pcd+φ(b)(1p)cd=0,
usando la notazione che ho introdotto nei miei commenti sotto la risposta di Stephen, vale a dire, e .cd+=c+c++cd=c+c

La soglia ottimale è quindi data dalla soluzione dell'equazioneDue cose da notare qui:

φ+(b)φ(b)=(1p)cdpcd+.

  1. Questo risultato è totalmente generico e funziona per qualsiasi distribuzione dei risultati del test, non solo normale. ( in quel caso ovviamente significa la funzione di densità di probabilità della distribuzione, non la densità normale.)φ
  2. Qualunque sia la soluzione per , è sicuramente una funzione di . (Cioè, vediamo immediatamente quanto contano i costi, oltre allo squilibrio di classe!)b(1p)cdpcd+

Sarei davvero interessato a vedere se questa equazione ha una soluzione generica per (parametrizzata da s), ma sarei sorpreso.bφ

Tuttavia, possiamo risolverlo normalmente! s annulla sul lato sinistro, quindi abbiamo quindi la soluzione è2πσ2

e12((bμ+)2σ2(bμ)2σ2)=(1p)cdpcd+(bμ)2(bμ+)2=2σ2log(1p)cdpcd+2b(μ+μ)+(μ2μ+2)=2σ2log(1p)cdpcd+
b=(μ+2μ2)+2σ2log(1p)cdpcd+2(μ+μ)=μ++μ2+σ2μ+μlog(1p)cdpcd+.

(Confrontalo con il risultato precedente! Vediamo che sono uguali se e solo se , cioè le differenze nel costo di classificazione errata rispetto al costo di una corretta classificazione sono le stesse in malattia e salute persone.)cd=cd+


Una breve dimostrazione

Diciamo (è abbastanza naturale dal punto di vista medico) e che (possiamo sempre ottenerlo dividendo i costi con , ovvero misurando tutti i costi in unità). Diciamo che la prevalenza è . Supponiamo anche che , e .c=0c++=1c++c++p=0.2μ=9.5μ+=10.5σ=1

In questo caso:

library( data.table )
library( lattice )

cminusminus <- 0
cplusplus <- 1
p <- 0.2
muminus <- 9.5
muplus <- 10.5
sigma <- 1

res <- data.table( expand.grid( b = seq( 6, 17, 0.1 ),
                                cplusminus = c( 1, 5, 10, 50, 100 ),
                                cminusplus = c( 2, 5, 10, 50, 100 ) ) )
res$cost <- cplusplus*p*( 1-pnorm( res$b, muplus, sigma ) ) +
  res$cplusminus*(1-p)*(1-pnorm( res$b, muminus, sigma ) ) +
  res$cminusplus*p*pnorm( res$b, muplus, sigma ) +
  cminusminus*(1-p)*pnorm( res$b, muminus, sigma )

xyplot( cost ~ b | factor( cminusplus ), groups = cplusminus, ylim = c( -1, 22 ),
        data = res, type = "l", xlab = "Threshold",
        ylab = "Expected overall cost", as.table = TRUE,
        abline = list( v = (muplus+muminus)/2+
                         sigma^2/(muplus-muminus)*log((1-p)/p) ),
        strip = strip.custom( var.name = expression( {"c"^{"+"}}["-"] ),
                              strip.names = c( TRUE, TRUE ) ),
        auto.key = list( space = "right", points = FALSE, lines = TRUE,
                         title = expression( {"c"^{"-"}}["+"] ) ),
        panel = panel.superpose, panel.groups = function( x, y, col.line, ... ) {
          panel.xyplot( x, y, col.line = col.line, ... )
          panel.points( x[ which.min( y ) ], min( y ), pch = 19, col = col.line )
        } )

Il risultato è (i punti indicano il costo minimo e la linea verticale mostra la soglia ottimale con l'approccio basato sulla precisione):

Costo complessivo previsto

Possiamo benissimo vedere come l'ottimizzazione basata sui costi possa essere diversa dall'ottimizzazione basata sull'accuratezza. È istruttivo riflettere sul perché: se è più costoso classificare un malato erroneamente sano rispetto al contrario ( è alto, è basso) rispetto al la soglia scende, poiché preferiamo classificare più facilmente nella categoria malato, d'altra parte, se è più costoso classificare un popolo sano malato erroneamente rispetto al contrario ( è basso, è alto) rispetto alla soglia, poiché preferiamo classificare più facilmente nella categoria sana. (Controlla questi sulla figura!)c+c+c+c+


Un esempio di vita reale

Diamo un'occhiata a un esempio empirico, anziché a una derivazione teorica. Questo esempio sarà sostanzialmente diverso da due aspetti:

  • Invece di assumere la normalità, utilizzeremo semplicemente i dati empirici senza tale ipotesi.
  • Invece di utilizzare un singolo test e i suoi risultati nelle sue unità, useremo diversi test (e li combineremo con una regressione logistica). La soglia verrà data alla probabilità prevista finale. Questo è in realtà l'approccio preferito, vedi il capitolo 19 - Diagnosi - nel BBR di Frank Harrell .

Il set di dati ( acathdal pacchetto Hmisc) proviene dalla banca dati delle malattie cardiovascolari della Duke University e contiene se il paziente ha avuto una coronaropatia significativa, come valutato dal cateterismo cardiaco, questo sarà il nostro gold standard, cioè il vero stato della malattia e il "test "sarà la combinazione di età, sesso, livello di colesterolo del soggetto e durata dei sintomi:

library( rms )
library( lattice )
library( latticeExtra )
library( data.table )

getHdata( "acath" )
acath <- acath[ !is.na( acath$choleste ), ]
dd <- datadist( acath )
options( datadist = "dd" )

fit <- lrm( sigdz ~ rcs( age )*sex + rcs( choleste ) + cad.dur, data = acath )

Vale la pena tracciare i rischi previsti su scala logit, per vedere come sono normali (essenzialmente, questo era quello che abbiamo assunto in precedenza, con un singolo test!):

densityplot( ~predict( fit ), groups = acath$sigdz, plot.points = FALSE, ref = TRUE,
             auto.key = list( columns = 2 ) )

Distribuzione dei rischi previsti

Beh, sono quasi normali ...

Andiamo avanti e calcoliamo il costo complessivo previsto:

ExpectedOverallCost <- function( b, p, y, cplusminus, cminusplus,
                                 cplusplus = 1, cminusminus = 0 ) {
  sum( table( factor( p>b, levels = c( FALSE, TRUE ) ), y )*matrix(
    c( cminusminus, cplusminus, cminusplus, cplusplus ), nc = 2 ) )
}

table( predict( fit, type = "fitted" )>0.5, acath$sigdz )

ExpectedOverallCost( 0.5, predict( fit, type = "fitted" ), acath$sigdz, 2, 4 )

E tracciamolo per tutti i costi possibili (una nota computazionale: non abbiamo bisogno di iterare inconsapevolmente attraverso i numeri da 0 a 1, possiamo ricostruire perfettamente la curva calcolandola per tutti i valori unici delle probabilità previste):

ps <- sort( unique( c( 0, 1, predict( fit, type = "fitted" ) ) ) )

xyplot( sapply( ps, ExpectedOverallCost,
                p = predict( fit, type = "fitted" ), y = acath$sigdz,
                cplusminus = 2, cminusplus = 4 ) ~ ps, type = "l", xlab = "Threshold",
        ylab = "Expected overall cost", panel = function( x, y, ... ) {
          panel.xyplot( x, y, ... )
          panel.points( x[ which.min( y ) ], min( y ), pch = 19, cex = 1.1 )
          panel.text( x[ which.min( y ) ], min( y ), round( x[ which.min( y ) ], 3 ),
                      pos = 3 )
        } )

Costo complessivo previsto in funzione della soglia

Possiamo benissimo vedere dove dovremmo mettere la soglia per ottimizzare il costo complessivo previsto (senza usare sensibilità, specificità o valori predittivi ovunque!). Questo è l'approccio corretto.

È particolarmente istruttivo contrastare queste metriche:

ExpectedOverallCost2 <- function( b, p, y, cplusminus, cminusplus,
                                  cplusplus = 1, cminusminus = 0 ) {
  tab <- table( factor( p>b, levels = c( FALSE, TRUE ) ), y )
  sens <- tab[ 2, 2 ] / sum( tab[ , 2 ] )
  spec <- tab[ 1, 1 ] / sum( tab[ , 1 ] )
  c( `Expected overall cost` = sum( tab*matrix( c( cminusminus, cplusminus, cminusplus,
                                                   cplusplus ), nc = 2 ) ),
     Sensitivity = sens,
     Specificity = spec,
     PPV = tab[ 2, 2 ] / sum( tab[ 2, ] ),
     NPV = tab[ 1, 1 ] / sum( tab[ 1, ] ),
     Accuracy = 1 - ( tab[ 1, 1 ] + tab[ 2, 2 ] )/sum( tab ),
     Youden = 1 - ( sens + spec - 1 ),
     Topleft = ( 1-sens )^2 + ( 1-spec )^2
  )
}

ExpectedOverallCost2( 0.5, predict( fit, type = "fitted" ), acath$sigdz, 2, 4 )

res <- melt( data.table( ps, t( sapply( ps, ExpectedOverallCost2,
                                        p = predict( fit, type = "fitted" ),
                                        y = acath$sigdz,
                                        cplusminus = 2, cminusplus = 4 ) ) ),
             id.vars = "ps" )

p1 <- xyplot( value ~ ps, data = res, subset = variable=="Expected overall cost",
              type = "l", xlab = "Threshold", ylab = "Expected overall cost",
              panel=function( x, y, ... ) {
                panel.xyplot( x, y,  ... )
                panel.abline( v = x[ which.min( y ) ],
                              col = trellis.par.get()$plot.line$col )
                panel.points( x[ which.min( y ) ], min( y ), pch = 19 )
              }  )
p2 <- xyplot( value ~ ps, groups = variable,
              data = droplevels( res[ variable%in%c( "Expected overall cost",
                                                     "Sensitivity",
                                                     "Specificity", "PPV", "NPV" ) ] ),
              subset = variable%in%c( "Sensitivity", "Specificity", "PPV", "NPV" ),
              type = "l", xlab = "Threshold", ylab = "Sensitivity/Specificity/PPV/NPV",
              auto.key = list( columns = 3, points = FALSE, lines = TRUE ) )
doubleYScale( p1, p2, use.style = FALSE, add.ylab2 = TRUE )

Costo complessivo previsto e metriche tradizionali in funzione della soglia

Ora possiamo analizzare quelle metriche che a volte sono specificamente pubblicizzate come in grado di trovare un taglio ottimale senza costi e contrastarlo con il nostro approccio basato sui costi! Usiamo le tre metriche più utilizzate:

  • Precisione (massimizza la precisione)
  • Regola Youden (massimizza )Sens+Spec1
  • Regola di Topleft (minimizza )(1Sens)2+(1Spec)2

(Per semplicità, sottrarremo i valori precedenti da 1 per la regola Youden e Precisione in modo da avere un problema di minimizzazione ovunque.)

Vediamo i risultati:

p3 <- xyplot( value ~ ps, groups = variable,
              data = droplevels( res[ variable%in%c( "Expected overall cost", "Accuracy",
                                                     "Youden", "Topleft"  ) ] ),
              subset = variable%in%c( "Accuracy", "Youden", "Topleft"  ),
              type = "l", xlab = "Threshold", ylab = "Accuracy/Youden/Topleft",
              auto.key = list( columns = 3, points = FALSE, lines = TRUE ),
              panel = panel.superpose, panel.groups = function( x, y, col.line, ... ) {
                panel.xyplot( x, y, col.line = col.line, ... )
                panel.abline( v = x[ which.min( y ) ], col = col.line )
                panel.points( x[ which.min( y ) ], min( y ), pch = 19, col = col.line )
              } )
doubleYScale( p1, p3, use.style = FALSE, add.ylab2 = TRUE )

Scelte per selezionare il taglio ottimale

Questo ovviamente riguarda una specifica struttura dei costi, , , , (questo ovviamente conta solo per la decisione di costo ottimale). Per studiare l'effetto della struttura dei costi, scegliamo solo la soglia ottimale (invece di tracciare l'intera curva), ma la tracciamo in funzione dei costi. Più specificamente, come abbiamo già visto, la soglia ottimale dipende dai quattro costi solo attraverso il rapporto , quindi tracciamo il taglio ottimale in funzione di questo, insieme al tipico utilizzo metriche che non utilizzano i costi:c=0c++=1c+=2c+=4cd/cd+

res2 <- data.frame( rat = 10^( seq( log10( 0.02 ), log10( 50 ), length.out = 500 ) ) )
res2$OptThreshold <- sapply( res2$rat,
                             function( rat ) ps[ which.min(
                               sapply( ps, Vectorize( ExpectedOverallCost, "b" ),
                                       p = predict( fit, type = "fitted" ),
                                       y = acath$sigdz,
                                       cplusminus = rat,
                                       cminusplus = 1,
                                       cplusplus = 0 ) ) ] )

xyplot( OptThreshold ~ rat, data = res2, type = "l", ylim = c( -0.1, 1.1 ),
        xlab = expression( {"c"^{"-"}}["d"]/{"c"^{"+"}}["d"] ), ylab = "Optimal threshold",
        scales = list( x = list( log = 10, at = c( 0.02, 0.05, 0.1, 0.2, 0.5, 1,
                                                   2, 5, 10, 20, 50 ) ) ),
        panel = function( x, y, resin = res[ ,.( ps[ which.min( value ) ] ),
                                             .( variable ) ], ... ) {
          panel.xyplot( x, y, ... )
          panel.abline( h = resin[variable=="Youden"] )
          panel.text( log10( 0.02 ), resin[variable=="Youden"], "Y", pos = 3 )
          panel.abline( h = resin[variable=="Accuracy"] )
          panel.text( log10( 0.02 ), resin[variable=="Accuracy"], "A", pos = 3 )
          panel.abline( h = resin[variable=="Topleft"] )
          panel.text( log10( 0.02 ), resin[variable=="Topleft"], "TL", pos = 1 )
        } )

Soglie ottimali per costi diversi

Le linee orizzontali indicano gli approcci che non utilizzano i costi (e sono quindi costanti).

Ancora una volta, vediamo bene che quando il costo aggiuntivo di errata classificazione nel gruppo sano aumenta rispetto a quello del gruppo malato, la soglia ottimale aumenta: se davvero non vogliamo che le persone sane siano classificate come malate, useremo un cutoff più elevato (e viceversa, ovviamente!).

E, infine, vediamo ancora una volta perché questi metodi che non utilizzano i costi non sono ( e non possono! ) Essere sempre ottimali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.