Пошаговая регрессия с использованием p-значений для удаления переменных с несущественными p-значениями

Я хочу выполнить пошаговую линейную регрессию с использованием p-значений в качестве критерия выбора, например: на каждом шаге отбрасывать переменные, которые имеют наивысшие, т.е. самые незначительные p-значения, остановка, когда все значения значительны, определенные некоторым порогом альфа.

Я полностью осознаю, что мне следует использовать AIC (например, команду step или stepAIC) или какой-либо другой критерий вместо этого, но мой босс не разбирается в статистике и настаивает на использовании p -ценности.

При необходимости я мог бы запрограммировать свою собственную процедуру, но мне интересно, есть ли уже реализованная версия этого.


person DainisZ    schedule 13.09.2010    source источник
comment
Надеюсь, ваш босс не читает stackoverflow. ;-)   -  person Joshua Ulrich    schedule 13.09.2010
comment
Почему именно ступенчатая регрессия? Сколько у вас переменных?   -  person Vince    schedule 13.09.2010
comment
Вы можете задать этот вопрос здесь: stats.stackexchange.com   -  person Shane    schedule 13.09.2010
comment
Я также мой босс не читает это ;-) У меня есть 9 переменных, и мне нужно немного попробовать, поэтому отбрасывать переменные вручную и самостоятельно настраивать новую модель - это немного сложно, поэтому мне интересно, есть ли автоматический способ как с шагом, только с p-значениями.   -  person DainisZ    schedule 13.09.2010
comment
Потому что кто-то в прошлом использовал пошаговую регрессию с p-значениями (я думаю, со STATA, но у нас больше нет STATA), и она настаивает на использовании точно такого же подхода. Вот такие боссы ... ;-)   -  person DainisZ    schedule 13.09.2010
comment
Может быть легче научить босса хорошей статистике, чем заставить R делать плохую статистику.   -  person Richard Herron    schedule 13.09.2010
comment
Просто выберите три переменные наугад - вы, вероятно, сделаете так же пошаговую регрессию.   -  person hadley    schedule 14.09.2010
comment
Ваш босс также говорит своему врачу, какое лекарство прописать, и его механику, как ремонтировать его машину?   -  person Rob Hyndman    schedule 14.09.2010


Ответы (6)


Покажите своему боссу следующее:

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))

Который дает :

            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 

Теперь, основываясь на p-значениях, которые вы бы исключили? x2 одновременно является наиболее значимым и наиболее незначительным.


Изменить: уточнить: этот пример не самый лучший, как указано в комментариях. Процедура в Stata и SPSS, AFAIK, также основана не на p-значениях T-теста на коэффициенты, а на F-тесте после удаления одной из переменных.

У меня есть функция, которая делает именно это. Это выбор «p-значения», но не Т-теста коэффициентов или результатов anova. Что ж, не стесняйтесь использовать его, если он вам кажется полезным.

#####################################
# 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)
}
person Joris Meys    schedule 13.09.2010
comment
Хороший пример - я мог бы использовать это пару месяцев назад! - person Matt Parker; 13.09.2010
comment
Я думаю, очевидно, что решение не основано исключительно на p-значениях. Вы начинаете с удаления наименее значимых взаимодействий высшего порядка, а затем потенциальных квадратичных членов, прежде чем рассматривать любые объясняющие переменные для удаления. - person George Dontas; 13.09.2010
comment
конечно это не так. Но удалите термин взаимодействия, и вы увидите, что ситуация остается прежней. Так что вам действительно стоит пойти к анове, но тогда вы столкнетесь с проблемой, какого типа. И я не собираюсь открывать эту банку с червями. - person Joris Meys; 13.09.2010
comment
Нет шансов поспорить с боссом на уровне, который сулит статистику ;-) Тем не менее, я постараюсь сделать пошаговый выбор вручную до тех пор. Просто странно, что для этого нет функции R, даже когда подход с использованием p-значений исходит из того времени, когда были слишком высокие вычислительные затраты на вычисление AIC ... - person DainisZ; 13.09.2010
comment
Знаю, это далеко не лучший пример. Это было просто для того, чтобы донести мысль. В любом случае метод, основанный на p-значении, основан на F-тесте, а не на t-тесте коэффициентов. Таким образом, добавленная мною функция должна дать ОП то, что он хочет. - person Joris Meys; 13.09.2010
comment
Спасибо за большую помощь. Вы правы, для метода на основе p-значения я должен использовать F-тест, забыл об этом. Также спасибо за размещение вашего кода, который также очень помогает. - person DainisZ; 15.09.2010
comment
@Joris Meys есть ли способ ограничить количество переменных? например, если я хочу выбрать только 5 или 10, как я могу это сделать? - person nik; 04.11.2016

