R中glmnet模型变量重要性计算的差异
Discripencies in variable importance calculation for glmnet model in R
我想计算 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")
然后我使用 vip
包来获得可变的重要性作为
#Using vip package
vip::vi_model(cvfit.glmnet, s = cvfit.glmnet$fit$lambda)
哪个returns我
># 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% 之间变化。
然后我尝试了这个 answer
的自定义函数
#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)
它returns我跟着输出
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
虽然自定义函数的输出不包含负值,但它确实在 0-1 或 0-100% 之间变化。
我知道 caret
包有 varImp
功能,它给出了 0-100% 之间的变量重要性。但是我想为 cv.glmnet
对象而不是 caret::train
对象实现同样的事情。如何为 cv.glmnet
对象实现 alike 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]
}
使用问题中的例子:
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
另一种为 glmnet 模型分配变量重要性的方法是根据包含的惩罚对变量进行评分 - 如果以更高的惩罚排除变量,则变量更重要。这种方法将在 mlr3 包中实现:https://github.com/mlr-org/mlr3learners/issues/28 at some point
我想计算 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")
然后我使用 vip
包来获得可变的重要性作为
#Using vip package
vip::vi_model(cvfit.glmnet, s = cvfit.glmnet$fit$lambda)
哪个returns我
># 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% 之间变化。
然后我尝试了这个 answer
的自定义函数#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)
它returns我跟着输出
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
虽然自定义函数的输出不包含负值,但它确实在 0-1 或 0-100% 之间变化。
我知道 caret
包有 varImp
功能,它给出了 0-100% 之间的变量重要性。但是我想为 cv.glmnet
对象而不是 caret::train
对象实现同样的事情。如何为 cv.glmnet
对象实现 alike 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]
}
使用问题中的例子:
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
另一种为 glmnet 模型分配变量重要性的方法是根据包含的惩罚对变量进行评分 - 如果以更高的惩罚排除变量,则变量更重要。这种方法将在 mlr3 包中实现:https://github.com/mlr-org/mlr3learners/issues/28 at some point