Apakah ada cara untuk menggunakan validasi silang untuk melakukan pemilihan variabel / fitur di R?

10

Saya memiliki satu set data dengan sekitar 70 variabel yang ingin saya kurangi. Yang ingin saya lakukan adalah menggunakan CV untuk menemukan variabel yang paling berguna dengan cara berikut.

1) Pilih secara acak katakan 20 variabel.

2) Gunakan stepwise/ LASSO/ lars/ etc untuk memilih variabel yang paling penting.

3) Ulangi ~ 50x dan lihat variabel mana yang paling sering dipilih (tidak dihilangkan).

Ini sejalan dengan apa yang randomForestakan dilakukan, tetapi rfVarSelpaket tampaknya hanya berfungsi untuk faktor / klasifikasi dan saya perlu memprediksi variabel dependen kontinu.

Saya menggunakan R sehingga setiap saran idealnya akan diterapkan di sana.

screechOwl
sumber
Apakah semua fitur penting? Berapa banyak sampel yang Anda miliki? Jika saya memahami masalahnya dengan benar, Anda dapat mencoba melakukan beberapa varian peningkatan - berulang kali pilih subset sampel dan masukkan semua variabel ke dalamnya dan lihat mana yang muncul lebih sering.
Ofelia
1
Saya pikir prosedur Anda tidak mungkin membaik pada LASSO, yang implementasinya dalam R (misalnya glmnet dan dihukum) secara default menggunakan cross-validation untuk menemukan parameter regularisasi "optimal". Satu hal yang dapat Anda pertimbangkan adalah mengulangi pencarian LASSO untuk parameter ini beberapa kali untuk mengatasi varians cross-validation yang berpotensi besar (CV berulang). Tentu saja, tidak ada algoritma yang dapat mengalahkan pengetahuan Anda sebelumnya tentang subjek tertentu.
miura

Jawaban:

9

Saya percaya apa yang Anda gambarkan sudah diterapkan dalam caretpaket. Lihatlah rfefungsi atau sketsa di sini: http://cran.r-project.org/web/packages/caret/vignettes/caretSelection.pdf

Sekarang, setelah mengatakan itu, mengapa Anda perlu mengurangi jumlah fitur? Dari 70 hingga 20 sebenarnya bukan urutan penurunan yang besar. Saya pikir Anda akan membutuhkan lebih dari 70 fitur sebelum Anda memiliki firma sebelumnya yang percaya bahwa beberapa fitur benar-benar dan benar-benar tidak masalah. Tapi sekali lagi, di situlah suatu prior subyektif masuk kurasa.

Shea Parkes
sumber
5

Tidak ada alasan mengapa frekuensi pemilihan variabel memberikan informasi apa pun yang belum Anda dapatkan dari pentingnya variabel dalam model awal. Ini pada dasarnya adalah ulangan signifikansi statistik awal. Anda juga menambahkan tingkat kesewenang-wenangan baru ketika mencoba memutuskan batas frekuensi pemilihan. Resampling pemilihan variabel rusak parah oleh collinearity selain masalah lainnya.

Frank Harrell
sumber
2

Saya telah merevisi jawaban saya sebelumnya hari ini. Saya sekarang telah menghasilkan beberapa contoh data untuk menjalankan kode. Yang lain dengan tepat menyarankan agar Anda mempertimbangkan menggunakan paket caret, yang saya setujui. Namun, dalam beberapa kasus, Anda mungkin perlu menulis kode Anda sendiri. Di bawah ini saya telah mencoba menunjukkan bagaimana menggunakan fungsi sample () dalam R untuk secara acak menetapkan pengamatan pada lipatan validasi silang. Saya juga menggunakan loop untuk melakukan seleksi awal variabel (menggunakan regresi linier univariat dengan nilai p cutoff 0,1) dan membangun model (menggunakan regresi bertahap) pada sepuluh set pelatihan. Anda kemudian dapat menulis kode Anda sendiri untuk menerapkan model yang dihasilkan ke lipatan validasi. Semoga ini membantu!

################################################################################
## 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.
################################################################################

Sebelum melakukan validasi silang, Anda harus membaca tentang penggunaannya yang benar. Kedua referensi ini menawarkan diskusi yang sangat baik tentang validasi silang:

  1. Simon RM, Subramanian J, Li MC, Menezes S. Menggunakan cross-validation untuk mengevaluasi akurasi prediksi pengklasifikasi risiko kelangsungan hidup berdasarkan data dimensi tinggi. Bioinform singkat. 2011 Mei; 12 (3): 203-14. Epub 2011 Februari 15. http://bib.oxfordjournals.org/content/12/3/203.long
  2. Richard Simon, Michael D. Radmacher, Kevin Dobbin dan Lisa M. McShane. Jebakan dalam Penggunaan Data Microarray DNA untuk Klasifikasi Diagnostik dan Prognostik. JNCI J Natl Cancer Inst (2003) 95 (1): 14-18. http://jnci.oxfordjournals.org/content/95/1/14.long

Makalah-makalah ini diarahkan untuk biostatistik, tetapi akan bermanfaat bagi siapa pun.

Juga, selalu ingat bahwa menggunakan regresi bertahap berbahaya (walaupun menggunakan validasi silang akan membantu mengurangi overfitting). Diskusi yang baik tentang regresi bertahap tersedia di sini: http://www.stata.com/support/faqs/stat/stepwise.html .

Beri tahu saya jika Anda memiliki pertanyaan tambahan!

Alexander
sumber
0

Saya baru saja menemukan sesuatu yang bagus di sini: http://cran.r-project.org/web/packages/Causata/vignettes/Causata-vignette.pdf

Coba ini mungkin saat menggunakan Paket 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]
Simon Nehls
sumber