Почему бы не попробовать использовать функцию step(), указав свой метод тестирования?

Например, для обратного исключения вы набираете только команду:

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

а для пошагового выбора просто:

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

Это может отображать как значения AIC, так и значения F и P.

person leonie    schedule 14.06.2012
comment
Обратите внимание, что эта процедура добавит / удалит переменную с наиболее значимым тестовым значением. Но выбор - продолжить или остановиться - остается за AIC. Я не думаю, что можно остановить процедуру, если нет значимых переменных (как того хочет OP). - person Davor Josipovic; 05.12.2016

Вот пример. Начните с самой сложной модели: она включает взаимодействия между всеми тремя независимыми переменными.

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

Трехстороннее взаимодействие явно не имеет значения. Вот как вы его удалите, чтобы начать процесс упрощения модели:

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

В зависимости от результатов вы можете продолжить упрощение модели:

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

В качестве альтернативы вы можете использовать функцию автоматического упрощения модели step, чтобы увидеть, насколько хорошо она работает:

model_step <- step(model1)
person George Dontas    schedule 13.09.2010
comment
Спасибо за Ваш ответ. Я просто понял, что недостаточно четко сформулировал свой вопрос: я ищу команду или пакет, которые делают это автоматически, используя значение p в качестве критерия. Командный шаг использует AIC. Я также мог бы сделать это вручную, пока вы предлагаете или программируете какую-то процедуру, которая делает это автоматически, но уже реализованная версия может оказаться очень кстати. - person DainisZ; 13.09.2010

Пакет rms: Regression Modeling Strategies содержит fastbw() именно то, что тебе нужно. Есть даже параметр для переключения с AIC на исключение на основе p-значения.

person Chris    schedule 02.12.2011

Если вы просто пытаетесь получить лучшую прогностическую модель, то, возможно, это не имеет большого значения, но для всего остального не беспокойтесь о подобном выборе модели. Это неверно.

Используйте методы сжатия, такие как регрессия гребня (например, в lm.ridge() в пакете MASS), лассо или эластичная сеть (комбинация ограничений гребня и лассо). Из них только лассо и эластичная сетка будут выполнять некоторую форму выбора модели, то есть заставлять коэффициенты некоторых ковариат равняться нулю.

См. Раздел «Регуляризация и сжатие» в представлении задач Машинное обучение на CRAN .

person Gavin Simpson    schedule 21.09.2010

Как упоминал Гэвин Симпсон, функция fastbw из пакета rms может использоваться для выбора переменных с помощью p-значения. Беллоу является примером, использующим пример Джорджа Донтаса. Используйте опцию rule='p', чтобы выбрать критерий p-значения.

require(rms)
model1 <- ols(Ozone ~ Temp * Wind * Solar.R, data=airquality)
model2 <- fastbw(fit=model1, rule="p", sls=0.05)
model2
person fhernanb    schedule 22.11.2018
comment
В тексте вы имели в виду пакет rms. Также существует пакет rsm, так что это может вызвать путаницу. - person Russ Lenth; 23.11.2018
comment
Спасибо rvl за разъяснения. Я починил это. - person fhernanb; 23.11.2018