Czy istnieje sposób wykorzystania krzyżowej weryfikacji do dokonania wyboru zmiennej / cechy w R?

10

Mam zestaw danych z około 70 zmiennymi, które chciałbym wyciąć. Chcę użyć CV, aby znaleźć najbardziej przydatne zmienne w następujący sposób.

1) Losowo wybierz powiedz 20 zmiennych.

2) Użyj stepwise/ LASSO/ lars/ etc, aby wybrać najważniejsze zmienne.

3) Powtórz ~ 50x i zobacz, które zmienne są najczęściej wybierane (nie eliminowane).

Jest to zgodne z tym, co randomForestzrobiłoby a, ale rfVarSelwydaje się, że pakiet działa tylko dla czynników / klasyfikacji i muszę przewidzieć ciągłą zmienną zależną.

Używam R, więc wszelkie sugestie byłyby idealnie tam zaimplementowane.

screechOwl
źródło
Czy wszystkie funkcje są ważne? Ile masz próbek? Jeśli dobrze rozumiem problem, możesz spróbować wykonać pewien wariant wzmocnienia - wielokrotnie wybierz podzbiór próbek i dopasuj do nich wszystkie zmienne i zobacz, które z nich pojawiają się częściej.
Ofelia
1
Myślę, że twoja procedura raczej nie ulegnie poprawie w LASSO, którego implementacje w R (np. Glmnet i penalizowane) domyślnie wykorzystują cross-validation w celu znalezienia „optymalnego” parametru regularyzacji. Jedną z rzeczy, które można wziąć pod uwagę, jest kilkakrotne powtórzenie wyszukiwania tego parametru w LASSO, aby poradzić sobie z potencjalnie dużą różnorodnością walidacji krzyżowej (powtarzane CV). Oczywiście żaden algorytm nie jest w stanie pokonać Twojej wiedzy na dany temat.
miura

Odpowiedzi:

9

Wierzę, że to, co opisujesz, jest już zaimplementowane w caretpakiecie. Spójrz na rfefunkcję lub winietę tutaj: http://cran.r-project.org/web/packages/caret/vignettes/caretSelection.pdf

Teraz, powiedziawszy to, dlaczego musisz zmniejszyć liczbę funkcji? Od 70 do 20 nie jest tak naprawdę spadkiem rzędu wielkości. Sądzę, że potrzebujesz więcej niż 70 funkcji, zanim będziesz miał zdecydowane przekonanie, że niektóre funkcje naprawdę i naprawdę nie mają znaczenia. Ale z drugiej strony, przypuszczam, że tutaj pojawia się subiektywny przeor.

Shea Parkes
źródło
5

Nie ma powodu, dla którego częstotliwość wyboru zmiennych dostarcza jakichkolwiek informacji, których nie otrzymujesz z pozornego znaczenia zmiennych w modelu początkowym. Jest to zasadniczo powtórzenie początkowego znaczenia statystycznego. dodajesz także nowy poziom arbitralności, gdy próbujesz zdecydować o wartości granicznej dla częstotliwości wyboru. Wybór zmiennych ponownego próbkowania jest poważnie uszkodzony przez kolinearność oprócz innych problemów.

Frank Harrell
źródło
2

Poprawiłem swoją odpowiedź z dzisiejszego dnia wcześniej. Wygenerowałem teraz kilka przykładowych danych, na których można uruchomić kod. Inni słusznie zasugerowali, abyś zastanowił się nad użyciem pakietu Caret, z którym się zgadzam. Jednak w niektórych przypadkach może być konieczne napisanie własnego kodu. Poniżej próbowałem zademonstrować, jak używać funkcji sample () w R do losowego przypisywania obserwacji do fałdów walidacji krzyżowej. Używam również pętli do przeprowadzania wstępnej selekcji zmiennych (przy użyciu regresji liniowej jednowymiarowej z łagodnym odcięciem wartości p 0,1) i budowania modelu (przy użyciu regresji krokowej) na dziesięciu zestawach treningowych. Następnie możesz napisać własny kod, aby zastosować powstałe modele do fałdów sprawdzania poprawności. Mam nadzieję że to pomoże!

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

Przed przeprowadzeniem walidacji krzyżowej ważne jest, aby przeczytać o jej właściwym użyciu. Te dwa odniesienia oferują doskonałe dyskusje na temat walidacji krzyżowej:

  1. Simon RM, Subramanian J, Li MC, Menezes S. Wykorzystanie walidacji krzyżowej do oceny dokładności predykcyjnej klasyfikatorów ryzyka przeżycia na podstawie danych wielowymiarowych. Krótkie Bioinform. 2011 maja; 12 (3): 203-14. Epub 2011 15 lutego. Http://bib.oxfordjournals.org/content/12/3/203.long
  2. Richard Simon, Michael D. Radmacher, Kevin Dobbin i Lisa M. McShane. Pułapki związane z wykorzystaniem danych z mikromacierzy DNA do klasyfikacji diagnostycznej i prognostycznej. JNCI J Natl Cancer Inst (2003) 95 (1): 14–18. http://jnci.oxfordjournals.org/content/95/1/14.long

Te artykuły są skierowane do biostatystów, ale przydałyby się każdemu.

Pamiętaj też, że stosowanie regresji krokowej jest niebezpieczne (chociaż stosowanie weryfikacji krzyżowej powinno pomóc w złagodzeniu nadmiernego dopasowania). Dobra dyskusja na temat regresji krokowej jest dostępna tutaj: http://www.stata.com/support/faqs/stat/stepwise.html .

Daj mi znać, jeśli masz dodatkowe pytania!

Alexander
źródło
0

Właśnie znalazłem tutaj coś ładnego: http://cran.r-project.org/web/packages/Causata/vignettes/Causata-vignette.pdf

Spróbuj tego, może podczas korzystania z pakietu 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
źródło