glmnet - 变量重要性?

10
我正在使用glmnet程序包进行LASSO回归。是否有一种方法可以获取所选个别变量的重要性?我考虑通过coef(...)命令获得的系数进行排名(即,离零越远,变量越重要)。这样做是否有效?谢谢您的帮助!
cvfit = cv.glmnet(x, y, family = "binomial")
coef(cvfit, s = "lambda.min")

## 21 x 1 sparse Matrix of class "dgCMatrix"
##                    1
## (Intercept)  0.14936
## V1           1.32975
## V2           .      
## V3           0.69096
## V4           .      
## V5          -0.83123
## V6           0.53670
## V7           0.02005
## V8           0.33194
## V9           .      
## V10          .      
## V11          0.16239
## V12          .      
## V13          .      
## V14         -1.07081
## V15          .      
## V16          .      
## V17          .      
## V18          .      
## V19          .      
## V20         -1.04341

glmnet会对输入变量进行缩放,因此在某种意义上,您选择具有最高“缩放效果”的变量。这在某种程度上是有道理的,实际上有一些论文试图解决这个特定的问题(还有Hastie和Tibshirani的最新书籍也讨论了这个问题)。然而,这确实是一个适合在StackExchange上提问的问题。 - ekstroem
3个回答

10
这是在caret包中的操作方法。
总结一下,你可以取最终系数的绝对值并进行排名。排名后的系数就是变量重要性。
若要查看源代码,您可以键入:
caret::getModelInfo("glmnet")$glmnet$varImp

如果您不想使用 caret 包,您可以运行以下代码,它应该可以正常工作。

varImp <- function(object, lambda = NULL, ...) {

  ## skipping a few lines

  beta <- predict(object, s = lambda, type = "coef")
  if(is.list(beta)) {
    out <- do.call("cbind", lapply(beta, function(x) x[,1]))
    out <- as.data.frame(out, stringsAsFactors = TRUE)
  } else out <- data.frame(Overall = beta[,1])
  out <- abs(out[rownames(out) != "(Intercept)",,drop = FALSE])
  out
}

最后,使用你的匹配调用该函数。
varImp(cvfit, lambda = cvfit$lambda.min)

2
我认为glmnet包生成的系数是非标准化的。 - Josh
@Boxuan 感谢您提供用于计算 glmnet 模型的 varImp 代码。但是,变量重要性值超过了1。但是当我们使用 caret 包中的 varImp 时,它总是在0-1范围内。您能否对此做出回应? - UseR10085
@BappaDas 能否分享一个可重现的例子?我的代码几乎与原始的 caret 代码相同,所以我不明白为什么会有差异。 - Boxuan
@Boxuan 请访问此问题,您将找到一个可重现的示例。 - UseR10085
当我尝试运行这段代码时,我收到了错误信息“no applicable method for varImp applied to an object of class "cv.glmnet"”。 - Mistakamikaze
默认情况下,varImp将所有重要性值缩放在1到100之间。你可以设置scale=F来禁止这种缩放。 - Alpha Bravo

9

2

使用cv.glmnet对象的内容创建有序系数列表非常简单...

coefList <- coef(cv.glmnet.MOD, s='lambda.1se')
coefList <- data.frame(coefList@Dimnames[[1]][coefList@i+1],coefList@x)
names(coefList) <- c('var','val')

coefList %>%
  arrange(-abs(val)) %>%
  print(.,n=25)

注意:正如其他帖子中所评论的那样...为了获得逐一比较,您需要在建模步骤之前对数字变量进行缩放/标准化...否则,一个具有非常小范围(0到1)的变量可能会被分配一个大系数值,当它与具有非常大范围(-10000到10000)的变量一起放置在模型中时,这将意味着您的系数值比较不是相对的,因此在大多数情况下是没有意义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接