10 votos

¿Hay alguna manera de utilizar la validación cruzada para hacer la selección de variables/características en R?

Tengo un conjunto de datos con unas 70 variables que me gustaría reducir. Lo que quiero hacer es utilizar CV para encontrar las variables más útiles de la siguiente manera.

1) Seleccione aleatoriamente, por ejemplo, 20 variables.

2) Utilizar stepwise / LASSO / lars /etc para elegir las variables más importantes.

3) Repita ~50x y vea qué variables se seleccionan (no se eliminan) con más frecuencia.

Esto va en la línea de lo que un randomForest lo haría, pero el rfVarSel parece que sólo funciona para factores/clasificación y yo necesito predecir una variable dependiente continua.

Estoy usando R así que cualquier sugerencia sería idealmente implementada allí.

9voto

Shea Parkes Puntos 2014

Creo que lo que describes ya está implementado en el caret paquete. Mira el rfe o la viñeta aquí: http://cran.r-project.org/web/packages/caret/vignettes/caretSelection.pdf

Ahora bien, dicho esto, ¿por qué hay que reducir el número de funciones? Pasar de 70 a 20 no es realmente una disminución del orden de magnitud. Creo que se necesitarían más de 70 características antes de tener la firme creencia a priori de que algunas de las características realmente no importan. Pero, de nuevo, supongo que ahí es donde entra en juego un previo subjetivo.

5voto

dan90266 Puntos 609

No hay ninguna razón por la que la frecuencia de selección de variables proporcione alguna información que no se obtenga ya de la importancia aparente de las variables en el modelo inicial. Esto es esencialmente una repetición de la importancia estadística inicial. también se está añadiendo un nuevo nivel de arbitrariedad al intentar decidir un límite para la frecuencia de selección. La selección de variables por remuestreo se ve muy perjudicada por la colinealidad, además de los otros problemas.

3voto

Joe Zack Puntos 1248

He revisado mi respuesta de hoy. Ahora he generado algunos datos de ejemplo para ejecutar el código. Otros han sugerido, con razón, que se utilice el paquete caret, con lo que estoy de acuerdo. Sin embargo, en algunos casos puede ser necesario escribir tu propio código. A continuación he intentado demostrar cómo utilizar la función sample() en R para asignar aleatoriamente las observaciones a los pliegues de validación cruzada. También utilizo los bucles for para realizar la preselección de variables (utilizando la regresión lineal univariante con un valor de corte indulgente de 0,1) y la construcción del modelo (utilizando la regresión por pasos) en los diez conjuntos de entrenamiento. A continuación, puede escribir su propio código para aplicar los modelos resultantes a los pliegues de validación. Espero que esto sea de ayuda.

################################################################################
## Load the MASS library, which contains the "stepAIC" function for performing
## stepwise regression, to be used later in this script
library(MASS)
################################################################################

################################################################################
## Generate example data, with 100 observations (rows), 70 variables (columns 1
## to 70), and a continuous dependent variable (column 71)
Data <- NULL
Data <- as.data.frame(Data)

for (i in 1:71) {
for (j in 1:100) {
Data[j,i]  <- rnorm(1) }}

names(Data)[71] <- "Dependent"
################################################################################

################################################################################
## Create ten folds for cross-validation. Each observation in your data will
## randomly be assigned to one of ten folds.
Data$Fold <- sample(c(rep(1:10,10)))

## Each fold will have the same number of observations assigned to it. You can
## double check this by typing the following:
table(Data$Fold)

## Note: If you were to have 105 observations instead of 100, you could instead
## write: Data$Fold <- sample(c(rep(1:10,10),rep(1:5,1)))
################################################################################

################################################################################
## I like to use a "for loop" for cross-validation. Here, prior to beginning my
## "for loop", I will define the variables I plan to use in it. You have to do
## this first or R will give you an error code.
fit <- NULL
stepw <- NULL
training <- NULL
testing <- NULL
Preselection <- NULL
Selected <- NULL
variables <- NULL
################################################################################

