Estadística

¿Qué queda de la "estadística robusta" clásica?

Estos días estoy muy atento a todo lo que tiene que ver con estadística robusta. El motivo es doble:

  • Estoy involucrado en un proyecto donde quieren ajustar ciertos modelos usando funciones de pérdida robustas (Huber, Tukey, etc.).
  • Hay una $latex 1 > p > 0$ de que me toque meter mano a MOMO y sus derivados para que lo del coronavirus no joda los contrafactuales de 2021 y sucesivos (¿bastará con eliminar unos cuantos meses de 2020?).

Así las cosas, ha aterrizado en mi tableta The Changing History of Robustness, donde, el autor, Stigler:

Sobremuestreando x (y no y)

Construyo unos datos (artificiales, para conocer la verdad):

n <- 10000
x1 <- rnorm(n)
x2 <- rnorm(n)
probs <- -2 + x1 + x2
probs <- 1 / (1 + exp(-probs))
y <- sapply(probs, function(p) rbinom(1, 1, p))
dat <- data.frame(y = y, x1 = x1, x2 = x2)

Construyo un modelo de clasificación (logístico, que hoy no hace falta inventar, aunque podría ser cualquier otro):

summary(glm(y ~ x1 + x2, data = dat, family = binomial))
#Call:
#glm(formula = y ~ x1 + x2, family = binomial, data = dat)
#
#Deviance Residuals:
#    Min       1Q   Median       3Q      Max
#-2.2547  -0.5967  -0.3632  -0.1753   3.3528
#
#Coefficients:
#            Estimate Std. Error z value Pr(>|z|)
#(Intercept) -2.05753    0.03812  -53.97   <2e-16 ***
#x1           1.01918    0.03386   30.10   <2e-16 ***
#x2           1.00629    0.03405   29.55   <2e-16 ***
#---
#Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#
#(Dispersion parameter for binomial family taken to be 1)
#
#    Null deviance: 9485.2  on 9999  degrees of freedom
#Residual deviance: 7373.4  on 9997  degrees of freedom
#AIC: 7379.4
#
#Number of Fisher Scoring iterations: 5

Correcto.

Sobre predicciones puntuales

Como tan a menudo se nos olvida, Taleb nos recuerda, breve y conciso, un par de cositas sobre las predicciones puntuales aquí. Además, casi todo lo que tiene que decir se resume en:

La regresión logística como el modelo más simple posible (que...)

Problema de regresión. Queremos $y = f(\mathbf{x})$. Lo más simple que podemos hacer: fiarlo todo a Taylor y escribir $ y = a_0 + \sum_i a_i x_i$.

Problema de clasificación. Lo más simple que podemos hacer, de nuevo: linealizar. Pero la expresión lineal tiene rango en $latex (-\infty, \infty)$. Solución, buscar la función $latex f$ más sencilla que se nos pueda ocurrir de $latex (-\infty, \infty)$ en $latex [0, 1]$. Entonces, $latex y = f(a_0 + \sum_i a_i x_i)$.

RuleFit

El otro día me sentí culpable porque me preguntaron sobre RuleFit y tuve que hacer un Simón (aka, me lo estudio para mañana). Y como mañana fue antier, lo que sigue.

Hay descripciones estándar de RuleFit (p.e., esta o la del artículo original) pero me voy a atrever con una original de mi propio cuño.

Comenzamos con lasso. Lasso está bien, pero tiene una limitación sustancial: se le escapan las iteracciones (vale, admito que lo anterior no es universalmente exacto, pero lo es casi y eso me vale). Entonces, la pregunta es: ¿cómo introducir interacciones en lasso?

Explicación de modelos

Este es el primer año en el que en mi curso de ciencia de datos (hasta ahora en el EAE; a partir del año que viene, vaya uno a saber si y dónde) introduzco una sección sobre explicación de modelos.

Hay quienes sostienen que, mejor que crear un modelo de caja negra y tratar luego de explicar las predicciones, es recomendable comenzar con un modelo directamente explicable (p.e., un GLM). Por mucha razón que traigan, vox clamantis in deserto: hay y seguirá habiendo modelos de caja negra por doquier.

53 (o, ¿cuál es la prior?)

