r bigdata glmnet lasso model.matrix

Gran matriz para ejecutar glmnet()



bigdata lasso (2)

A quien le pueda interesar. He desarrollado un paquete R llamado biglasso que se adapta a los modelos tipo lazo con Big Data. Funciona con una matriz de diseño mapeada en memoria (grande) basada en el paquete bigmemory y puede funcionar sin problemas para casos de datos más grandes que la memoria RAM. Además, es más eficiente en computación y memoria en comparación con glmnet mediante el uso de las reglas de evaluación de características recientemente propuestas, así como una mejor implementación. Consulte la página de GitHub para obtener más información y no dude en proporcionarnos sugerencias o comentarios.

Tengo un problema para ejecutar glmnet lasso con un amplio conjunto de datos. Mis datos tienen N = 50, pero p> 49000, todos los factores. Entonces, para ejecutar glmnet tengo que crear un modelo.matriz, PERO simplemente me quedo sin memoria cuando llamo a modelo.

Como ejemplo trabajado generaré un conjunto de datos:

data <- matrix(rep(0,50*49000), nrow=50) for(i in 1:50) { x = rep(letters[2:8], 7000) y = sample(x=1:49000, size=49000) data[i,] <- x[y] } data <- as.data.frame(data) x = c(rep(''A'', 20), rep(''B'', 15), rep(''C'', 15)) y = sample(x=1:50, size=50) class = x[y] data <- cbind(data, class)

Después de eso, traté de crear un model.matrix para ingresar en glmnet.

formula <- as.formula(class ~ .) X = model.matrix(formula, data) model <- cv.glmnet(X, class, standardize=FALSE, family=''multinomial'', alpha=1, nfolds=10)

En el último paso (X = model.matrix ...) me quedé sin memoria. ¿Que puedo hacer?


Le pregunté al profesor Trevor Hastie y recibí los siguientes consejos:

"Hola Flavio

model.matrix te está matando. Tendrá factores de 49K, y la matriz del modelo está tratando de representarlos como contrastes, que serán 6 matrices de columnas, por lo que 49 * 6 aproximadamente 300K columnas. ¿Por qué no hacer variables ficticias binarias (7 por factor), y simplemente construir esto directamente sin usar model.matrix. Podría guardar 1/7 del espacio almacenando esto a través de SparseMatrix (glmnet acepta formatos de matriz dispersos) "

Hice exactamente eso y trabajé perfectamente bien. Creo que eso puede ser útil para otros.

Un artículo, con código, que surgió de este problema: http://www.rmining.net/2014/02/25/genetic-data-large-matrices-glmnet/

Para evitar enlaces rotos, publicaré parte de la publicación aquí:

El problema con el enfoque de la fórmula es que, en general, los datos genómicos tienen más columnas que observaciones. Los datos que trabajé en ese caso tenían 40,000 columnas y solo 73 observaciones. Para crear un pequeño conjunto de datos de prueba, ejecute el siguiente código:

for(i in 1:50) { x = rep(letters[2:8], 7000) y = sample(x=1:49000, size=49000) data[i,] <- x[y] } data <- as.data.frame(data) x <- c(rep(''A'', 20), rep(''B'', 15), rep(''C'', 15)) y <- sample(x=1:50, size=50) class = x[y] data <- cbind(data, class)

Entonces, con este conjunto de datos intentaremos ajustar un modelo con glmnet ():

formula <- as.formula(class ~ .) X <- model.matrix(formula, data) model <- cv.glmnet(X, class, standardize=FALSE, family=''multinomial'', alpha=1, nfolds=10)

Y si no tiene una computadora con más RAM que la mía, probablemente perderá memoria y se bloqueará en R. ¿La solución? Mi primera idea fue probar sparse.model.matrix() que crea un modelo de matriz dispersa con la misma fórmula. Desafortunadamente, no funcionó, porque incluso con una matriz dispersa, ¡el modelo final todavía es demasiado grande! Curiosamente, este conjunto de datos ocupa solo 24 MB de la RAM, pero cuando se utiliza el modelo.matrix, el resultado es una matriz con más de 1 Gb.

La solución que encontré fue construir la matriz a mano. Para hacer esto, codificamos la matriz con variables ficticias, columna por columna, y almacenamos el resultado en una matriz dispersa. Luego usaremos esta matriz como entrada para el modelo y veremos si no perderá memoria:

## Creates a matrix using the first column X <- sparse.model.matrix(~data[,1]-1) ## Check if the column have more then one level for (i in 2:ncol(data)) { ## In the case of more then one level apply dummy coding if (nlevels(data[,i])>1) { coluna <- sparse.model.matrix(~data[,i]-1) X <- cBind(X, coluna) } ## Transform fator to numeric else { coluna <- as.numeric(as.factor(data[,i])) X <- cBind(X, coluna) }

NOTA: Preste atención a cómo estamos utilizando una matriz dispersa; se requiere el paquete Matrix. También tenga en cuenta que las columnas están conectadas utilizando cBind () en lugar de cbind ().

La matriz así generada fue mucho más baja: menos de 70 Mb cuando hice la prueba. Afortunadamente glmnet () admite una matriz dispersa y puede ejecutar el modelo:

mod.lasso <- cv.glmnet(X, class, standardize=FALSE, family=''multinomial'', alpha=1, nfolds=10)

Por lo tanto, puede crear modelos con este tipo de datos sin soplar la memoria y sin usar los paquetes R para grandes conjuntos de datos como bigmemory y ff .