AUC = Wilcoxon , de nuevo

estadística
2021
Author

José Luis Cañadas Reche

Published

March 8, 2021

Anda la gente que si viendo a ver cómo calcular el AUC (roc), que si cómo se hace en spark o que si hay que tener en cuenta muchos puntos de corte y ver las tablas de clasificación asociadas. Eso está bien para contarlo, pero no para calcularlo.

El AUC se puede considerar como la probabilidad de que el score de un “sí” elegido al azar es mayor que el score de un “no” elegido al azar. No lo digo yo, lo cuenta mucho mejor que yo , Carlos en su entrada AUC = WILCOXON. De hecho, voy a coger sus mismos datos, salvo por la semilla, que no la indica.

Mostrar / ocultar código
set.seed(45)
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)

Y como bien comenta Carlos, tanto Wilcoxon como el cálculo usual del AUC dan esa probabilidad. Para esto da igual que los scores sean incluso negativo, se trata de algo que da un orden.

Mostrar / ocultar código
car::some(dat)
#>    res      score
#> 1   si  1.3407997
#> 2   si  0.2966597
#> 7   si  0.4986218
#> 9   si  2.8090374
#> 12  si  1.2159889
#> 34  no  0.2854323
#> 40  no  0.2459699
#> 48  no -0.3504094
#> 53  no  0.1114906
#> 60  no -0.8165108

Y copiando de su blog

Mostrar / ocultar código
test <- wilcox.test(score ~ res, data = dat)$statistic
# pongo el 1- pq salia menor que 0.5
1- test / n^2
#>         W 
#> 0.7122222
Mostrar / ocultar código
library(pROC)
my_roc <- roc(dat$res, dat$score)
auc(my_roc)
#> Area under the curve: 0.7122

Pero también podemos hacerlo muestreando.

Nos creamos función

Mostrar / ocultar código
etiquetas <- dat$res=="si"
table(etiquetas)
#> etiquetas
#> FALSE  TRUE 
#>    30    30

Ahora muestreamos con reemplazamiento los scores correspondientes a etiqueta = TRUE, es decir a los sis

Mostrar / ocultar código
pos <- sample(dat$score[etiquetas], size = 1e7, replace = TRUE)
neg <- sample(dat$score[!etiquetas], size = 1e7, replace = TRUE)

Y simplemente calculamos la probabilidad que buscamos haciendo la proporción de la veces qeu el score de un positivo gana al de un negativo.

Mostrar / ocultar código
mean(pos>neg)
#> [1] 0.7122233

Y es una buena aproximación, creemos función y pongamos que en caso de empate de score, ni pa ti ni pa mi.

Mostrar / ocultar código
auc_probability <- function(labels, scores, N=1e7){
  pos <- sample(scores[labels], N, replace=TRUE)
  neg <- sample(scores[!labels], N, replace=TRUE)
  (sum(pos > neg) + sum(pos == neg)/2) / N
}

Pues ya tenemos una forma “sencilla” de calcular auc’s, que se puede usar por ejemplo en sql.

Mostrar / ocultar código
auc_probability(etiquetas, dat$score, N= 1e6)
#> [1] 0.712108

Salud y buena tarde