En la documentación técnica del estudio ENE-COVID19 (recuérdese: INE + ISCIII) se describe un estudio de fiabilidad previo del test rápido (sección A1.2) que se anuncia así:

Según el fabricante, el test tiene una sensibilidad del 88% y 97% para determinar IgM e IgG respectivamente, y una especificidad de 100% frente a ambos isótopos. Para comprobar el comportamiento del test elegido, se han llevado a cabo dos estudios de fiabilidad.

Veamos en qué consisten.

Aleatoriedad hirsuta, aleatoriedad pochola

Contemplando y comparando

y

se me han venido a la mente los adjetivos hirsuto y pocholo para calificar las respectivas formas de aleatoriedad que representan. La primera es el resultado del habitual

n <- 200
x <- runif(n)
y <- runif(n)
plot(x, y, pch = 16)

mientras que la segunda exige el más sofisticado

library(randtoolbox)
s <- sobol(n, 2, scrambling = 3)
x <- s[,1]
y <- s[,2]
plot(x, y, pch = 16)

Se ve que Sobol quería rellenar más armoniosamente el espacio. Me temo que, al hablar de aleatoriedad, muchos de nosotros también (p.e., esto).

No hagáis esto o se darán cuenta de que sois muy cutres

Lo que no hay que hacer nunca si no quieres que se enteren de que eres inmensamente cutre es escribir código en las líneas del siguiente seudocódigo:

m = model(y ~ a + b + c)
if (modelo.p_value(a) > .05)
    m = model(y ~ b + c)

¡No, no, no, no, NO!

En defensa de Simón: variaciones diarias de la mortalidad

Qué cafres tenéis que ser para que tenga que salir yo —precisamente yo, que tantas cosas no buenas tengo para decir del buen hombre— en defensa de Simón. Tiene delito que de todo lo que se le pueda echar en cara os hayáis fijado en una intervención en la que os trataba de desasnar para que no le anduviéseis buscando tres pies a la varianza.

Es un tema que vengo tratando de antiguo en estas páginas y de ello dan fe:

Consensus clustering

No hay nada tan corrosivo para la fe en el clústering que probar una y otra vez k-medias (por ejemplo) sobre los mismos datos y ver cómo los resultados cambian drásticamente de ejecución en ejecución.

Pero eso viene a ser, esencialmente, lo que hay detrás del consensus clústering (CC), una técnica que puede ser usada, entre otros fines, para determinar el número óptimo de grupos.

La idea fundamental de la cosa es que observaciones que merezcan ser agrupadas juntas lo serán muy frecuentemente aunque cambien ligeramente las condiciones iniciales (por ejemplo, se tome una submuestra de los datos o cambien las condiciones iniciales de k-medias, por ejemplo). Si uno altera esas condiciones iniciales repetidas veces puede contar la proporción de las veces que las observaciones i y j fueron emparejadas juntas y crear la correspondiente matriz (simétrica, para más señas) $latex C(i,j)$.

lme4 + simulate

Esta entrada es casi una referencia para mí. Cada vez tiro más de lme4 en mis modelos y en uno en concreto que tengo entre manos toca simular escenarios. Para lo cual, simulate.merMod.

Véamoslo en funcionamiento. Primero, datos (ANOVA-style) y el modelo que piden a gritos:

library(plyr)
library(lme4)

a <- c(0,0,0, -1, -1, 1, 1, -2, 2)
factors <- letters[1:length(a)]

datos <- ldply(1:100, function(i){
    data.frame(x = factors, y = a + rnorm(length(a)))
})
modelo <- lmer(y ~ (1 | x), data = datos)

El resumen del modelo está niquelado:

summary(modelo)

# Linear mixed model fit by REML ['lmerMod']
# Formula: y ~ (1 | x)
# Data: datos
#
# REML criterion at convergence: 2560.3
#
# Scaled residuals:
#     Min      1Q  Median      3Q     Max
# -3.6798 -0.6442 -0.0288  0.6446  3.3582
#
# Random effects:
#     Groups   Name        Variance Std.Dev.
# x        (Intercept) 1.5197   1.2328
# Residual             0.9582   0.9789
# Number of obs: 900, groups:  x, 9
#
# Fixed effects:
#     Estimate Std. Error t value
# (Intercept) -0.009334   0.412212  -0.023

En particular,