Auc

Matrices de confusión, sensibilidad, especificidad, curva ROC, AUC y todas esas cosas

Esta entrada es una breve introducción a los conceptos indicados en el título. Está motivada por una pregunta que se formuló en Twitter acerca de la existencia o no de lo que voy a escribir en español y a que ninguna de las respuestas aportadas me satisfizo.

Todos esos conceptos hacen referencia al estudio de la bondad de un modelo de clasificación (es decir, un modelo que trata de predecir una etiqueta (o una variable categórica, si se quiere) a partir de ciertos datos). Comenzaré por una descripción exenta de esos conceptos y terminaré con una discusión desde la perspectiva de su aplicación práctica que, espero, sirva para ponerlos en su lugar.

Cotas superiores para el AUC

El AUC tiene una cota superior de 1. Concedido. Pero alguien se quejó de que el AUC = 0.71 que aparece aquí era bajo.

Se ve que ignora esto. Donde está todo tan bien contado que no merece la pena tratar de reproducirlo o resumirlo aquí.

AUC = Wilcoxon

Construyo unos datos,

n <- 30
si <- data.frame(res = "si",
    score = rnorm(n, 1, 1))
no <- data.frame(res = "no",
    score = rnorm(n, 0, 1))
dat <- rbind(si, no)

que simulan los scorings de un modelo hipótetico en el que comparo unos casos positivos y otros negativos.

Comparo con el test de Wilcoxon el scoring según la etiqueta y normalizo (adecuadamente):

test <- wilcox.test(score ~ res, data = dat)$statistic
test / n^2

Por otro lado calculo el AUC:

library(pROC)
my_roc <- roc(dat$res, dat$score)
auc(my_roc)

¡Lo mismo!

Motivo: ambas expresiones dan la probabilidad de que el scoring de un sí elegido al azar sea superior al de un no elegido también al azar. Cosa que está superdocumentada en el ancho mundo.

El AUC es la probabilidad de que...

Voy a constuir unos datos artificiales y un modelo de clasificación binaria,

library(mgcv)
library(ggplot2)
library(pROC)

n <- 10000
dat <- gamSim(1, n=n, dist="binary", scale=.33)

lr.fit <- gam(y ~ s(x0, bs="cr") +
    s(x1, bs="cr") + s(x2, bs="cr") +
    s(x3, bs="cr"),
    family=binomial, data=dat,
    method="REML")

y luego (mal hecho: debería hacerlo sobre un conjunto de validación distinto) a obtener las predicciones para las observaciones

res <- data.frame(real = factor(dat$y),
    prob = predict(lr.fit, type = "response"))

que

ggplot(res, aes(x=prob, fill=real)) +
    geom_density(alpha=.3)

representa así:

predicciones_gam

Me pregunto si el clasificador construido es bueno. Para lo cual voy a construir la curva ROC con