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

10

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

1) Seleccione aleatoriamente digamos 20 variables.

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

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

Esto está en la línea de lo randomForestque haría, pero el rfVarSelpaquete parece funcionar solo para factores / clasificación y necesito predecir una variable dependiente continua.

Estoy usando R, por lo que cualquier sugerencia idealmente se implementaría allí.

Chillido búho
fuente
¿Todas las características son importantes? ¿Cuántas muestras tienes? Si entiendo el problema correctamente, puede intentar hacer alguna variante de refuerzo: seleccione repetidamente un subconjunto de muestras y ajuste todas las variables a ellas y vea cuáles aparecen con más frecuencia.
Ofelia
1
Creo que es poco probable que su procedimiento mejore en LASSO, cuyas implementaciones en R (por ejemplo, glmnet y penalizado) emplean por defecto la validación cruzada para encontrar el parámetro de regularización "óptimo". Una cosa que podría considerar es repetir la búsqueda LASSO de este parámetro varias veces para hacer frente a la variación potencialmente grande de la validación cruzada (CV repetido). Por supuesto, ningún algoritmo puede vencer su conocimiento previo específico del tema.
miura

Respuestas:

9

Creo que lo que describe ya está implementado en el caretpaquete. Mire la rfefunción o la viñeta aquí: http://cran.r-project.org/web/packages/caret/vignettes/caretSelection.pdf

Ahora, dicho eso, ¿por qué necesita reducir la cantidad de funciones? De 70 a 20 no es realmente un orden de disminución de magnitud. Creo que necesitaría más de 70 funciones antes de tener una firma previa y creer que algunas de las funciones realmente y realmente no importan. Pero, de nuevo, ahí es donde entra un prior subjetivo, supongo.

Shea Parkes
fuente
5

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

Frank Harrell
fuente
2

He revisado mi respuesta de hoy más temprano. Ahora he generado algunos datos de ejemplo en los que ejecutar el código. Otros han sugerido acertadamente que considere usar el paquete de caret, con lo que estoy de acuerdo. En algunos casos, sin embargo, puede que sea necesario escribir su propio código. A continuación, he intentado demostrar cómo usar la función sample () en R para asignar aleatoriamente observaciones a pliegues de validación cruzada. También utilizo los bucles para realizar una preselección variable (usando una regresión lineal univariada con un valor de corte indulgente p de 0.1) y la construcción de modelos (usando regresión por pasos) en los diez conjuntos de entrenamiento. Luego puede escribir su propio código para aplicar los modelos resultantes a los pliegues de validación. ¡Espero que esto ayude!

################################################################################
## 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 validación cruzada:

  1. Simon RM, Subramanian J, Li MC, Menezes S. Utilizando la validación cruzada para evaluar la precisión predictiva de los clasificadores de riesgo de supervivencia basados ​​en datos de alta dimensión. Breve Bioinform. Mayo de 2011; 12 (3): 203-14. Epub 2011 15 de febrero. Http://bib.oxfordjournals.org/content/12/3/203.long
  2. Richard Simon, Michael D. Radmacher, Kevin Dobbin y Lisa M. McShane. Dificultades en el uso de datos de microarrays de ADN para la clasificación diagnóstica y pronóstica. 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 bioestadísticos, pero serían útiles para cualquiera.

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

¡Dejame saber si tienes algunas preguntas adicionales!

Alejandro
fuente