web-dev-qa-db-fra.com

Régression pas à pas en utilisant des valeurs p pour supprimer les variables avec des valeurs p non significatives

Je souhaite effectuer une régression linéaire pas à pas en utilisant valeurs-p comme critère de sélection. toutes les valeurs sont significatives définies par un seuil alpha.

Je suis tout à fait conscient que je devrais utiliser l'AIC (par exemple, la commande step ou stepAIC) ou un autre critère à la place, mais mon patron n'a aucune connaissance des statistiques et insiste sur l'utilisation des valeurs p.

Si nécessaire, je pourrais programmer ma propre routine, mais je me demande s'il existe une version déjà implémentée de celle-ci.

28
DainisZ

Montrez à votre patron ce qui suit:

set.seed(100)
x1 <- runif(100,0,1)
x2 <- as.factor(sample(letters[1:3],100,replace=T))

y <- x1+x1*(x2=="a")+2*(x2=="b")+rnorm(100)
summary(lm(y~x1*x2))

Qui donne :

            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -0.1525     0.3066  -0.498  0.61995    
x1            1.8693     0.6045   3.092  0.00261 ** 
x2b           2.5149     0.4334   5.802 8.77e-08 ***
x2c           0.3089     0.4475   0.690  0.49180    
x1:x2b       -1.1239     0.8022  -1.401  0.16451    
x1:x2c       -1.0497     0.7873  -1.333  0.18566    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

Maintenant, en fonction des valeurs-p, vous excluriez laquelle? x2 est le plus significatif et le moins significatif en même temps.


Edit: Pour préciser: Cet exemple n'est pas le meilleur, comme indiqué dans les commentaires. La procédure décrite dans Stata et SPSS est également AFAIK, non pas non plus sur les valeurs p du test T sur les coefficients, mais sur le test F après suppression d’une des variables. 

J'ai une fonction qui fait exactement cela. Ceci est une sélection sur "la valeur p", mais pas du test T sur les coefficients ou sur les résultats anova. Eh bien, n'hésitez pas à l'utiliser si cela vous semble utile.

#####################################
# Automated model selection
# Author      : Joris Meys
# version     : 0.2
# date        : 12/01/09
#####################################
#CHANGE LOG
# 0.2   : check for empty scopevar vector
#####################################

# Function has.interaction checks whether x is part of a term in terms
# terms is a vector with names of terms from a model
has.interaction <- function(x,terms){
    out <- sapply(terms,function(i){
        sum(1-(strsplit(x,":")[[1]] %in% strsplit(i,":")[[1]]))==0
    })
    return(sum(out)>0)
}

# Function Model.select
# model is the lm object of the full model
# keep is a list of model terms to keep in the model at all times
# sig gives the significance for removal of a variable. Can be 0.1 too (see SPSS)
# verbose=T gives the F-tests, dropped var and resulting model after 
model.select <- function(model,keep,sig=0.05,verbose=F){
      counter=1
      # check input
      if(!is(model,"lm")) stop(paste(deparse(substitute(model)),"is not an lm object\n"))
      # calculate scope for drop1 function
      terms <- attr(model$terms,"term.labels")
      if(missing(keep)){ # set scopevars to all terms
          scopevars <- terms
      } else{            # select the scopevars if keep is used
          index <- match(keep,terms)
          # check if all is specified correctly
          if(sum(is.na(index))>0){
              novar <- keep[is.na(index)]
              warning(paste(
                  c(novar,"cannot be found in the model",
                  "\nThese terms are ignored in the model selection."),
                  collapse=" "))
              index <- as.vector(na.omit(index))
          }
          scopevars <- terms[-index]
      }

      # Backward model selection : 

      while(T){
          # extract the test statistics from drop.
          test <- drop1(model, scope=scopevars,test="F")

          if(verbose){
              cat("-------------STEP ",counter,"-------------\n",
              "The drop statistics : \n")
              print(test)
          }

          pval <- test[,dim(test)[2]]

          names(pval) <- rownames(test)
          pval <- sort(pval,decreasing=T)

          if(sum(is.na(pval))>0) stop(paste("Model",
              deparse(substitute(model)),"is invalid. Check if all coefficients are estimated."))

          # check if all significant
          if(pval[1]<sig) break # stops the loop if all remaining vars are sign.

          # select var to drop
          i=1
          while(T){
              dropvar <- names(pval)[i]
              check.terms <- terms[-match(dropvar,terms)]
              x <- has.interaction(dropvar,check.terms)
              if(x){i=i+1;next} else {break}              
          } # end while(T) drop var

          if(pval[i]<sig) break # stops the loop if var to remove is significant

          if(verbose){
             cat("\n--------\nTerm dropped in step",counter,":",dropvar,"\n--------\n\n")              
          }

          #update terms, scopevars and model
          scopevars <- scopevars[-match(dropvar,scopevars)]
          terms <- terms[-match(dropvar,terms)]

          formul <- as.formula(paste(".~.-",dropvar))
          model <- update(model,formul)

          if(length(scopevars)==0) {
              warning("All variables are thrown out of the model.\n",
              "No model could be specified.")
              return()
          }
          counter=counter+1
      } # end while(T) main loop
      return(model)
}
28
Joris Meys

