¿Cómo interpretar Lasso reduciendo todos los coeficientes a 0?

8

Tengo un conjunto de datos con 338 predictores y 570 instancias (desafortunadamente no se puede cargar) en el que estoy usando el Lazo para realizar la selección de funciones. En particular, estoy usando la cv.glmnetfunción de la glmnetsiguiente manera, donde mydata_matrixhay una matriz binaria de 570 x 339 y la salida también es binaria:

library(glmnet)
x_dat <- mydata_matrix[, -ncol(mydata_matrix)]
y <- mydata_matrix[, ncol(mydata_matrix)]
cvfit <- cv.glmnet(x_dat, y, family='binomial')

Este gráfico muestra que la desviación más baja ocurre cuando todas las variables se han eliminado del modelo. ¿Esto realmente dice que solo usar la intercepción es más predictivo del resultado que usar incluso un solo predictor, o he cometido un error, posiblemente en los datos o en la llamada a la función?

Esto es similar a una pregunta anterior , pero no obtuvo ninguna respuesta.

plot(cvfit)

ingrese la descripción de la imagen aquí

Stuart Lacy
fuente
1
Creo que este enlace puede desarrollar algunos de los detalles. En esencia, puede significar que muchos (si no todos) sus predictores no son muy significativos. El hilo a continuación explica esto con más detalle. stats.stackexchange.com/questions/182595/…
Dhiraj
3
@Dhiraj Significant es un término técnico relacionado con la prueba de significación de hipótesis nula. No es apropiado aquí.
Matthew Drury

Respuestas:

11

No creo que hayas cometido un error en el código. Se trata de interpretar la salida.

El lazo no indica qué regresores individuales son "más predictivos" que otros. Simplemente tiene una tendencia incorporada a estimar coeficientes como cero. Cuanto mayor es el coeficiente de penalización , mayor es esa tendencia.log(λ)

Su gráfica de validación cruzada muestra que a medida que más y más coeficientes se fuerzan a cero, el modelo hace un mejor y mejor trabajo al predecir subconjuntos de valores que se han eliminado al azar del conjunto de datos. Cuando se logran los mejores errores de predicción con validación cruzada (medidos como la "Desviación Binomial" aquí) cuando todos los coeficientes son cero, debe sospechar que ninguna combinación lineal de ningún subconjunto de regresores puede ser útil para predecir los resultados.

Puede verificar esto generando respuestas aleatorias que sean independientes de todos los regresores y aplicando su procedimiento de ajuste. Aquí hay una forma rápida de emular su conjunto de datos:

n <- 570
k <- 338
set.seed(17)
X <- data.frame(matrix(floor(runif(n*(k+1), 0, 2)), nrow=n,
                       dimnames=list(1:n, c("y", paste0("x", 1:k)))))

El marco de datos Xtiene una columna binaria aleatoria llamada "y" y otras 338 columnas binarias (cuyos nombres no importan). Utilicé su enfoque para hacer retroceder "y" contra esas variables, pero, solo para tener cuidado, me aseguré de que el vector de respuesta yy la matriz del modelo xcoincidan (lo que podrían no hacer en caso de que falten valores en los datos) :

f <- y ~ . - 1            # cv.glmnet will include its own intercept
M <- model.frame(f, X)
x <- model.matrix(f, M)
y <- model.extract(M, "response")
fit <- cv.glmnet(x, y, family="binomial")

El resultado es notablemente como el tuyo:

plot(fit)

Figura

De hecho, con estos datos completamente aleatorios, el Lazo aún devuelve nueve estimaciones de coeficientes distintos de cero (aunque sabemos, por construcción, que los valores correctos son todos cero). Pero no debemos esperar la perfección. Además, debido a que el ajuste se basa en la eliminación aleatoria de subconjuntos de datos para la validación cruzada, generalmente no obtendrá el mismo resultado de una ejecución a la siguiente. En este ejemplo, una segunda llamada a cv.glmnetproduce un ajuste con un solo coeficiente distinto de cero. Por esta razón, si tiene tiempo, siempre es una buena idea volver a ejecutar el procedimiento de ajuste varias veces y realizar un seguimiento de qué coeficientes estimados son consistentemente distintos de cero. Para estos datos, con cientos de regresores, esto llevará un par de minutos repetir nueve veces más.

sim <- cbind(as.numeric(coef(fit)), 
             replicate(9, as.numeric(coef(cv.glmnet(x, y, family="binomial")))))
plot(1:k, rowMeans(sim[-1,] != 0) + runif(k, -0.025, 0.025), 
     xlab="Coefficient Index", ylab="Frequency not zero (jittered)",
     main="Results of Repeated Cross-Validated Lasso Fits")

Figura 2

Ocho de estos regresores tienen estimaciones distintas de cero en aproximadamente la mitad de los ajustes; el resto de ellos nunca tienen estimaciones distintas de cero. Esto muestra en qué medida el Lazo aún incluirá estimaciones de coeficientes distintos de cero, incluso cuando los coeficientes sean verdaderamente cero.

whuber
fuente
1

Si desea obtener más información puede usar la función

fit1<-glmnet(x_dat, y, family='binomial', alpha= x)

plot(fit1, xvar = "lambda", label = TRUE)

El gráfico debe ser similar a ingrese la descripción de la imagen aquí Las etiquetas permiten identificar el efecto de lambda para los regresores.

¿Puede usar diferentes valores de x (en el modelo se llama factor alfa) a 0 (regresión de cresta) a 1 (regresión LASSO)? El valor [0,1] es la regresión neta elástica

Luigi Biagini
fuente
Disminuir alfa a 0.5 ha ayudado a incluir más variables, gracias por el consejo.
Stuart Lacy
0

La respuesta de que no hay combinaciones lineales de variables que sean útiles para predecir resultados es cierta en algunos casos, pero no en todos.

Tenía una trama como la anterior que fue causada por multicolinealidad en mis datos. La reducción de las correlaciones permitió que Lasso funcionara, pero también eliminó información útil sobre los resultados. Se obtuvieron mejores conjuntos de variables usando la importancia aleatoria del bosque para seleccionar las variables y luego usando Lasso.

Lluvioso
fuente
-1

Es posible pero un poco sorprendente. LASSO puede hacer cosas raras cuando tiene colinealidad, en cuyo caso probablemente debería establecer alfa <1 para que se ajuste la red elástica. Puede elegir alfa mediante validación cruzada, pero asegúrese de utilizar los mismos pliegues para cada valor de alfa.

persona_dentro
fuente