################################################################################
## Now we can begin the ten-fold cross validation. First, we open the "for loop"
for (CV in 1:10) {

## Now we define your training and testing folds. I like to store these data in
## a list, so at the end of the script, if I want to, I can go back and look at
## the observations in each individual fold
training[[CV]] <- Data[which(Data$Fold != CV),]
testing[[CV]]  <- Data[which(Data$Fold == CV),]

## We can preselect variables by analyzing each variable separately using
## univariate linear regression and then ranking them by p value. First we will
## define the container object to which we plan to output these data.
Preselection[[CV]] <- as.data.frame(Preselection[CV])

## Now we will run a separate linear regression for each of our 70 variables.
## We will store the variable name and the coefficient p value in our object
## called "Preselection".
for (i in 1:70) {
Preselection[[CV]][i,1]  <- i
Preselection[[CV]][i,2]  <- summary(lm(Dependent ~ training[[CV]][,i] , data = training[[CV]]))$coefficients[2,4]
}

## Now we will remove "i" and also we will name the columns of our new object.
rm(i)
names(Preselection[[CV]]) <- c("Variable", "pValue")

## Now we will make note of those variables whose p values were less than 0.1.
Selected[[CV]] <- Preselection[[CV]][which(Preselection[[CV]]$pValue <= 0.1),] ; row.names(Selected[[CV]]) <- NULL

## Fit a model using the pre-selected variables to the training fold
## First we must save the variable names as a character string
temp <- NULL
for (k in 1:(as.numeric(length(Selected[[CV]]$Variable)))) {
temp[k] <- paste("training[[CV]]$V",Selected[[CV]]$Variable[k]," + ",sep="")}
variables[[CV]] <- paste(temp, collapse = "")
variables[[CV]] <- substr(variables[[CV]],1,(nchar(variables[[CV]])-3))

## Now we can use this string as the independent variables list in our model
y <- training[[CV]][,"Dependent"]
form <- as.formula(paste("y ~", variables[[CV]]))

## We can build a model using all of the pre-selected variables
fit[[CV]] <- lm(form, training[[CV]])

## Then we can build new models using stepwise removal of these variables using
## the MASS package
stepw[[CV]] <- stepAIC(fit[[CV]], direction="both")

## End for loop
}

## Now you have your ten training and validation sets saved as training[[CV]]
## and testing[[CV]]. You also have results from your univariate pre-selection
## analyses saved as Preselection[[CV]]. Those variables that had p values less
## than 0.1 are saved in Selected[[CV]]. Models built using these variables are
## saved in fit[[CV]]. Reduced versions of these models (by stepwise selection)
## are saved in stepw[[CV]].

## Now you might consider using the predict.lm function from the stats package
## to apply your ten models to their corresponding validation folds. You then
## could look at the performance of the ten models and average their performance
## statistics together to get an overall idea of how well your data predict the
## outcome.
################################################################################

Antes de realizar la validación cruzada, es importante que lea sobre su uso adecuado. Estas dos referencias ofrecen excelentes discusiones sobre la validación cruzada:

  1. Simon RM, Subramanian J, Li MC, Menezes S. Using cross-validation to evaluate predictive accuracy of survival risk classifiers based on high-dimensional data. Brief Bioinform. 2011 May;12(3):203-14. Epub 2011 Feb 15. http://bib.oxfordjournals.org/content/12/3/203.long
  2. Richard Simon, Michael D. Radmacher, Kevin Dobbin y Lisa M. McShane. Pitfalls in the Use of DNA Microarray Data for Diagnostic and Prognostic Classification. JNCI J Natl Cancer Inst (2003) 95 (1): 14-18. http://jnci.oxfordjournals.org/content/95/1/14.long

Estos documentos están dirigidos a los bioestadísticos, pero pueden ser útiles para cualquier persona.

Además, tenga siempre en cuenta que el uso de la regresión por pasos es peligroso (aunque el uso de la validación cruzada debería ayudar a aliviar el exceso de ajuste). Una buena discusión sobre la regresión por pasos está disponible aquí: http://www.stata.com/support/faqs/stat/stepwise.html .

Hágame saber si tiene alguna otra pregunta.

0voto

Ahmed Kotb Puntos 2492

Acabo de encontrar algo bonito por aquí: http://cran.r-project.org/web/packages/Causata/vignettes/Causata-vignette.pdf

Pruebe esto tal vez cuando se utiliza el paquete glmnet

# extract nonzero coefficients
coefs.all <- as.matrix(coef(cv.glmnet.obj, s="lambda.min"))
idx <- as.vector(abs(coefs.all) > 0)
coefs.nonzero <- as.matrix(coefs.all[idx])
rownames(coefs.nonzero) <- rownames(coefs.all)[idx]

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X