Pourquoi ne pas essayer d’utiliser la fonction step() en spécifiant votre méthode de test?

Par exemple, pour l'élimination en arrière, vous ne tapez qu'une commande:

step(FullModel, direction = "backward", test = "F")

et pour une sélection par étapes, simplement:

step(FullModel, direction = "both", test = "F")

Cela peut afficher les valeurs AIC ainsi que les valeurs F et P.

17
leonie

Voici un exemple. Commencez par le modèle le plus compliqué: cela inclut les interactions entre les trois variables explicatives.

model1 <-lm (ozone~temp*wind*rad)
summary(model1)

Coefficients:
Estimate Std.Error t value Pr(>t)
(Intercept) 5.683e+02 2.073e+02 2.741 0.00725 **
temp          -1.076e+01 4.303e+00 -2.501 0.01401 *
wind          -3.237e+01 1.173e+01 -2.760 0.00687 **
rad           -3.117e-01 5.585e-01 -0.558 0.57799
temp:wind      2.377e-01 1.367e-01 1.739 0.08519   
temp:rad       8.402e-03 7.512e-03 1.119 0.26602
wind:rad       2.054e-02 4.892e-02 0.420 0.47552
temp:wind:rad -4.324e-04 6.595e-04 -0.656 0.51358

L'interaction à trois voies n'est clairement pas significative. Voici comment vous le supprimez pour commencer le processus de simplification du modèle:

model2 <- update(model1,~. - temp:wind:rad)
summary(model2)

En fonction des résultats, vous pouvez continuer à simplifier votre modèle:

model3 <- update(model2,~. - temp:rad)
summary(model3)
...

Sinon, vous pouvez utiliser la fonction de simplification automatique du modèle step, à voirqui

model_step <- step(model1)
10
George Dontas

Si vous essayez simplement d'obtenir le meilleur modèle prédictif, alors peut-être que cela n'a pas d'importance, mais pour le reste, ne vous embêtez pas avec ce type de sélection de modèle. Il est faux.

Utilisez des méthodes de retrait telles que la régression de crête (dans lm.ridge() dans le package MASS par exemple), ou le lasso, ou le réseau élastique (une combinaison de contraintes de crête et de lasso). Parmi ceux-ci, seuls le lasso et le filet élastique effectuent une certaine forme de sélection de modèle, c'est-à-dire contraignent les coefficients de certaines covariables à zéro.

Reportez-vous à la section Régularisation et réduction de la vue Machine Learning sur CRAN.

7
Gavin Simpson

Paquet rms: stratégies de modélisation de régression a fastbw() qui fait exactement ce dont vous avez besoin. Il existe même un paramètre permettant de passer de l’AIC à l’élimination basée sur la valeur p.

7
Chris

Comme mentionné par Gavin Simpson, la fonction fastbw du package rms peut être utilisée pour sélectionner des variables à l'aide de la valeur p. Ci-dessous un exemple utilisant l'exemple donné par George Dontas. Utilisez l'option rule='p' pour sélectionner les critères de valeur p.

require(rms)
model1 <- ols(Ozone ~ Temp * Wind * Solar.R, data=airquality)
model2 <- fastbw(fit=model1, rule="p", sls=0.05)
model2
0
fhernanb