R中glmnet模型变重要性计算的不成熟性

R中glmnet模型变重要性计算的不成熟性,r,r-caret,glmnet,vip,R,R Caret,Glmnet,Vip,我想计算R中glmnet模型的变量重要性。我使用glmnet包来拟合弹性网络模型,如 library(glmnet) library(caret) library(vip) data_y <- as.vector(mtcars$mpg) data_x <- as.matrix(mtcars[-1]) fit.glmnet <- glmnet(data_x, data_y, family="gaussian") set.seed(123) cvfit.g

我想计算R中glmnet模型的变量重要性。我使用
glmnet
包来拟合弹性网络模型,如

library(glmnet)
library(caret)
library(vip)

data_y <- as.vector(mtcars$mpg)
data_x <- as.matrix(mtcars[-1])

fit.glmnet <- glmnet(data_x, data_y, family="gaussian")

set.seed(123)
cvfit.glmnet = cv.glmnet(data_x, data_y, standardize=T)
cvfit.glmnet$lambda.min
coef(cvfit.glmnet, s = "lambda.min")
这让我回过神来

># A tibble: 10 x 3
   Variable Importance Sign 
   <chr>         <dbl> <chr>
 1 cyl         -0.886  NEG  
 2 disp         0      NEG  
 3 hp          -0.0117 NEG  
 4 drat         0      NEG  
 5 wt          -2.71   NEG  
 6 qsec         0      NEG  
 7 vs           0      NEG  
 8 am           0      NEG  
 9 gear         0      NEG  
10 carb         0      NEG 
虽然自定义函数的输出不包含负值,但其变化范围在0-1或0-100%之间


我知道
caret
软件包有
varImp
函数,该函数提供0-100%之间的变量重要性。但是我想为
cv.glmnet
对象实现同样的功能,而不是
caret::train
对象。如何实现
cv.glmnet
对象的变量重要性相似
caret
包?

问题是如何获得介于0-100%之间的glmnet变量重要性

如果希望根据系数大小以特定(通常是最佳)惩罚分配重要性。如果这些系数是基于标准化变量(glmnet中的默认值)导出的,则系数可以简单地缩放到0-1范围:

略加修改的函数如下所示:

varImp <- function(object, lambda = NULL, ...) {
  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)
  } else out <- data.frame(Overall = beta[,1])
  out <- abs(out[rownames(out) != "(Intercept)",,drop = FALSE])
  out <- out/max(out)
  out[order(out$Overall, decreasing = TRUE),,drop=FALSE]
}

为glmnet模型分配变量重要性的另一种方法是根据包含惩罚对变量进行评分——如果以较高惩罚排除变量,则变量更为重要。这种方法将在mlr3包中实施:在某一点上

如果变量在某个λ上具有更高的系数,或者如果其系数在更高的L1惩罚下达到0,您会说变量更重要吗?我认为在某个λ上具有更高系数的变量,更重要。为什么不调用
vip::vi_model(cvfit.glmnet,s=cvfit.glmnet$lambda.min)
?与调用
varImp(cvfit.glmnet,lambda=cvfit.glmnet$lambda.min)中一样
。我得到了相同的值,但差异
varImp
返回了系数的绝对值。即使使用了
vip::vi_模型(cvfit.glmnet,s=cvfit.glmnet$lambda.min)
,我只得到了不同的结果。你能用你得到的结果更新这个问题吗?非常感谢,您能提供您提到的使用
mlr3
包的另一种方法吗?看起来我错了,它还没有实现:好的,函数
varImp
基本上是从
caret
包中获取的。虽然我们使用
caret
package实现它,但是当我在问题中提到使用它时,它不提供缩放的重要性。你能告诉我为什么会发生这种情况吗?似乎对varImp函数的输出进行了额外的处理,在该函数中,对于所有在插入符号中有重要位置的学习者,它被缩放到0-1范围。考虑这些例子:<代码> CART::VALIMP(TestOrthCyrasCVY模型,lambda=0.007)和<代码> CART::VARIMP(TestOrthCythCVMask$FialMalm,lambda=0.007)< /Cord> >如果你在Gimple模型上调用它,你会得到不重要的重要性,而如果你调用这个火车对象,你会变得更重要。您可以通过
插入符号:::varImp.train
#Using function provided in this example
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)
  } else out <- data.frame(Overall = beta[,1])
  out <- abs(out[rownames(out) != "(Intercept)",,drop = FALSE])
  out
}

varImp(cvfit.glmnet, lambda = cvfit.glmnet$lambda.min)
        Overall
cyl  0.88608541
disp 0.00000000
hp   0.01168438
drat 0.00000000
wt   2.70814703
qsec 0.00000000
vs   0.00000000
am   0.00000000
gear 0.00000000
carb 0.00000000
varImp <- function(object, lambda = NULL, ...) {
  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)
  } else out <- data.frame(Overall = beta[,1])
  out <- abs(out[rownames(out) != "(Intercept)",,drop = FALSE])
  out <- out/max(out)
  out[order(out$Overall, decreasing = TRUE),,drop=FALSE]
}
varImp(cvfit.glmnet, lambda = cvfit.glmnet$lambda.min)
#output
         Overall
wt   1.000000000
cyl  0.320796270
am   0.004840186
hp   0.004605913
disp 0.000000000
drat 0.000000000
qsec 0.000000000
vs   0.000000000
gear 0.000000000
carb 0.000000000