9

我有一个包含 1000 个观察值和 76 个变量的数据集,其中大约 20 个是分类变量。我想在整个数据集上使用 LASSO。我知道通过 lars 或 glmnet 在 LASSO 中使用因子变量并不能真正起作用,但是变量太多了,并且它们可以采用太多不同的无序值来合理地对它们进行数字重新编码。

在这种情况下可以使用 LASSO 吗?我该怎么做呢?创建预测变量矩阵会产生以下响应:

hdy<-as.numeric(housingData2[,75])
hdx<-as.matrix(housingData2[,-75])
model.lasso <- lars(hdx, hdy)
Error in one %*% x : requires numeric/complex matrix/vector arguments

我意识到其他方法可能更容易或更合适,但挑战实际上是使用 lars 或 glmnet 来做到这一点,所以如果可能的话,我将不胜感激任何想法或反馈。

谢谢,

4

2 回答 2

6

这里的其他答案指出了将分类因素重新编码为虚拟变量的方法。根据您的应用程序,它可能不是一个很好的解决方案。如果你只关心预测,那么这可能没问题,而且 Flo.P 提供的方法应该没问题。LASSO 会为您找到一组有用的变量,而且您可能不会过度拟合。

但是,如果您有兴趣解释您的模型或在事后讨论哪些因素很重要,那么您就处于一个奇怪的位置。model.matrix 本身采用的默认编码有非常具体的解释。model.matrix 使用所谓的“虚拟编码”。(我记得将其作为“参考编码”学习;请参见此处以获取摘要。)这意味着如果包含其中一个虚拟变量,您的模型现在有一个参数,其解释是“该因子的一个水平与任意一个水平之间的差异选择了该因素的其他水平”。也许没有选择该因素的其他假人。您可能还会发现,如果因子水平的顺序发生变化,您最终会得到不同的模型。

有一些方法可以解决这个问题,但我不会将某些东西粘在一起,而是尝试使用组套索。基于上面 Flo.P 的代码:

install.packages("gglasso")
library(gglasso)


create_factor <- function(nb_lvl, n= 100 ){
  factor(sample(letters[1:nb_lvl],n, replace = TRUE))}

df <- data.frame(var1 = create_factor(5), 
                 var2 = create_factor(5), 
                 var3 = create_factor(5), 
                 var4 = create_factor(5),
                 var5 = rnorm(100),
                 y = rnorm(100))

y <- df$y
x <- model.matrix( ~ ., dplyr::select(df, -y))[, -1]
groups <- c(rep(1:4, each = 4), 5)
fit <- gglasso(x = x, y = y, group = groups, lambda = 1)
fit$beta

因此,由于我们没有指定因子(var1、var2 等)与 y 之间的关系,因此 LASSO 做得很好,并将所有系数设置为 0,除非应用了最小量的正则化。您可以使用 lambda(调整参数)的值,或者将选项留空,该函数将为您选择一个范围。

于 2018-06-29T18:07:26.943 回答
2

您可以使用model.matrix.

我创建了一个data.frame。y 是目标变量。

create_factor <- function(nb_lvl, n= 100 ){
  factor(sample(letters[1:nb_lvl],n, replace = TRUE))}

df <- data.frame(var1 = create_factor(5), 
           var2 = create_factor(5), 
           var3 = create_factor(5), 
           var4 = create_factor(5),
           var5 = rnorm(100),
           y = create_factor(2))


    # var1 var2 var3 var4        var5   y
    # 1    a    c    c    b -0.58655607 b
    # 2    d    a    e    a  0.52151994 a
    # 3    a    b    d    a -0.04792142 b
    # 4    d    a    a    d -0.41754957 b
    # 5    a    d    e    e -0.29887004 a

选择所有因子变量。我使用dplyr::select_if然后解析变量名称来获得一个表达式y ~ var1 + var2 +var3 +var4

library(dplyr)
library(stringr)
library(glmnet)
vars_name <- df %>% 
  select(-y) %>% 
  select_if(is.factor) %>% 
  colnames() %>% 
  str_c(collapse = "+") 

model_string <- paste("y  ~",vars_name )

用 . 创建虚拟变量model.matrix。不要忘记将as.formula字符强制转换为公式。

 x_train <- model.matrix(as.formula(model_string), df)

适合您的模型。

 lasso_model <- cv.glmnet(x=x_train,y = df$y, family = "binomial", alpha=1, nfolds=10)

代码可以简化。但想法就在这里。

于 2017-10-21T20:17:53.073 回答